jck28 - 小柒 - spring boot3.x版本 + mybatis完整项目流程

一,导入spring boot 3.x版本的所有相关依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!-- spring结合Swagger生成API依赖,适用于spring boot3.x项目 -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.13.1</version>
        </dependency>
        <!-- mysql连接 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <!--mybatis坐标-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.16</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>
        <!-- dto实体类转换依赖-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.5.3.Final</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <!--插件设置-->
                <configuration>
                    <!--允许移动生成的文件-->
                    <verbose>true</verbose>
                    <!--启用覆盖-->
                    <overwrite>true</overwrite>
                    <!--自动生成配置 如果名字是generatorConfig.xml可以省略配置-->
                    <configurationFile>src/main/resources/generator/generatorConfig.xml</configurationFile>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.29</version>
                        <scope>runtime</scope>
                    </dependency>
                    <dependency>
                        <groupId>tk.mybatis</groupId>
                        <artifactId>mapper</artifactId>
                        <version>4.1.5</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>1.5.3.Final</version>
                        </path>
                        <!-- 这里spring3导入mapstruct时必须要加lombok,否则Result模板类会读不到-->
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.24</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

二,利用 MyBatisGenerator自动生成数据库对应的实体类及mapper接口文件

(1) 新增generator/generatorConfig.xml文件

  • 该文件路径与依赖导入配置的路径一致
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">


<!-- 配置生成器 -->
<generatorConfiguration>
    <!-- 引入配置文件 -->
    <properties resource="generator/config.properties"/>
    <!-- 一个数据库一个context 配置对象环境-->
    <!-- id="MysqlTable" :此上下文的唯一标识符。此值将用于一些错误消息。
    targetRuntime="MyBatis3Simple":为了避免生成Example相关的代码和方法。如果需要则改为Mybatis3
     defaultModelType="flat" :每个表只生成一个实体类    -->
    <context id="MysqlTable" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <!-- 配置起始与结束标识符 指明数据库的用于标记数据库对象名的符号-->
        <!-- ORACLE就是双引号,MYSQL默认是`反引号  数据库使用mysql,所以前后的分隔符都设为”`”-->
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <!--用来定义一个插件,用于扩展或者修改MBG生成的代码,不常用,可以配置0个或者多个,个数不受限制。
        只有一个Type标签,其中填插件的全限定名。
        常用的有缓存插件,序列化插件,RowBounds插件,ToString插件等。-->
        <plugin type="${mapper.plugin}">
            <property name="mappers" value="${mapper.Mapper}"/>
        </plugin>

        <!--数据库连接配置-->
        <jdbcConnection driverClass="${jdbc.driver}"
                        connectionURL="${jdbc.url}"
                        userId="${jdbc.username}"
                        password="${jdbc.password}">
        </jdbcConnection>

        <!-- javaModelGenerator - 配置生成的实体类位置 type使用XMLMAPPER,会使接口和XML完全分离。
            targetPackage:放置生成的类的包。 MyBatis Generator 将根据需要为生成的包创建文件夹
            targetProject:包所在的project下的位置,指定了将保存对象的项目和源文件夹。该目录不存在,MyBatis Generator 将不会创建该目录        -->
        <javaModelGenerator targetPackage="${java.targetPackage}" targetProject="${java.targetProject}">
            <!-- 设置一个根对象,如果设置了这个根对象,那么生成的keyClass或者recordClass会继承这个类;
            在Table的rootClass属性中可以覆盖该选项
            注意:如果在key class或者record class中有root class相同的属性,MBG就不会重新生成这些属性了,
            包括:1,属性名相同,类型相同,有相同的getter/setter方法;
            rootClass:所有实体类的父类,如果父类定义了一些字段以及对应的getter、setter方法,那么实体类中就不会再生成。必须要类的安全限定名,如com.momo.test.BasePo         -->
            <property name="rootClass"
                      value="${java.rootClass}"/>
        </javaModelGenerator>

        <!-- sqlMapGenerator:配置SQL映射生成器(Mapper.xml文件)的属性,可选且最多配置1个  配置映射位置只有两个必选属性(和实体类的差不多):
                targetPackage:生成映射文件存放的包名,可能会受到其他配置的影响。
                targetProject:指定目标targetPackage的项目路径,可以用相对路径或者绝对路径        -->
        <sqlMapGenerator targetPackage="${mapper.targetPackage}" targetProject="${mapper.targetProject}"/>
        <!-- 配置接口位置
            typetype="XMLMAPPER":接口和XML完全分离;所有方法都在XML中,接口用依赖Xml文件
            targetPackage:生成Mapper文件存放的包名,可能会受到其他配置的影响。
            targetProject:指定目标targetPackage的项目路径,可以用相对路径        -->
        <javaClientGenerator targetPackage="${java.targetMapperPackage}" targetProject="${java.targetProject}"
                             type="XMLMAPPER"/>

        <!-- table可以有多个,每个数据库中的表都可以写一个table,schema是数据库名,
        tableName表示要匹配的数据库表,也可以在tableName属性中通过使用%通配符来匹配所有数据库表,只有匹配的表才会自动生成文件 -->
        <!-- 配置数据库表 -->
        <table schema="testcase" tableName="test_case">
            <!-- generatedKey:用来指定自动生成的主键的属性。针对MySql,SQL Server等自增类型主键
                   indetity:设置为true时会被标记为indentity列,并且selectKey标签会被插入在Insert标签(order=AFTER)。
                   设置为false时selectKey会插入到Insert之前(oracal序列),默认为false.            -->
            <generatedKey column="case_id" sqlStatement="Mysql" identity="true"/>
        </table>

        <!-- 生成用户的相关类 -->
        <!--        <table schema="aitest_mini" tableName="hogwarts_test_user" domainObjectName="HogwartsTestUser" enableCountByExample="false" enableDeleteByExample="false"-->
        <!--               enableSelectByExample="false" enableUpdateByExample="false" >-->
        <!--            <generatedKey column="id" sqlStatement="Mysql" identity="true"/>-->
        <!--        </table>-->
    </context>
