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是其中比较常见的一款。通过接口可以成功返回数据,但是数据的格式有一些问题。文章对这些问题的解决进行了细致地阐述。

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


参考资料:

相关推荐
苹果醋326 分钟前
SpringBoot快速入门
java·运维·spring boot·mysql·nginx
皓木.1 小时前
(自用)配置文件优先级、SpringBoot原理、Maven私服
java·spring boot·后端
我自飞扬临天下1 小时前
Mybatis-Plus快速入门
数据库·mybatis-plus
秋恬意1 小时前
什么是MyBatis
mybatis
CodeChampion1 小时前
60.基于SSM的个人网站的设计与实现(项目 + 论文)
java·vue.js·mysql·spring·elementui·node.js·mybatis
i7i8i9com1 小时前
java 1.8+springboot文件上传+vue3+ts+antdv
java·spring boot·后端
寻找沙漠的人1 小时前
JavaEE 导读与环境配置
java·spring boot·java-ee
coding侠客2 小时前
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘
java·spring boot·后端
武昌库里写JAVA3 小时前
使用React Strict DOM改善React生态系统
数据结构·vue.js·spring boot·算法·课程设计