SpringBoot速通(实战教学)

框架、Spring、SpringBoot

框架:简单来说就是写好的东西的集合;

Spring框架:管理对象的创建和使用,核心是通过容器(IOC)管理对象

缺点:使用比较繁琐

SpringBoot框架:核心是约定大于配置。内嵌了Tomcat服务器。(注解代替配置文件)

上图中直接使用Component注解就在容器中创建了类对象。

创建SpringBoot项目

首先下载好JDK和IDEA。

这里的依赖可以先不选择,后续在pom.xml文件中自行配置。

创建成功后如上图,这里我们将Maven源换成阿里源。

上图所示就是配置成功。

蓝色选中部分可以删掉。

application.properties是SpringBoot项目中的配置文件,用于配置对象相关参数,例如定义数据库的账户名、密码、项目端口号等。yml格式现在更为主流,这里我们直接修改其后缀名。

SpringBoot整合SpringMvc实现第一个api接口

要使用SpringMvc,先在pom.xml文件中添加依赖。

第三项为新添加项,刷新后即可正常使用。

为什么这个依赖没有版本号?因为当前项目的父项目的父项目使用了dependencyManagement进行管理,父pom统一管理子模块依赖版本。

使用SpringMVC的话直接使用注解即可。

@Controller和@RestController区别

Controller:返回页面(HTML、视图),如果要返回JSON,必须手动加@ResponseBody。不适用于前后端分离系统。

RestController:直接返回数据 (JSON / 字符串 / XML),自动给所有方法加上 @ResponseBody,不会返回页面,只返回接口数据。适用于前后端分离系统。

示例

java 复制代码
@Controller
public class UserController {

    // 1. 返回页面(templates/index.html)
    @GetMapping("/index")
    public String index() {
        return "index"; // 找页面
    }

    // 2. 返回JSON → 必须加 @ResponseBody
    @GetMapping("/user")
    @ResponseBody
    public User getUser() {
        return new User();
    }
}
java 复制代码
@RestController // 自带 @ResponseBody
public class UserApiController {

    // 直接返回 JSON,不用加任何注解
    @GetMapping("/user")
    public User getUser() {
        return new User();
    }
}

实现一个简单的hello api

注意这里面@RestController和@RequestMapping缺一不可。

访问路径

bash 复制代码
localhost:8080/hello

这里如果在类上加@RequstMapping注解,则需要增加访问地址前缀,访问路径:

bash 复制代码
localhost:8080/index/hello

这是该类上的统一前缀,如果需要整个项目添加统一前缀,则在application.yml文件中添加。

访问路径:

bash 复制代码
http://localhost:8080/api/index/hello

SpringMVC实现Restfulapi请求方法

url中只写资源名称而不写动作。

Get请求

如果要反复使用@Getmapping,其所带参数需不一致,否则报错。

Post请求

post请求携带请求体,前后端分离系统一般携带JSON格式数据。

这里注解使用@RequestBody来接收Json数据。

Put请求

Delete请求

上面Json形式数据需用postman来进行测试

SpringBoot多环境配置

原本我们只有一份配置文件

现在我们变成三份配置文件,一份开发环境,一份生产环境,一份设置默认环境。

三层架构的概念

经典的Controller,Service,Mapper(Dao)三层架构

SpringBoot整合Mybatis-Plus

我们先创建一个数据库,再创建一个表。

这里我直接使用Mybatis-Plus官方文档中内容进行创建如图

之后我们在pom.xml中添加Mybatis-Plus和mysql依赖

之后在application-dev.yml文件中配置mysql

我们创建mapper目录后再补充mybatis-plus相关配置如下图

之后在启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹

之后我们添加以下lombok依赖,方便我们实体类的创建。

之后创建entity包,创建User类

之后创建Mapper接口

通一下逻辑

mybatis-plus在项目启动时会根据MapperScan注解来寻找Mapper接口并且实例化放入IOC容器中,@Autowired或@Resource从容器中获取对象。

下面是测试代码

运行时可能遇到IDEA版本、SpringBoot版本、lombok版本冲突问题,结合ai自行解决即可。

下图是运行成功截图

通过继承Mybatis-Plus通用Service实现自己的Service类

在Service包中构建下图所示结构

UserService见下图