</generatorConfiguration>
     

(2) 新增 generator/config.properties文件

# 数据库连接配置
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.43.68:3306
jdbc.username=root
jdbc.password=123456

# mapper插件配置
mapper.plugin=tk.mybatis.mapper.generator.MapperPlugin
mapper.Mapper=com.ceshiren.spring3.common.MySqlExtensionMapper

# entity实体类路径
java.targetProject=src/main/java
# entity实体类包名
java.targetPackage=com.ceshiren.spring3.entity
# 实体类的根包名BaseEntityNew
java.rootClass=com.ceshiren.spring3.entity.BaseEntityNew

# 生成mapper.xml文件的路径
mapper.targetProject=src/main/resources
# 生成mapperXML文件的包名
mapper.targetPackage=mapper

# entity实体类对应的mapper接口文件生成路径
java.targetMapperPackage=com.ceshiren.spring3.mapper

(3) 新增对应配置文件里插件定义的文件

  • MySqlExtensionMapper文件
package com.ceshiren.spring3.common;

import tk.mybatis.mapper.common.IdsMapper;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

public interface MySqlExtensionMapper<T> extends Mapper<T>, MySqlMapper<T>, IdsMapper<T> {
}

  • BaseEntityNew实体类文件
package com.ceshiren.spring3.entity;

import java.io.Serializable;

public class BaseEntityNew implements Serializable {
    private static final long serialVersionUID = 2054813493011812469L;
}

(4) 执行插件语句,生成对应的实体类,mapper.xml文件和mapper接口文件

(5) 添加mapper扫描路径(加上MapperScan注解)

package com.ceshiren.spring3;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication()
@MapperScan("com.ceshiren.spring3.mapper")
public class Spring3Application {
    public static void main(String[] args) {
        SpringApplication.run(Spring3Application.class, args);
    }
}

三,spring配置相关数据源(application.yml文件为例)

# spring数据库连接配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.43.68/testcase
    username: root
    password: 123456
# spring boot 2.x版本,Swagger页面展示内容配置
#  mvc:
#    pathmatch:
#      matching-strategy: ANT_PATH_MATCHER

