鱼和熊掌不可兼得:Spring boot3,Swagger3(使用Mybatis-Plus搭建框架)

2023-11-10

文章写于2023年7月1日,目前使用的配置尽量用最新的,如果晚于这个日期很久,请参考新的配置.

使用MyBatis plus搭建框架后使用swagger或者采用的Spring 3后使用swagger 3,启动项目出现如下错误:Type javax.servlet.http.HttpServletRequest not present

其根本原因是spring3目前不支持swagger产生的问题.解决方法有两种一种改为spring2,另外就是找一个swagger的代替品.

作为一个倔强的程序员(我一直认为这个是程序员应该有的良好品质),是绝对不会放弃新版本的spring3的,所以只能更换swagger了.

接下来我们将对程序进行两次升级.下面将用一个案例来说明.别担心,很简单.

首先做好准备工作.

1.创建两张MySql表

CREATE TABLE `address`  (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键:用户地址编号',
  `usersId` int NULL COMMENT '外键:用户编号',
  `tel` varchar(20) NULL COMMENT '电话',
  `location` varchar(200) NULL COMMENT '详细地址',
  `recipient` varchar(20) NULL COMMENT '收件人',
  `locationName` varchar(20) NULL COMMENT '命名的收件地址',
  `deleted` tinyint NULL COMMENT '逻辑删除',
  PRIMARY KEY (`id`)
);

CREATE TABLE `users`  (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键:用户编号',
  `userName` varchar(20) NULL COMMENT '姓名',
  `password` varchar(20) NULL COMMENT '登录密码',
  `age` int NULL COMMENT '年龄',
  `email` varchar(50) NULL COMMENT '邮箱,登录名',
  `deleted` tinyint NULL COMMENT '逻辑删除',
  PRIMARY KEY (`id`)
) COMMENT = '用户表';

ALTER TABLE `address` ADD CONSTRAINT `fk_address_users_1` FOREIGN KEY (`usersId`) REFERENCES `users` (`id`);

2.创建好项目,搭建项目框架,本次仍然是使用Spring boot ,MyBatis Plus进行项目搭建,先添加pom文件,注意里面被注释的内容,被注释的内容是第二次升级需要用到的代码.具体代码如下:(以下的代码是本篇文章的完整代码)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.flamelp</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>MP_Redis_SpringDoc</name>
    <description>MP_Redis_SpringDoc</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
<!--        redis,jedis,cache,spring boot web,thymeleaf,mybatis-spring,lombok-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.2</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter-test</artifactId>
            <version>3.0.2</version>
            <scope>test</scope>
        </dependency>
<!--mp,mp代码生成器,模板-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

<!--        第一次升级使用springDoc 代替swagger-->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.0.4</version>
        </dependency>
<!--第二次升级使用knife4j,里面包含了第一次升级使用springDoc-->
<!--        <dependency>-->
<!--            <groupId>com.github.xiaoymin</groupId>-->
<!--            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>-->
<!--            <version>4.1.0</version>-->
<!--        </dependency>-->

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3.使用MyBatis Plus生成代码框架,这部分内容略,可以看我另外一篇文章:

MyBaits-Plus使用redis作为缓存的另外一种方法_flame.liu的博客-CSDN博客

这里需要注意的是MyBatis Plus的最新版已经支持springDoc了,这里需要做一些小的改动:

在MyBatis Plus进行全局配置的时候将enableSwagger() 改为 enableSpringdoc(),这样MP将自动在实体类上创建好SpringDOC的注解,省下很多事情.

第一次升级,使用功能更加强大的SpringDoc代替现有的Swagger,虽然SpringDoc也可以叫做Swagger.

1.在pom文件中去掉swagger的配置,添加springDOC的配置

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.0.4</version>
</dependency>

2.在实体类,Controll类中添加注解,注解说明如下:

OpenAPI注解
注解         说明
@Schema 标注在实体和实体的属性上面,如果使用MyBatis-Plus会自动给你加上
@Tag(name = “接口类描述”) 标注在controller上,用来描述类的作用.
@Operation(summary =“接口方法描述”) 标注在controller的方法上,用来描述方法的作用
@Parameter(description=“参数描述”) 标注在controller的方法上,用来描述方法的参数
@Parameters 标注在controller的方法上,用来描述方法的多个参数
@Parameter(hidden = true) 、@Operation(hidden = true)@Hidden 排除api,一般不用到.

接下来我们从具体使用来看注解的用法

3.实体类具体代码.(由MP自动生成)

@TableName("users")
//mybatis plus会自动添加@Schema主键,前提条件是你在数据库的表和列中添加了相应的注释
@Schema(name = "Users", description = "用户表")
public class Users implements Serializable {

