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,去测试类进行测试。

跑通后即可看到数据

相关推荐
咩咩啃树皮12 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
鱟鲥鳚12 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
大模型码小白14 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司14 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地15 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415915 小时前
TCP超时重传机制是为了解决什么问题?
java
二宝哥16 小时前
CentOS 7.9 系统下 Redis 5.0.4 单机安装与源码编译安装指南
redis·centos
莫逸风18 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
隔窗听雨眠18 小时前
Spring Boot在云原生时代的编程范式革新研究
spring boot·后端·云原生
z1234567898618 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程