# spring boot 3.x版本的Swagger配置
springdoc:
  api-docs:
    path: /v3/api-docs
  swagger-ui:
    path: /swagger-ui.html

#mybatis连接配置
mybatis:
  configuration:
    use-actual-param-name: true
    # 查询mapper.xml文件路径
  mapper-locations: classpath:mapper/*.xml
  # 实体类的包名路径
  type-aliases-package: com.ceshiren.springtemplate.entity

四,配置接口返回相关的文件

(1)新建util包,新增接口返回Result的模板类

package com.ceshiren.springtemplate.util;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.HashMap;

@Data
@Schema(title = "Result返回模板类", description ="返回结果体封装" )
public class Result<T> implements Serializable {
    //HashMap已实现的序列化实例对象
    private static final long serialVersionUID = 1L;

    @Schema(title = "是否成功", example = "true", required = true)
    private boolean success;
    @Schema(title = "返回结果码 0 成功 1 失败", example = "1", required = true, allowableValues = "1,0")
    private int code;
    @Schema(title = "返回消息", example = "成功", allowableValues = "成功,失败" )
    private String msg;
    @Schema(title = "响应结果数据")
    private T data;

    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.setSuccess(true);
        result.setCode(ResultCode.SUCCESS);
        result.setMsg("成功");
        return result;
    }

    public static <T> Result<T> error(){
        Result<T> result = new Result<>();
        result.setSuccess(false);
        result.setCode(ResultCode.ERROR);
        result.setMsg("失败");
        result.setData((T)new HashMap<>());
        return result;
    }

    public Result<T> message(String message){
        this.setMsg(message);
        return this;
    }

    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }

    public Result<T> data(T value){
        this.setData(value);
        return this;
    }
}
  • ResultCode 接口
package com.ceshiren.springtemplate.util;

public interface ResultCode {
      static Integer SUCCESS = 0;
      static Integer ERROR = 1;
}

(2)新建exception包,新增异常处理类

package com.ceshiren.springtemplate.exception;

import com.ceshiren.springtemplate.exception.ServiceException;
import com.ceshiren.springtemplate.util.Result;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

//ControllerAdvice  AOP面向切面编程,对原来对功能没有侵入性,原来什么样子现在还是什么样子
//我只是在原来的功能的基础上给你扩展出一个功能,统一异常处理功能
//spring boot 3.x版本必须要加上Hidden注解,不然swagger-ui页面会报错
@Hidden
@RestControllerAdvice
public class GlobalExceptionHandler {

    String tips = "系统繁忙,请稍后重试";

    @ExceptionHandler({Exception.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
//    @ResponseBody
    public Result exceptionHandler(Exception e){
        //记录日志,通知运维,通知开发
        //控制台打印异常,万一出现异常调试
        e.printStackTrace();
        return Result.error().message("非业务异常 "+ tips);
    }


    //自定义ServiceException异常,是一个运行时的异常
    @ExceptionHandler({ServiceException.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result servceExceptionHandler(HttpServletRequest req, ServiceException se){
        String requestUrl = req.getRequestURI();
        String method = req.getMethod();
        se.printStackTrace();
        //前端页面展示的message异常内容
        return Result.error().message("业务异常 "+ tips
                +"RestAPI:"+method + " "+ requestUrl).code(se.getCode());
    }


    // .ArithmeticException - 计算溢出或者除数为0的异常
    @ExceptionHandler({ArithmeticException.class})
    public Result exceptionHandlerArithmetic(ArithmeticException e){
        e.printStackTrace();
        return Result.error().message("除数不能为0");
    }

}

(3)exception包下,新增自定义异常类

package com.ceshiren.springtemplate.exception;

public class ServiceException extends RuntimeException{
    /**
     * 业务错误码
     */
    private Integer code;
    /**
     * 错误提示
     */
    private String message;

    public ServiceException(String message) {
        this.message = message;
    }

    public ServiceException( String message, Integer code) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public ServiceException setCode(Integer code) {
        this.code = code;
        return this;
    }

    public String getMessage() {
        return message;
    }

    public ServiceException setMessage(String message) {
        this.message = message;
        return this;
    }
}