    private static final long serialVersionUID = 1L;

    @Schema(description = "主键:用户编号")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
}

以上是代码片段,主要由MP自动生成,

4.controller类具体代码,这里写了两个类和不同的方法做对比.

先是UsersController类

import com.flamelp.demo.entity.Users;
import com.flamelp.demo.service.IUsersService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author flamelp. 仅用于教学使用
 * @since 2023-07-01
 */
@RestController
@RequestMapping("/demo/users")
@Tag(name="UsersController",description = "操作用户信息的接口")
public class UsersController {
    @Resource
    private IUsersService usersService;

    @Tag(name = "createData",description = "初始化页面数据")
    @Parameter(name = "modelAndView",description = "action传递过来的modelView")
    private void createData(ModelAndView modelAndView){
        List<Users> usersList = usersService.list();
        //页面初始化时,添加所有数据并显示
        modelAndView.addObject("usersList",usersList);
    }

    @RequestMapping("index")
    @Operation(summary="index",description = "默认显示所有用户信息")
    public ModelAndView index(){
        ModelAndView modelAndView = new ModelAndView("index");
        return modelAndView;
    }


    @RequestMapping("search")
    @Operation(summary="search",description = "根据id搜索用户信息")
    @Parameter(name="search",description = "需要查找的用户编号")
    @ApiResponse(description = "返回查询到的用户")
    public Users search(int id){
        Users user = usersService.selectById(id);
        return user;
    }
}

这里需要注意的是private方法,返回ModelAndView的方法是不会出现在测试里面的.另外也可以观察到这两个方法使用的是@RequestMapping注解,所以在测试的时候可以用到多种方式进行测试,先不急,后面会遇到.

为了做对比,还有一个AddressController类.

import com.flamelp.demo.entity.Address;
import com.flamelp.demo.service.IAddressService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/demo/address")
@Tag(name = "AddressController", description = "地址管理")
public class AddressController {
    @Resource
    private IAddressService addressService;

    @GetMapping({"list"})
    @Operation(summary = "showAddress", description = "查找并显示所有地址")
    @ApiResponse(description = "所有用户信息")
    public List<Address> showAddress() {
        List<Address> addresses = this.addressService.list();
        return addresses;
    }

    @PostMapping("addAddress")
    @Operation(summary = "addAddress", description = "添加地址信息")
    @Parameter(name = "addresses", description = "需要添加的地址信息")
    public Address addAddress(Address addresses) {
        return this.addressService.add(addresses);
    }
}

这里使用的是@GetMapping和@PostMapping注解.后面截图你会看到不一样的地方.

接下来是启动.在地址栏输入http://localhost:XXXX/swagger-ui/index.html    xxxx是你指定的端口

打开的页面是:

上图显示的是两个controll和实体类.可以看到UsersController类的私有方法和返回ModelAndView的方法没有显示在这里,同时标注了@RequestMapping注解的方法有7种测试方法.

如果我们有多个controller,并且方法也很多的时候,这个页面就会显得凌乱,那么有什么好办法吗?这就是我们的第二次升级.

第二次升级:使用knife4j增强工具,别急,改动很少.

 1.在pom中去掉,springdoc-openapi-starter-webmvc-ui的配置,并取消knife4j-spring-boot-starter 和 knife4j-openapi3-jakarta-spring-boot-starter的注释,也就是启用这两个.代码在前面已经给了.

btw:knife4j 包含了springdoc

2.配置application.yml

# springdoc-openapi 配置
springdoc:
  swagger-ui:
    #springdoc的访问路径
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  group-configs:
    - group: 'default'
      paths-to-match: '/**'
      #需要扫描的包,这里需要改成你自己的.
      packages-to-scan: com.flamelp.demo

knife4j:
  enable: true
  setting:
    language: zh_cn

3.其它的不需要做修改,包括类里面的注解一个都不需要改.不过访问路径不同了.http://localhost:xxxx/doc.html#/home

原来的http://localhost:XXXX/swagger-ui/index.html   路径仍然可以访问.但是很明显doc.html访问更加的清晰.而且描述也更加的具体.

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