impl中我们要实现每个方法,但是太麻烦了

我们可以直接继承Mybatis提供的实现类

具体的方法可查看Mybatis官方文档

下图是测试通过

使用SpringMvc实现增删改查api接口

我们先创建common包并创建Result类

类中代码如下

java 复制代码
package com.ittao.demo_6_2.common;

import com.sun.net.httpserver.Authenticator;
import lombok.Data;

import java.io.Serializable;

@Data
public class Result implements Serializable {
    private static final long serialVersionUID = 1L;

    private String code;
    private String message;
    private Object data;

    /**
     * 直接返回成功结果
     * @param data 获取的数据
     * @return
     */
    public static Result success(Object data) {
        return success("200", "操作成功", data);
    }

    /**
     * 自定义返回成功结果
     * @param code 状态码
     * @param message 提示信息
     * @param data 获取的数据
     * @return
     */
    public static Result success(String code, String message, Object data) {
        Result result = new Result();
        result.setCode(code);
        result.setMessage(message);
        result.setData(data);
        return result;
    }

    /**
     * 不带结果直接返回成功
     * @return
     */
    public static Result success(){
        Result result = new Result();
        result.setCode("200");
        result.setMessage("操作成功");
        return result;
    }

    /**
     * 直接返回失败信息
     * @return
     */
    public static Result error(){
        return error("400", "操作失败",null);
    }

    /**
     * 自定义返回失败信息
     * @param code 状态码
     * @param message 提示信息
     * @param data 获取的数据
     * @return
     */
    public static Result error(String code, String message, Object data) {
        Result result = new Result();
        result.setCode(code);
        result.setMessage(message);
        result.setData(data);
        return result;
    }

    /**
     * 带参数返回失败信息
     * @param message 提示信息
     * @return
     */
    public static Result error(String message){
        return error("400", message, null);
    }
}

之后我们就可以完成Controller部分内容,代码见下面

java 复制代码
package com.ittao.demo_6_2.controller;