五,新建config包,新增swagger自定义配置信息类:

package com.ceshiren.springtemplate.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;  
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("testcase数据库接口文档")
                        .description("spring-test-api")
                        .contact(new Contact().name("demi").email("liupan0721@gmail.com"))
                        .version("1.0"));
    }
}

六, 新建service包,并新建TestCaseService接口,传参为entity包的实体类

package com.ceshiren.spring3.service;

import com.ceshiren.spring3.entity.TestCase;
import com.ceshiren.spring3.util.Result;

public interface TestCaseService {
    Result find(TestCase testCase);
    Result insert(TestCase testCase);
    Result update(TestCase testCase);
    Result delete(TestCase testCase);
}
 

七,service包下新增TestCaseService的实现类TestCaseServiceImpl

package com.ceshiren.spring3.service;

import com.ceshiren.spring3.entity.TestCase;
import com.ceshiren.spring3.mapper.TestCaseMapper;
import com.ceshiren.spring3.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import java.util.Date;
import java.util.List;

@Service
public class TestCaseServiceImpl implements TestCaseService {
    @Autowired
    private TestCaseMapper testCaseMapper;

    @Override
    public Result find(TestCase testCase) {
        List<TestCase> selectList = testCaseMapper.select(testCase);
        System.out.println(selectList);
        return Result.success().message("查询成功!").data(selectList);
    }

    @Override
    public Result insert(TestCase testCase) {
        int insert = testCaseMapper.insert(testCase);
        testCase.setCreateBy("lp");
        testCase.setCreateTime(new Date());

        return Result.success().message("插入数据成功!").data(testCase);
    }

    @Override
    public Result update(TestCase testCase) {
        Example example = new Example(TestCase.class);
        Example.Criteria criteria = example.createCriteria();
        //模糊查询
//        criteria.andLike("caseName", "%" + testCase.getCaseName() + "%");
        //完全匹配查询
        criteria.andEqualTo("caseName", testCase.getCaseName());
        //根据caseName获取查询的结果
        List<TestCase> testCases = testCaseMapper.selectByExample(example);
        System.out.println("查找结果的第一条数据:"  + testCases.get(0));
        //获取查询结果数据的唯一主键
        Integer caseId = testCases.get(0).getCaseId();
        //将唯一主键填充到testCase
        testCase.setCaseId(caseId);
        testCase.setUpdateTime(new Date());
        //更新testCase填入的caseId对应的这条数据
        testCaseMapper.updateByPrimaryKeySelective(testCase);

        return Result.success().data(testCase).message("修改成功!");
    }

    @Override
    public Result delete(TestCase testCase) {
        int deleteKey = testCaseMapper.deleteByPrimaryKey(testCase.getCaseId());
        System.out.println(deleteKey);
        return Result.success().message("删除成功!").data(testCase);
    }
}

八,在controller包下新建接口交互类CaseController,新增数据库表的增删改查接口

package com.ceshiren.spring3.controller;

import com.ceshiren.spring3.entity.TestCase;
import com.ceshiren.spring3.entity.UserDto;
import com.ceshiren.spring3.service.TestCaseService;
import com.ceshiren.spring3.service.UserService;
import com.ceshiren.spring3.util.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@Tag(name = "spring3版本请求")
public class CaseController {
    @Autowired
    UserService userService;

    @Autowired
    TestCaseService testCaseService;
    
    @Operation(description = "用户登陆")
    @PostMapping(value = "/user/login", produces = "application/json")
    Result login(@RequestBody UserDto userDto) {
        return userService.login(userDto);
    }


    @Operation(description = "查询用例数据")
    @PostMapping(value = "/selectOne", produces = "application/json")
    Result selectCase(@RequestBody TestCase testCase) {
        return testCaseService.find(testCase);
    }

    @Operation(description = "插入单条数据")
    @PostMapping(value = "/insertOne", produces = "application/json")
    Result insertCase(@RequestBody TestCase testCase) {
        return testCaseService.insert(testCase);
    }