鱼和熊掌不可兼得:Spring boot3,Swagger3(使用Mybatis-Plus搭建框架) 的相关文章

  • Java 枚举与创建位掩码和检查权限的混淆

    我想将此 c 权限模块移植到 java 但是当我无法将数值保存在数据库中然后将其转换为枚举表示形式时 我很困惑如何执行此操作 在 C 中 我创建一个如下所示的枚举 public enum ArticlePermission CanRead
  • 使用 LinkedList 实现下一个和上一个按钮

    这可能是一个愚蠢的问题 但我很难思考清楚 我编写了一个使用 LinkedList 来移动加载的 MIDI 乐器的方法 我想制作一个下一个和一个上一个按钮 以便每次单击该按钮时都会遍历 LinkedList 如果我硬编码itr next or
  • .properties 中的通配符

    是否存在任何方法 我可以将通配符添加到属性文件中 并且具有所有含义 例如a b c d lalalala 或为所有以结尾的内容设置一个正则表达式a b c anything 普通的 Java 属性文件无法处理这个问题 不 请记住 它实际上是
  • 如何使用assertEquals 和 Epsilon 在 JUnit 中断言两个双精度数?

    不推荐使用双打的assertEquals 我发现应该使用带有Epsilon的形式 这是因为双打不可能100 严格 但无论如何我需要比较两个双打 预期结果和实际结果 但我不知道该怎么做 目前我的测试如下 Test public void te
  • HSQL - 识别打开连接的数量

    我正在使用嵌入式 HSQL 数据库服务器 有什么方法可以识别活动打开连接的数量吗 Yes SELECT COUNT FROM INFORMATION SCHEMA SYSTEM SESSIONS
  • 内部类的构造函数引用在运行时失败并出现VerifyError

    我正在使用 lambda 为内部类构造函数创建供应商ctx gt new SpectatorSwitcher ctx IntelliJ建议我将其更改为SpectatorSwitcher new反而 SpectatorSwitcher 是我正
  • 如何对不同的参数类型使用相同的java方法?

    我的问题 我有 2 个已定义的记录 创建对象请求 更新对象请求 必须通过实用方法进行验证 由于这两个对象具有相同的字段 因此可以对这两种类型应用相同的验证方法 现在我只是使用两种方法进行重载 但它很冗长 public record Crea
  • 如何在谷歌地图android上显示多个标记

    我想在谷歌地图android上显示带有多个标记的位置 问题是当我运行我的应用程序时 它只显示一个位置 标记 这是我的代码 public class koordinatTask extends AsyncTask
  • 获取文件的总大小(以字节为单位)[重复]

    这个问题在这里已经有答案了 可能的重复 java 高效获取文件大小 https stackoverflow com questions 116574 java get file size efficiently 我有一个名为 filenam
  • Cucumber 0.4.3 (cuke4duke) 与 java + maven gem 问题

    我最近开始为 Cucumber 安装一个示例项目 并尝试使用 maven java 运行它 我遵循了这个指南 http www goodercode com wp using cucumber tests with maven and ja
  • 最新的 Hibernate 和 Derby:无法建立 JDBC 连接

    我正在尝试创建一个使用 Hibernate 连接到 Derby 数据库的准系统项目 我正在使用 Hibernate 和 Derby 的最新版本 但我得到的是通用的Unable to make JDBC Connection error 这是
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • Opencv Java 灰度

    我编写了以下程序 尝试从彩色转换为灰度 Mat newImage Imgcodecs imread q1 jpg Mat image new Mat new Size newImage cols newImage rows CvType C
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 在java中为组合框分配键

    我想添加一个JComboBox在 Swing 中这很简单 但我想为组合中的每个项目分配值 我有以下代码 JComboBox jc1 new JComboBox jc1 addItem a jc1 addItem b jc1 addItem
  • 长轮询会冻结浏览器并阻止其他 ajax 请求

    我正在尝试在我的中实现长轮询Spring MVC Web 应用程序 http static springsource org spring docs 2 0 x reference mvc html但在 4 5 个连续 AJAX 请求后它会
  • 如何将双精度/浮点四舍五入为二进制精度?

    我正在编写对浮点数执行计算的代码的测试 不出所料 结果很少是准确的 我想在计算结果和预期结果之间设置一个容差 我已经证实 在实践中 使用双精度 在对最后两位有效小数进行四舍五入后 结果始终是正确的 但是usually四舍五入最后一位小数后
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • 如何防止在Spring Boot单元测试中执行import.sql

    我的类路径中有一个 import sql 文件 其中包含一些 INSERT 语句 当使用 profile devel 运行我的应用程序时 它的数据被加载到 postgres 数据库中 到目前为止一切正常 当使用测试配置文件执行测试时 imp
  • Spring Boot 无法更新 azure cosmos db(MongoDb) 上的分片集合

    我的数据库中存在一个集合 documentDev 其分片键为 dNumber 样本文件 id 12831221wadaee23 dNumber 115 processed false 如果我尝试使用以下命令通过任何查询工具更新此文档 db

随机推荐