import com.ittao.demo_6_2.common.Result;
import com.ittao.demo_6_2.entity.User;
import com.ittao.demo_6_2.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;

    /**
     * 新增用户
     * @param user
     * @return
     */
    @PostMapping
    public Result save(@RequestBody User user) {
        userService.save(user);
        return Result.success();
    }

    /**
     * 修改用户
     * @param user
     * @return
     */
    @PutMapping
    public Result update(@RequestBody User user) {
        userService.updateById(user);
        return Result.success();
    }

    /**
     * 查询单个用户
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result getOne(@PathVariable Integer id) {
        return Result.success(userService.getById(id));
    }

    /**
     * 查询所有用户
     * @return
     */
    @GetMapping
    public Result findAll() {
        return Result.success(userService.list());
    }

    /**
     * 删除用户
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        userService.removeById(id);
        return Result.success();
    }
}

之后我们用Postman测试即可

整合Mybatis-Plus分页插件并实现分页api方法

我们在userController文件中新增分页查询接口,代码如下

java 复制代码
/**
     * 分页查询
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/page")
    public Result findPage(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize){
        return Result.success(
                userService.page(new Page<>(pageNum,pageSize))
        );
    }

测试结果如下

这里我们看到设置了pageSize=2但并没有生效,这是因为在Mybatis-Plus中要使用分页功能,需要在SpringBoot中注入插件对象。

我们直接查看Mybatis-plus文档,搜索分页插件。

创建config包,创建MybatisPlusConfig类,粘贴文档中配置代码,并将启动类中MapperScan移到该类上方

接下来我们引入Maven bom依赖

之后就可以正常在配置类中进行导入。

现在可以正常分页了,见下图

拓展:@bean只是创建bean的一种方式,大部分时候我们不用 @Bean,而是用 @Service / @Controller.

① 什么时候用 @Service / @Component

自己写的类 → 直接加在类上

② 什么时候用 @Bean

别人写的类、第三方类 → 在配置类里写方法创建

  1. 接收前端请求 → `@Controller` 2. 写业务逻辑 → `@Service` 3. 操作数据库 → `@Repository` 4. 通用工具、辅助类 → `@Component`
  • 自己写的源码类 → 类上加 `@Component` 系列 - 第三方jar包里的类(你不能修改源码) → 配置类中用 `@Bean` 方法创建Bean

Mybatis-plus实现数据的自动填充

首先在数据库中创建字段

之后修改实体类,添加这两个属性。

但是代码中我们习惯用驼峰,与数据库中字段不一致,我们可以用@TableField注解添加value,并且添加fill属性。

之后我们创建Handler包并创建类

完成后重启项目即可,测试用Postman发送请求。

这里拓展一下,我们可以使用JsonFormat注解来指定自动填充的时间格式。

Mybatis-Plus实现条件查询

我们以findPage方法进行演示

测试结果如下

SpringBoot整合Redis

首先添加redis依赖和redis连接池依赖

这样引入后,启动时依赖对应的类就会往springboot容器中注入redis的操作对象------redistemplate,我们就能直接使用。但原生配置的对象不好用,我们习惯用getkey和setkey方法,因此我们需要相关配置。

我们先在配置文件中加入redis相关

之后我们创建redisConfig类,代码如下

java 复制代码
@Configuration
public class RedisConfig {
    @Value("${spring.data.redis.host}")
    private String redisHost;

    @Value("${spring.data.redis.port}")
    private int redisPort;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);
        return new LettuceConnectionFactory(config);
    }

    @SuppressWarnings("removal")
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory Factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(Factory);

        //设置key和hashKey使用字符串序列化
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());

        //设置Jackson2JsonRedisSerializer作为value序列化方式
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        mapper.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.PROPERTY
        );

        jackson2JsonRedisSerializer.setObjectMapper(mapper);

        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        return template;
    }
}

之后创建util包,并创建RedisUtil工具类。代码如下

java 复制代码
package com.ittao.demo_6_2.util;

import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /*** 通用操作 ***/

    public boolean expire(String key, long time){
        try{
            if(time>0){
                redisTemplate.expire(key,time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public long getExpire(String key){
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }

    public boolean hasKey(String key){
        try{
            return redisTemplate.hasKey(key);
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public void del(String... keys){
        if(keys!=null && keys.length>0){
            if(keys.length==1){
                redisTemplate.delete(keys[0]);
            } else{
                redisTemplate.delete(CollectionUtils.arrayToList(keys).toString());
            }
        }
    }

    /*** String操作 ***/

    public Object get(String key){
        return key==null?null:redisTemplate.opsForValue().get(key);
    }

    public boolean set(String key, Object value){
        try{
            redisTemplate.opsForValue().set(key,value);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean set(String key, Object value, long time){
        try{
            if(time>0){
                redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECONDS);
            } else{
                set(key,value);
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public long incr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key,delta);
    }

    public long decr(String key, long delta){
        if(delta<0){
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key,-delta);
    }

    /*** Hash操作 ***/

    public Object hGet(String key, String item){
        return redisTemplate.opsForHash().get(key,item);
    }

    public Map<Object,Object> hmGet(String key){
        return redisTemplate.opsForHash().entries(key);
    }

    public boolean hmSet(String key, Map<String,Object> map){
        try{
            redisTemplate.opsForHash().putAll(key,map);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean hmSet(String key, Map<String,Object> map, long time){
        try{
            redisTemplate.opsForHash().putAll(key,map);
            if(time>0){
                expire(key,time);
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean hSet(String key, String item, Object value){
        try{
            redisTemplate.opsForHash().put(key,item,value);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean hSet(String key, String item, Object value, long time){
        try{
            redisTemplate.opsForHash().put(key,item,value);
            if(time>0){
                expire(key,time);
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public void hDel(String key, Object... item){
        redisTemplate.opsForHash().delete(key,item);
    }

    public boolean hHasKey(String key, String item){
        return redisTemplate.opsForHash().hasKey(key,item);
    }

    public double hIncr(String key, String item, double by){
        return redisTemplate.opsForHash().increment(key,item,by);
    }

    public double hDecr(String key, String item, double by){
        return redisTemplate.opsForHash().increment(key,item,-by);
    }

    /*** Set操作 ***/

    public Set<Object> sMembers(String key){
        return redisTemplate.opsForSet().members(key);
    }

    public boolean sHasKey(String key, Object value){
        return redisTemplate.opsForSet().isMember(key,value);
    }

    public long sSet(String key, Object... values){
        try{
            return redisTemplate.opsForSet().add(key,values);
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    public long sSet(String key, long time, Object... values){
        try{
            Long count = redisTemplate.opsForSet().add(key,values);
            if(time>0){
                expire(key,time);
            }
            return count;
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    public long sGetSetSize(String key){
        try{
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    public long setRemove(String key, Object... values){
        try{
            Long count = redisTemplate.opsForSet().remove(key,values);
            return count;
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    /*** List操作 ***/

    public List<Object> lGet(String key, long start, long end){
        try{
            return redisTemplate.opsForList().range(key,start,end);
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    public long lGetListSize(String key){
        try{
            return redisTemplate.opsForList().size(key);
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    public Object lGetIndex(String key, long index){
        try{
            return redisTemplate.opsForList().index(key,index);
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    public boolean lSet(String key, Object value){
        try{
            redisTemplate.opsForList().rightPush(key,value);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean lSet(String key, Object value, long time){
        try{
            redisTemplate.opsForList().rightPush(key,value);
            if(time>0){
                expire(key,time);
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean lSetAll(String key, List<Object> value){
        try{
            redisTemplate.opsForList().rightPushAll(key,value);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean lSetAll(String key, List<Object> value, long time){
        try{
            redisTemplate.opsForList().rightPushAll(key,value);
            if(time>0){
                expire(key,time);
            }
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean lUpdateIndex(String key, long index, Object value){
        try{
            redisTemplate.opsForList().set(key,index,value);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public long lRemove(String key, long count, Object value){
        try{
            Long remove = redisTemplate.opsForList().remove(key,count,value);
            return remove;
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    /*** ZSet操作 ***/

    public boolean zSet(String key, Object value, double score){
        try{
            redisTemplate.opsForZSet().add(key,value,score);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean zSet(String key, Object value, double score, long time){
        try{
            Boolean result = redisTemplate.opsForZSet().add(key,value,score);
            if(time>0){
                expire(key,time);
            }
            return result;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public Set<Object> zGet(String key, double min, double max){
        try{
            return redisTemplate.opsForZSet().rangeByScore(key,min,max);
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    public long zRemove(String key, Object... values){
        try{
            Long count = redisTemplate.opsForZSet().remove(key,values);
            return count;
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    /*** 原子操作 ***/

    public boolean setNx(String key, Object value){
        try{
            return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key,value));
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean setNx(String key, Object value, long time){
        try{
            Boolean result = redisTemplate.opsForValue().setIfAbsent(key,value,time,TimeUnit.SECONDS);
            return Boolean.TRUE.equals(result);
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean setXx(String key, Object value){
        try{
            return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfPresent(key,value));
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public boolean setXx(String key, Object value, long time){
        try{
            Boolean result = redisTemplate.opsForValue().setIfPresent(key,value,time,TimeUnit.SECONDS);
            return Boolean.TRUE.equals(result);
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public long incrByAtomic(String key, long delta){
        try{
            return redisTemplate.opsForValue().increment(key,delta);
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    public double incrByFloat(String key, double delta){
        try{
            return redisTemplate.opsForValue().increment(key,delta);
        } catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    public boolean append(String key, String value){
        try{
            redisTemplate.opsForValue().append(key,value);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
}

之后我们用navacat连接上redis,去测试类进行测试。

跑通后即可看到数据

相关推荐
云絮.1 小时前
增删改查操作
java·开发语言
阿坤带你走近大数据1 小时前
Linux中管道符的作用
java·linux·服务器
码不停蹄的玄黓2 小时前
Spring Boot 实现过滤器(Filter)三种常用方式
java·spring boot·后端
dualven_in_csdn2 小时前
一键起飞调用示例
android·java·javascript
TPBoreas2 小时前
AQS 是啥
java·开发语言
宋哥转AI2 小时前
@Tool写了但tools/list为空?Spring AI MCP Server注册的两种路径和四个坑
java·agent·mcp
旧物有情2 小时前
C#异步编程
网络·rpc·c#
兰令水2 小时前
leecodecode【树形DP】【2026.6.11打卡-java版本】
java·算法·深度优先
骑士雄师3 小时前
19.3 langgraph的工作节点和路由函数
java·前端·数据库