    @Operation(description = "修改数据")
    @PostMapping(value = "/update", produces = "application/json")
    Result updateCase(@RequestBody TestCase testCase) {
        return testCaseService.update(testCase);
    }

    @Operation(description = "删除数据")
    @DeleteMapping(value = "/remove", produces = "application/json")
    Result deleteById(@RequestBody TestCase testCase) {
        return testCaseService.delete(testCase);
    }

}

九,启动项目成功后,打开swagger页面,调用接口验证正常

十,后端架构优化

  • 使用mapstruct实现dto实体类与entity实体类的转换,具体导入依赖见最开始的导入依赖

(1)在dto包下新建与客户端交互的实体类,dto实体类字段要少于entity的实体类

package com.ceshiren.spring3.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import javax.persistence.Column;

@Schema(title = "testcase_dto实体类")
public class TestCaseDto {
    /**
     * 用例名称
     */
    @Column(name = "case_name")
    private String caseName;

    /**
     * 一级模块
     */
    @Column(name = "first_module")
    private String firstModule;

    /**
     * 二级模块
     */
    @Column(name = "second_module")
    private String secondModule;

    /**
     * 是否基线用例(0 -否, 1 - 是)
     */
    @Schema(title = "是否基线用例",allowableValues = "0,1",defaultValue = "0")
    @Column(name = "base_case")
    private Integer baseCase;

    /**
     * 接口请求url
     */
    @Column(name = "request_url")
    private String requestUrl;

    /**
     * 请求body
     */
    @Column(name = "request_body")
    private String requestBody;

    /**
     * 测试环境分组
     */
    private String environment;

    public String getCaseName() {
        return caseName;
    }

    public void setCaseName(String caseName) {
        this.caseName = caseName;
    }

    public String getFirstModule() {
        return firstModule;
    }

    public void setFirstModule(String firstModule) {
        this.firstModule = firstModule;
    }

    public String getSecondModule() {
        return secondModule;
    }

    public void setSecondModule(String secondModule) {
        this.secondModule = secondModule;
    }

    public Integer getBaseCase() {
        return baseCase;
    }

    public void setBaseCase(Integer baseCase) {
        this.baseCase = baseCase;
    }

    public String getRequestUrl() {
        return requestUrl;
    }

    public void setRequestUrl(String requestUrl) {
        this.requestUrl = requestUrl;
    }

    public String getRequestBody() {
        return requestBody;
    }

    public void setRequestBody(String requestBody) {
        this.requestBody = requestBody;
    }

    public String getEnvironment() {
        return environment;
    }

    public void setEnvironment(String environment) {
        this.environment = environment;
    }
}

(2)service层定义接口TestCaseDtoService,接口传参为TestCaseDto

package com.ceshiren.spring3.service;

import com.ceshiren.spring3.dto.TestCaseDto;
import com.ceshiren.spring3.util.Result;

public interface TestCaseDtoService {
    Result find(TestCaseDto testCaseDto);
    Result insert(TestCaseDto testCaseDto);
    Result update(TestCaseDto testCaseDto);
    Result delete(TestCaseDto testCaseDto);
}

(3)新建转换接口,将dto实体类转换成entity实体类

package com.ceshiren.spring3.converter;

import com.ceshiren.spring3.dto.TestCaseDto;
import com.ceshiren.spring3.entity.TestCase;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

@Mapper(componentModel = "spring")
public interface TestCaseDtoConverter {
    //TestCaseDto实体类转换成TestCase实体类,返回值为TestCase

    @Mappings({
            //target是dto实体类对应的字段,source是entity实体类对应的字段
            @Mapping(target = "caseName", source = "caseName"),
            @Mapping(target = "firstModule", source = "firstModule"),
            @Mapping(target = "secondModule", source = "secondModule"),
            @Mapping(target = "baseCase", source = "baseCase"),
            @Mapping(target = "requestUrl", source = "requestUrl"),
            @Mapping(target = "requestBody", source = "requestBody"),
            @Mapping(target = "environment", source = "environment")
    })

    TestCase dtoToEntity(TestCaseDto testCaseDto);

}

(4)service层新增对应的实现类TestCaseDtoServiceImpl

