Spring Boot 集成MyBatis-Plus

文章目录

    • 一、背景说明
    • 二、集成过程
      • [2.1 引入 maven 依赖](#2.1 引入 maven 依赖)
      • [2.2 增加属性配置](#2.2 增加属性配置)
      • [2.3 自动配置类](#2.3 自动配置类)
    • 三、验证集成
      • [3.1 控制器](#3.1 控制器)
      • [3.2 服务类](#3.2 服务类)
      • [3.3 Mapper接口类](#3.3 Mapper接口类)
      • [3.4 实体类](#3.4 实体类)
      • [3.4 不要忘记XML文件](#3.4 不要忘记XML文件)
      • [3.5 发起请求](#3.5 发起请求)
    • 四、技巧拓展
      • [4.1 如何打印sql语句?](#4.1 如何打印sql语句?)
      • [4.2 如何对参数增加非空验证?](#4.2 如何对参数增加非空验证?)
      • [4.3 如何查看 Maven 依赖?](#4.3 如何查看 Maven 依赖?)
      • [4.3 如何解决时间格式问题?](#4.3 如何解决时间格式问题?)
      • [4.4 如何快速增加 `serialVersionUID` 属性?](#4.4 如何快速增加 serialVersionUID 属性?)
    • [五、总 结](#五、总 结)

一、背景说明

大部分的项目都需要进行数据的持久化,所以必然会使用到数据库。而关系型数据库是其中比较常见的数据库类型。目前使用比较多的关系型数据库有:MySQL、PostgreSQL和Oracle等。

在古早的应用开发中,需要开发人员写许多的DAL(数据访问层)代码,需要自己管理数据库的连接与关闭,还需要自己从ResultSet中获取数据,然后再将其组装为对象。在其中会编写大量非业务代码,并且这些代码往往充满了重复。

ORM的出现解决了前面提到的一系列问题,ORM的全称是 Object Relational Mapping ,翻译为对象关系模型。这里所说的对象是指业务领域的对象,关系 则指的是关系数据库(具体而言就是数据表和字段)。

ORM可以实现自动将数据库中的表字段映射为对象的属性,其采用的方式是:使用映射元数据 来描述对象关系的映射。ORM充当了应用程序的业务逻辑层和数据库之间的桥梁。常见的ORM中间件有:Hibernate和ibatis(目前已更名为 MyBatis)。

本篇所提及的 MyBatis-PlusMyBatis 的功能进行了增强。

二、集成过程

在Spring Boot项目中集成 MyBatis-Plus 过程比较简单,大概分为三个步骤:

  • 引入maven依赖
  • 增加属性配置
  • 增加相关的自动配置类

如果不知道如何创建Spring Boot项目,可以参考以往的文章:

[Spring Boot实战] 如何快速地创建spring boot项目

2.1 引入 maven 依赖

为了使用 MyBatis-Plus,需要添加相关依赖:

xml 复制代码
 <!--mybatis-plus-->
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>${mybaits-plus.version}</version>
 </dependency>

同时因为需要数据库进行数据的存储,所以还需要添加下面的依赖(我们选择的MySQL数据库):

xml 复制代码
 <!--mysql-->
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <scope>runtime</scope>
 </dependency>

如果仅限于集成 MyBatis-Plus,这两个依赖就已经足够了。

2.2 增加属性配置

相关的属性配置到 application.yml 文件中:

yaml 复制代码
spring:
  application:
    name: "demo-api"
  datasource:
    # MySql 8.0以上版本
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 兼容以前的配置
    jdbc-url: jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&useTimezone=true&serverTimezone=GMT%2B8&allowMultiQueries=true
    url: ${spring.datasource.jdbc-url}
    username: your_username
    password: your_password

2.3 自动配置类

前面我们已经提过:ORM使用映射元数据 来描述对象关系的映射。所以我们需要对相关信息进行配置,比如:

  • 使用的是什么数据库
  • 数据库连接是什么
  • Mapper 接口文件在哪里
  • MyBatis 所依赖的XML文件到哪里去找
  • MyBatis 的 SqlSessionFactory 如何创建(依赖数据源、MyBatis插件)

Spring Boot 中的配置一般以 @Configuration 进行标识。相关代码如下:

java 复制代码
@Configuration
@MapperScan(basePackages = "com.xhm.demo.api.mapper")
public class DataSourceConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //注册乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource, MybatisPlusInterceptor interceptor) throws Exception {
        MybatisSqlSessionFactoryBean ssfb = new MybatisSqlSessionFactoryBean();
        ssfb.setDataSource(dataSource);
        ssfb.setPlugins(interceptor);
        //到哪里找xml文件
        ssfb.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/mapper/*Mapper.xml"));
        return ssfb.getObject();
    }
}

配置类的 @MapperScan(basePackages = "com.xhm.demo.api.mapper") 指定了 Mapper 接口的存放位置。

第一个 Bean 用于创建数据源,会根据相关依赖自动判断数据库类型。@ConfigurationProperties(prefix = "spring.datasource") 会将以 spring.datasource 开头的属性配置赋值给数据源对象的对应属性。

第二个 Bean 用于注册 MyBatis-Plus 的相关插件(这里暂时只注册了 分页插件和 乐观锁插件)

第三个 Bean 用于创建 SqlSessionFactory 的实例。 SqlSessionFactory 是一个接口,负责数据库Session(会话)的管理,数据库会话通俗点讲就是客户端与数据库的单次连接。其依赖下面的信息:

  • 数据源
  • MyBatis-Plus 插件
  • xml文件的存放位置(资源路径)

三、验证集成

下面是常见的三层架构的目录结构:

shell 复制代码
api
├── controller
├── dto
├── entity
├── mapper
└── service

其中最主要的目录自上而下依次是:

  • controller :控制器目录(表示层)
  • service:服务类目录(业务逻辑层)
  • mapper:DAO目录(数据访问层)

另外两个目录的作用:

  • entity:实体类目录
  • dto:数据传输对象(DTO)目录

创建对应的表:

sql 复制代码
create table t_card_puncher
(
   id                   int(10) not null auto_increment,
   name                 varchar(15) comment '打卡人姓名',
   nick                 varchar(50) comment '打卡人昵称',
   avatar               varchar(100) comment '头像',
   status               smallint(2) default 10 comment '打卡人状态(10-已保存;20-已启用;0-已作废)',
   account_id           int(10) comment '对应账号id',
   remark               varchar(500) comment '备注',
   added_by             int(10) comment '新增人id',
   added_by_name        varchar(20) comment '新增人姓名',
   added_time           datetime default CURRENT_TIMESTAMP comment '新增时间',
   last_modified_by     int(10) comment '最后修改人id',
   last_modified_by_name varchar(20) comment '最后修改人姓名',
   last_modified_time   datetime default CURRENT_TIMESTAMP comment '最后修改时间',
   last_modified_ip     varchar(50) comment '最后修改IP',
   valid                smallint(1) default 1 comment '是否有效(1-有效;0-无效)',
   primary key (id)
);

alter table t_card_puncher comment '习惯打卡人表';

依次在上面的目录中创建相关类,实现一个简单的接口。我们将按照从上而下的顺序创建相关的类。

3.1 控制器

代码清单3.1-1:

java 复制代码
// CardPuncherController.java

@RestController
@RequestMapping("/cardPuncher")
public class CardPuncherController {
    @Resource
    private CardPuncherService service;

    @PostMapping("/queryById")
    public BaseResponse<CardPuncher> queryById(@RequestBody @Valid IdRequest request){
        CardPuncher dto = service.queryCardPuncherById(request.getId());
        return BaseResponse.ok(dto);
    }
}

控制器类依赖下面三个类:

  1. IdRequest (DTO)
  2. CardPuncher (实体类)
  3. CardPuncherService (服务类--接口)

代码清单3.1-2:

java 复制代码
// IdRequest.java

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;

import java.io.Serializable;
import javax.validation.constraints.NotNull;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class IdRequest implements Serializable {

    private static final long serialVersionUID = 4111263664475615283L;
    /**
     * id
     */
    @NotNull(message = "ID不能为空!")
    private Integer id;
}

3.2 服务类

控制器一般不含任何的业务逻辑,它只是将请求委托给相关的服务类。并且为了保持依赖的松散,控制器是不直接依赖于具体类的,而是依赖于接口。

代码清单3.2-1:

java 复制代码
//打卡人服务类 :CardPuncherService.java

import com.baomidou.mybatisplus.extension.service.IService;
import com.xhm.demo.api.entity.CardPuncher;

public interface CardPuncherService extends IService<CardPuncher> {

    /**
     * 根据id查询打卡人
     *
     * @param id 打卡人id
     * @return 打卡人DTO
     */
    CardPuncher queryCardPuncherById(Integer id);
}

代码清单3.2-2,就是接口的对应实现:

java 复制代码
// 打卡人服务实现类:CardPuncherServiceImpl.java
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhm.demo.api.entity.CardPuncher;
import com.xhm.demo.api.enums.ValidEnum;
import com.xhm.demo.api.mapper.CardPuncherMapper;
import com.xhm.demo.api.service.CardPuncherService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class CardPuncherServiceImpl extends ServiceImpl<CardPuncherMapper, CardPuncher> implements CardPuncherService {

    @Override
    public CardPuncher queryCardPuncherById(Integer id) {
        LambdaQueryWrapper<CardPuncher> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(CardPuncher::getValid, ValidEnum.VALID.getCode());
        queryWrapper.eq(CardPuncher::getId, id);
        return this.getOne(queryWrapper);
    }
}

服务实现类依赖下面的类:

  1. ServiceImpl(MyBatis-Plus内置的服务实现类)
  2. CardPuncherService (服务接口类)
  3. CardPuncherMapper(Mapper接口)
  4. CardPuncher
  5. Wrappers (条件构造器

3.3 Mapper接口类

Mapper接口类比较简单,因为我们没有自定义脚本,而是调用了 ServiceImpl.getOne 方法。所以 Mapper 接口类中是没有自己的方法的。

代码清单3.3-1:

java 复制代码
// 打卡人 Mapper 接口类:CardPuncherMapper.java

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface CardPuncherMapper extends BaseMapper<CardPuncher> {

}

3.4 实体类

实体类和数据表的字段是一一对应的,所以其是一个比较重要的类。相关代码如下:

java 复制代码
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("t_card_puncher")
public class CardPuncher extends BaseEntity {
    private static final long serialVersionUID = 1L;

    /**
     * 打卡人姓名
     */
    private String name;
}

其中需要重点强调的是:

当数据库中table的名称和实体类名称不一致时,一定需要使用注解 @TableName 进行显示声明表的名称。

否则会提示相关的表不存在(例子中默认认为表名是 card_puncher,而我们的表是有前缀 t_ 的)

其中的注解 @Accessors(chain = true) 的作用如下:

被该注解修饰的类,setters方法返回的该类的实例(即this),而不是void。所以可以链式地调用setters方法。

链式调用代码如下:

java 复制代码
CardPuncher entity = new CardPuncher().setName("老书生");

上述类之间的关系如下图所示:

3.4 不要忘记XML文件

在讲自动配置类时,我们提到过需要指定xml文件的存放位置:

"classpath:/mapper/*Mapper.xml"

那么我们必须在mapper中创建对应的xml文件,否则就会报如下错误:

shell 复制代码
org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'cardPuncherController'
: Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException
: Error creating bean with name 'cardPuncherServiceImpl'
: Unsatisfied dependency expressed through field 'baseMapper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException
: Error creating bean with name 'cardPuncherMapper' defined in file
...
nested exception is java.io.FileNotFoundException: class path resource [mapper/] cannot be resolved to URL because it does not exist

主要错误信息:

java.io.FileNotFoundException: class path resource [mapper/] cannot be resolved to URL because it does not exist

XML文件(CardPuncherMapper.xml)内容如下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xhm.demo.api.mapper.CardPuncherMapper">

</mapper>

启动Spring Boot 项目,观察控制台,发现多了MyBatis的banner。并且没有任何报错信息。

移步到端点,可以发现多一个db项:

表明项目中使用了数据库,并且数据库的类型是MySQL。

3.5 发起请求

使用 Postman 发起接口请求。

因为此时表中还没有数据,所以结果如下:

插入1条数据:

sql 复制代码
insert into my_database.t_card_puncher(`name`,nick,added_by,added_by_name,last_modified_by,last_modified_by_name)
values('老书生','leon',-1,'系统',-1,'系统');

再次请求,结果如下:

可以成功查出数据。到这里 MyBatis 的集成已经初步成功了。

之所以说初步成功,是因为还有一些问题需要解决。如上图中时间格式的问题,2024-06-21T09:31:00 这种时间格式有自己的专有名词:ISO日期时间格式 / ISO 8601

还有一个问题:当Id为空时,没有返回期望的错误信息,而是报400错误:

四、技巧拓展

4.1 如何打印sql语句?

发送请求后,在项目的控制台没有出现期望的sql语句,那么该如何处理才能成功打印sql语句呢?

其实方法也很简单,在 application.yml 中添加如下配置:

yaml 复制代码
# 查看sql
logging:
  level:
    com.xhm.demo.api.mapper: debug

其中的 com.xhm.demo.api.mapper 是 Mapper 接口所在的包名。设置其日志级别为debug

打印的sql脚本如下:

shell 复制代码
2024-06-23 00:26:49.147 DEBUG 40300 --- [nio-8080-exec-6] c.x.d.a.m.CardPuncherMapper.selectOne    : ==>  Preparing: SELECT id,name,added_by,added_by_name,added_time,last_modified_by,last_modified_by_name,last_modified_time,last_modified_ip,valid FROM t_card_puncher WHERE (valid = ? AND id = ?)
2024-06-23 00:26:49.188 DEBUG 40300 --- [nio-8080-exec-6] c.x.d.a.m.CardPuncherMapper.selectOne    : ==> Parameters: 1(Integer), 1(Integer)
2024-06-23 00:26:49.226 DEBUG 40300 --- [nio-8080-exec-6] c.x.d.a.m.CardPuncherMapper.selectOne    : <==      Total: 1

脚本是出现了,但是似乎不那么完美。如果查询条件比较多,拼接起来还是比较麻烦的。有无其他办法能够查看拼接好的脚本呢?

可以试试一款IDEA插件:MyBatis Log Free

借助这款插件,可以查看完整的sql语句:

如果是第一次使用该插件,可以通过如下方式打开:

【Tools】-> 【MyBatis Log Plugin】

4.2 如何对参数增加非空验证?

非空校验不生效,有两种情况:

  1. 空条件直接传到sql中
  2. 接口返回400错误,控制台有 WARN 日志

第一种情况

如果 @NotNull注解在请求类的属性 (如IdRequest类)上。检查Controller的方法的入参是否遗漏 @Valid 注解。

如果已经增加了注解,非空校验依然没有生效,则有可能是maven依赖不完整,可能 pom 中只增加了如下依赖:

xml 复制代码
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>

有两种解决方法:

  1. 增加 hibernate-validator 依赖
    validation-api 中只定义了相关注解,具体的校验逻辑在 hibernate-validator 中。所以需要添加如下依赖:
xml 复制代码
 <!-- hibernate-validator -->
 <dependency>
     <groupId>org.hibernate.validator</groupId>
     <artifactId>hibernate-validator</artifactId>
 </dependency>
  1. 去除 validation-api 依赖,以下面的依赖进行替换:
xml 复制代码
<!--参数校验-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

第二种情况

因为没有对 MethodArgumentNotValidException 异常进行处理而导致校验信息没有返回。具体的现象是响应报文的结果如下:

所以需要增加 统一异常处理类 。相关代码如下:

java 复制代码
// exception/CommonExceptionHandler.java

@Slf4j
@ControllerAdvice
public class CommonExceptionHandler {
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public BaseResponse<?> bindMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        String traceId = MDC.get("traceId");
        StringBuilder errorMessage = new StringBuilder();
        List<FieldError> errors = ex.getBindingResult().getFieldErrors();
        for (FieldError error : errors) {
            //只取错误信息
            errorMessage.append(error.getDefaultMessage()).append(";");
        }

        errorMessage.deleteCharAt(errorMessage.length() - 1);
        log.error(String.format("traceId: %s, Exception: [%s] %s, request error, parameters invalid:%s", traceId, ex.getParameter().getParameterName(), ex, errorMessage));
        return BaseResponse.error(BaseResultCodeEnum.ERROR.getCode(), errorMessage.toString());
    }
}

BaseResponse.java代码如下:

java 复制代码
@Data
public class BaseResponse<T> implements Serializable {


    private static final long serialVersionUID = -5330932746124338859L;

    /**
     * 响应状态码
     */
    private String code;

    /**
     * 响应消息
     */
    private String message;

    /**
     * 响应数据
     */
    private T data;

    public static <K> BaseResponse<K> ok() {
        return BaseResponse.result(BaseResultCodeEnum.SUCCESS.getCode(), BaseResultCodeEnum.SUCCESS.getMessage());
    }

    public static <K> BaseResponse<K> ok(K data) {
        BaseResponse<K> response = BaseResponse.ok();
        response.setData(data);
        return response;
    }

    public static <K> BaseResponse<K> error(String message) {
        return BaseResponse.result(BaseResultCodeEnum.ERROR.getCode(), message);
    }

    public static <K> BaseResponse<K> error(String code, String message) {
        return BaseResponse.result(code, message);
    }

    public static <K> BaseResponse<K> result(String code, String message) {
        BaseResponse<K> response = new BaseResponse<>();
        response.setCode(code);
        response.setMessage(message);
        return response;
    }
}

4.3 如何查看 Maven 依赖?

有两种查看 Maven 依赖的方式:

  1. mvn dependency:tree命令
  2. 使用Idea的 Dependency Analyzer

其中第二种方式依赖 IDEA的插件: Maven Helper

第一种方式的演示:

在终端输入如下命令:

shell 复制代码
mvn dependency:tree

输出结果如下:

shell 复制代码
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building demo-api 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ demo-api ---
[INFO] com.xhm:demo-api:jar:0.0.1-SNAPSHOT
...
[INFO] +- org.projectlombok:lombok:jar:1.18.20:compile (optional)
...
[INFO] +- mysql:mysql-connector-java:jar:8.0.23:runtime
[INFO] \- org.springframework.boot:spring-boot-starter-validation:jar:2.3.10.RELEASE:compile
[INFO]    +- org.glassfish:jakarta.el:jar:3.0.3:compile
[INFO]    \- org.hibernate.validator:hibernate-validator:jar:6.1.7.Final:compile
[INFO]       +- jakarta.validation:jakarta.validation-api:jar:2.0.2:compile
[INFO]       +- org.jboss.logging:jboss-logging:jar:3.4.1.Final:compile
[INFO]       \- com.fasterxml:classmate:jar:1.5.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.018 s
[INFO] Finished at: 2024-06-25T16:12:36+08:00
[INFO] Final Memory: 26M/304M
[INFO] ------------------------------------------------------------------------

第二种方式的演示:

打开pom文件,从 Text 模式切换到 Dependency Analyzer 模式:

  • 选择 All Dependencies as Tree ,点击 "Refresh UI" 按钮
  • 收缩树形结构(全部)
  • 展开 spring-boot-starter-validation ,可以看到其依赖项。

如图所示,其依赖于 hibernate-validator,而 hibernate-validator 又依赖于 jakarta.validation-api (替换validation-api 包含注解 javax.validation.constraints.NotNull

4.3 如何解决时间格式问题?

前面我提到过接口返回的日期时间格式默认是:ISO日期时间格式。而很多时候我们需要指定的日期时间格式。如:

  • 当提到出生日期是,时间精度至少需要精确到天,在中国一般的日期格式是:2024-06-20
  • 但是当我们需要获知订单的创建时间时,可能需要这样的时间格式:2024-06-21 08:30:50

要解决这个问题,其实也比较简单,可以使用 jackson-annotation 包中的注解 @JsonFormat 对日期时间格式进行自定义。

下面使用该注解对 BaseEntity 进行功能增强:

java 复制代码
@Data
public class BaseEntity implements Serializable {
...
	/**
	 * 新增时间
	 */
	@JsonFormat(pattern = "yyyy-MM-dd")
	private LocalDateTime addedTime;
	...
	
    /**
     * 最后修改时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime lastModifiedTime;
}

这里只是为了演示的方便,生产代码不建议这样写:

直接将实体类暴露给最终用户 不是一个好的实践,因为一旦字段发生变动,就需要客户代码进行相应的调整。

普遍的做法是:引入DTO作为接口的数据载体。所以 @JsonFormat 注解也是打在DTO类上。

4.4 如何快速增加 serialVersionUID 属性?

对于可序列化的类,一般强烈建议显式声明 serialVersionUID 值。因为默认计算得到的 serialVersionUID 值可能会引发 InvalidClassException 。那么有没有什么快速的方法去完成这件事情呢?

如果你使用的是 IDEA ,可以参考下面的方法:

  • 打开 Settings 窗口,输入搜索词: serial
  • 在【Editor】-【Inspections】中找到:【Java】- 【Serializatioin issues】。
  • 然后勾选其中的 Serializable class without serialVersionUID

上面设置的作用是:如果一个类实现了Serializable接口,但是没有声明 serialVersionUID 值,就会告警。

F2 定位到告警信息后,再组合按键 Alt + Enter ,弹出上图的信息后,再按一次 Enter 后,就可以快速插入 serialVersionUID 值了。使用该方式生成的 serialVersionUID 能很好地避免重复的问题。

五、总 结

本文详细讲述了如何在Spring Boot 项目中集成 MyBatis-Plus,其中的设置和依赖都遵循最小功能集的原则。

增加集成相关的配置和依赖后,我们又创建了一个简单的接口,用于验证本次集成是否成功。其中谈到了SSM项目中基本的项目结构,相关代码都是从生产代码中抽象出来的,具有很强的参考意义。文中还以类图的形式给出了各个类之间的关系,可以帮助读者更好地理解代码结构。

接口测试时,我们使用了post工具,Postman是其中比较常见的一款。通过接口可以成功返回数据,但是数据的格式有一些问题。文章对这些问题的解决进行了细致地阐述。

最后还分享了实际开发中可能会用到的一些小技巧,希望可以启动抛砖引玉的作用。有交流意愿的小伙伴可以在评论区进行留言。


参考资料:

相关推荐
战族狼魂10 分钟前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
用键盘当武器的秋刀鱼3 小时前
springBoot统一响应类型3.5.1版本
java·spring boot·后端
小李同学_LHY4 小时前
三.微服务架构中的精妙设计:服务注册/服务发现-Eureka
java·spring boot·spring·springcloud
爱喝醋的雷达6 小时前
Spring SpringBoot 细节总结
java·spring boot·spring
嘵奇8 小时前
深入解析 Spring Boot 测试核心注解
java·spring boot·后端
技术liul9 小时前
解决Spring Boot Configuration Annotation Processor not configured
java·spring boot·后端
依旧很淡定9 小时前
14-SpringBoot3入门-MyBatis-Plus之CRUD
mybatis-plus·crud
KATA~11 小时前
解决MyBatis-Plus枚举映射错误:No enum constant问题
java·数据库·mybatis
腥臭腐朽的日子熠熠生辉12 小时前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
绝顶少年14 小时前
Spring Boot 注解:深度解析与应用场景
java·spring boot·后端