package com.ceshiren.spring3.service;

import com.ceshiren.spring3.converter.TestCaseDtoConverter;
import com.ceshiren.spring3.dto.TestCaseDto;
import com.ceshiren.spring3.entity.TestCase;
import com.ceshiren.spring3.mapper.TestCaseMapper;
import com.ceshiren.spring3.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import java.util.Date;
import java.util.List;

@Service
public class TestCaseDtoServiceImpl implements TestCaseDtoService {
    @Autowired
    private TestCaseMapper testCaseMapper;

    @Autowired
    TestCaseDtoConverter testCaseDtoConverter;

    @Override
    public Result find(TestCaseDto testCaseDto) {
        TestCase testCase = testCaseDtoConverter.dtoToEntity(testCaseDto);
        List<TestCase> selectList = testCaseMapper.select(testCase);
        System.out.println(selectList);
        return Result.success().message("查询成功!").data(selectList);
    }

    @Override
    public Result insert(TestCaseDto testCaseDto) {
        TestCase testCase = testCaseDtoConverter.dtoToEntity(testCaseDto);
        testCaseMapper.insert(testCase);
        testCase.setCreateBy("lp");
        testCase.setCreateTime(new Date());
        return Result.success().message("插入数据成功!").data(testCase);
    }

    @Override
    public Result update(TestCaseDto testCaseDto) {
        TestCase testCase = testCaseDtoConverter.dtoToEntity(testCaseDto);
        Example example = new Example(TestCase.class);
        Example.Criteria criteria = example.createCriteria();
        //模糊查询
//        criteria.andLike("caseName", "%" + testCase.getCaseName() + "%");
        //完全匹配查询
        criteria.andEqualTo("caseName", testCase.getCaseName());
        //根据caseName获取查询的结果
        List<TestCase> testCases = testCaseMapper.selectByExample(example);
        System.out.println("查找结果的第一条数据:"  + testCases.get(0));
        //获取查询结果数据的唯一主键
        Integer caseId = testCases.get(0).getCaseId();
        //将唯一主键填充到testCase
        testCase.setCaseId(caseId);
        testCase.setUpdateBy("tmp");
        testCase.setUpdateTime(new Date());
        //更新testCase填入的caseId对应的这条数据
        testCaseMapper.updateByPrimaryKeySelective(testCase);

        return Result.success().data(testCase).message("修改成功!");
    }

    @Override
    public Result delete(TestCaseDto testCaseDto) {
        TestCase testCase = testCaseDtoConverter.dtoToEntity(testCaseDto);
        int deleteOne = testCaseMapper.delete(testCase);
        System.out.println(deleteOne);
        return Result.success().message("删除成功!").data(testCase);
    }
}

(5)controller层修改对应接口的传参为TestCaseDto

package com.ceshiren.spring3.controller;

import com.ceshiren.spring3.dto.TestCaseDto;
import com.ceshiren.spring3.service.TestCaseService;
import com.ceshiren.spring3.util.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@Tag(name = "spring3版本请求")
public class CaseController {
    @Autowired
    TestCaseService testCaseService;

    @Operation(description = "查询用例数据")
    @PostMapping(value = "/selectOne", produces = "application/json")
    Result selectCase(@RequestBody TestCaseDto testCaseDto) {
        return testCaseService.find(testCaseDto);
    }

    @Operation(description = "插入单条数据")
    @PostMapping(value = "/insertOne", produces = "application/json")
    Result insertCase(@RequestBody TestCaseDto testCaseDto) {
        return testCaseService.insert(testCaseDto);
    }

    @Operation(description = "修改数据")
    @PostMapping(value = "/update", produces = "application/json")
    Result updateCase(@RequestBody TestCaseDto testCaseDto) {
        return testCaseService.update(testCaseDto);
    }

    @Operation(description = "删除数据")
    @DeleteMapping(value = "/remove", produces = "application/json")
    Result deleteById(@RequestBody TestCaseDto testCaseDto) {
        return testCaseService.delete(testCaseDto);
    }
}

(6)启动swagger ,查看接口请求展示页面是否正确