[1]-swagger-demo

参考:尝鲜刚发布的 SpringFox 3.0.0,以前造的轮子可以不用了... - 程序猿DD - 博客园 (cnblogs.com)

1. 依赖说明

依赖,2020.7发布的,也就只有这个版本 😂

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

看看它引入的依赖(mvn dependency:tree),可以大致看出来的一些

  1. annotation:注解依赖,这个可以被项目中的api模块引入从而使用它的注解
  2. jackson-annotations:jackson序列化注解,但是没有实际引入序列化依赖,因此在项目中需要自己引入
  3. mapstruct:我现在在做的项目中也使用到了这个,类似 BeanUtil.copyProperties的作用,Bean转换
  4. springfox-swagger-ui:默认还引入了UI界面,因此在自己封装swagger作为通用依赖的时候一般会排除掉,因为不同项目可能喜欢不同的UI界面(生产一般不引入UI)
  5. sl4f-api:日志门面
  6. spring-beans、spring-context

问题:v3和原来的swagger2的annotation和model区别

[INFO] \- io.springfox:springfox-boot-starter:jar:3.0.0:compile
[INFO]    +- io.springfox:springfox-oas:jar:3.0.0:compile
[INFO]    |  +- io.swagger.core.v3:swagger-annotations:jar:2.1.2:compile
[INFO]    |  +- io.swagger.core.v3:swagger-models:jar:2.1.2:compile
[INFO]    |  |  \- com.fasterxml.jackson.core:jackson-annotations:jar:2.10.1:compile
[INFO]    |  +- io.springfox:springfox-spi:jar:3.0.0:compile
[INFO]    |  +- io.springfox:springfox-schema:jar:3.0.0:compile
[INFO]    |  +- io.springfox:springfox-core:jar:3.0.0:compile
[INFO]    |  |  \- net.bytebuddy:byte-buddy:jar:1.10.11:compile
[INFO]    |  +- io.springfox:springfox-spring-web:jar:3.0.0:compile
[INFO]    |  |  \- io.github.classgraph:classgraph:jar:4.8.83:compile
[INFO]    |  +- io.springfox:springfox-spring-webmvc:jar:3.0.0:compile
[INFO]    |  +- io.springfox:springfox-spring-webflux:jar:3.0.0:compile
[INFO]    |  +- io.springfox:springfox-swagger-common:jar:3.0.0:compile
[INFO]    |  \- org.mapstruct:mapstruct:jar:1.3.1.Final:runtime
[INFO]    +- io.springfox:springfox-data-rest:jar:3.0.0:compile
[INFO]    +- io.springfox:springfox-bean-validators:jar:3.0.0:compile
[INFO]    +- io.springfox:springfox-swagger2:jar:3.0.0:compile
[INFO]    |  +- io.swagger:swagger-annotations:jar:1.5.20:compile
[INFO]    |  \- io.swagger:swagger-models:jar:1.5.20:compile
[INFO]    +- io.springfox:springfox-swagger-ui:jar:3.0.0:compile
[INFO]    +- com.fasterxml:classmate:jar:1.5.1:compile
[INFO]    +- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO]    +- org.springframework.plugin:spring-plugin-core:jar:2.0.0.RELEASE:compile
[INFO]    |  +- org.springframework:spring-beans:jar:5.2.0.RELEASE:compile
[INFO]    |  |  \- org.springframework:spring-core:jar:5.2.0.RELEASE:compile
[INFO]    |  |     \- org.springframework:spring-jcl:jar:5.2.0.RELEASE:compile
[INFO]    |  +- org.springframework:spring-context:jar:5.2.0.RELEASE:compile
[INFO]    |  |  \- org.springframework:spring-expression:jar:5.2.0.RELEASE:compile
[INFO]    |  \- org.springframework:spring-aop:jar:5.2.0.RELEASE:compile
[INFO]    \- org.springframework.plugin:spring-plugin-metadata:jar:2.0.0.RELEASE:compile

SpringBoot Web的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.7.0</version>
</dependency>

同样看下它的依赖树

  1. jackson:jackson序列化的注解与实现
  2. tomcat:内嵌tomcat容器
  3. web:web和webmvc有什么区别还没了解过
  4. spring-boot-starte:这个也没了解过其作用。Core starter, including auto-configuration support, logging and YAML,自动配置等的依赖实际被它引入了
[INFO] \- org.springframework.boot:spring-boot-starter-web:jar:2.7.0:compile
[INFO]    +- org.springframework.boot:spring-boot-starter:jar:2.7.0:compile
[INFO]    +- org.springframework.boot:spring-boot-starter-json:jar:2.7.0:compile
[INFO]    |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.13.3:compile
[INFO]    |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.13.3:compile
[INFO]    |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.13.3:compile
[INFO]    |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.13.3:compile
[INFO]    |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.13.3:compile
[INFO]    |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.13.3:compile
[INFO]    +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.7.0:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.63:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.63:compile
[INFO]    |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.63:compile
[INFO]    +- org.springframework:spring-web:jar:5.3.20:compile
[INFO]    |  \- org.springframework:spring-beans:jar:5.3.20:compile
[INFO]    \- org.springframework:spring-webmvc:jar:5.3.20:compile
[INFO]       +- org.springframework:spring-aop:jar:5.3.20:compile
[INFO]       +- org.springframework:spring-context:jar:5.3.20:compile
[INFO]       \- org.springframework:spring-expression:jar:5.3.20:compile

2. Demo

复习一下maven是如何解决依赖冲突的(浅探maven处理重复依赖不同版本的方式_IRON_MAN_KD的博客-CSDN博客_maven传递依赖不同版本

1、最短路径原则

2、声明优先原则

3、同级依赖后加载覆盖先加载

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.7.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-boot-starter</artifactId>
        <version>3.0.0</version>
    </dependency>
</dependencies>
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

不需要显式开启,swagger使用的@EnableSwagger2和新的@EnableOpenApi区别?@EnableOpenApi不必显式使用,因为其@Import的类在springfox-boot-starter中的spring.factories中配置了(引入的是一个自动配置类OpenApiAutoConfiguration)。而这个配置类又@Import了@EnableSwagger2引入@Import的Swagger2DocumentationConfiguration。

@EnableOpenApi引入的依赖比@EnableSwagger2多,而SpringBoot自动配置下,不必使用这两个任何一个注解。

@ApiModel("用户基本信息")
public class User {
    @ApiModelProperty("姓名")
    private String name;
    @ApiModelProperty("年龄")
    private Integer age;
    @ApiModelProperty("地址")
    private String address;
    @ApiModelProperty("邮箱")
    private String email;
}
@Api(tags = "用户管理")
@RestController
public class UserController {

    @ApiOperation("创建用户")
    @PostMapping("/user")
    public User create(@RequestBody User user) {
        return user;
    }

    @ApiOperation("用户详情")
    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id) {
        return new User("bbb", 21, "上海", "aaa@bbb.com");
    }

    @ApiOperation("用户列表")
    @GetMapping("/users")
    public List<User> list(@ApiParam("查看第几页") @RequestParam int pageIndex,
                           @ApiParam("每页多少条") @RequestParam int pageSize) {
        List<User> result = new ArrayList<>();
        result.add(new User("aaa", 50, "北京", "aaa@ccc.com"));
        result.add(new User("bbb", 21, "广州", "aaa@ddd.com"));
        return result;
    }

    @ApiIgnore
    @DeleteMapping("/user/{id}")
    public String deleteById(@PathVariable Long id) {
        return "delete user : " + id;
    }
}

Restful API的设计?

DDD的项目结构?

启动发现报错

org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException

SpringBoot更新到2.6.0启动报错 Failed to start bean ‘documentationPluginsBootstrapper‘ 问题处理_CHQIUU的博客-CSDN博客_springboot升级失败

好像swagger和knif4j都有这个问题,而且我看knif4j的最新依赖也就是2020.9😂
搞错了,应该是 knife4j,开源并且经常更新的也挺多的。
还发现一个问题,springfox-相关的项目好像都停止在了2020,后续都没有维护了😂
swagger和snife4j的区别?

问题是因为新版本的路径匹配使用了PathPatternParser,而swagger一直没有更新,还使用的AntPathMatcher内部原理待续(为什么错误、区别)

配置下面使用原本的AntPathMatcher,有的还使用@EnableWebMvc这个注解的作用是?有没有副作用?

spring:
  mvc:
    pathmatch:
      matching-strategy: ANT_PATH_MATCHER

成功启动。

接口地址

3.0 中的接口地址也和之前有所不同,以前在 2.9.2 中我们主要访问两个地址:

现在在 3.0 中,这两个地址也发生了变化:

特别是文档页面地址,如果用了 3.0,而去访问之前的页面,会报 404。

具体页面不用图片展示了,由于很久没有更新了,UI界面并不是很友好。

  1. 这次更新,移除了原来默认的swagger页面路径:http://host/context-path/swagger-ui.html,新增了两个可访问路径:http://host/context-path/swagger-ui/index.htmlhttp://host/context-path/swagger-ui/
  2. 通过调整日志级别,还可以看到新版本的swagger文档接口也有新增,除了以前老版本的文档接口/v2/api-docs之外,还多了一个新版本的/v3/api-docs接口。

对于UI的访问地址在哪,如果没有特殊配置,直接看引入的UI的依赖,看一下首页html在哪个路径下(3.0版本之前),如下,本应不需要加上/swagger-ui路径的,应该是在哪里配置掉了。

image

直接在IDEA里全局搜索swagger-ui,相关的配置类有SpringfoxConfigurationProperties.SwaggerUiConfigurationProperties这个配置类对应springfox.documentation.swagger-ui.enabled=false可以禁用掉/swagger-ui路径前缀,默认是true。这里有一个知识点@NestedConfigurationProperty注解使用场景,对应的是@ConfigurationProperties

同时也有配置springfox.documentation.swagger-ui.baseUrl,也就是路径/swagger-ui再添加自定义路由,如服务名用于区分不同服务。

在这里阅读的时候差点掉坑了,两个类都是public的,一时联想到一个java类里不能有两个public的,想了一下才反应过来仅能有一个public的外部类。

https://github.com/SpringForAll/spring-boot-starter-swagger

参考博客之前自己封装的一套,什么时候拜读一下
还有就是maven搜索springfox-开头的依赖,还是有很多模块的,不同模块的作用?

3. swagger-ui 路径前缀

IDEA全局搜索swagger-ui即可得到,springfox对webmvc的webflux分别使用了一套配置

  • SwaggerUiWebFluxConfigurationSwaggerUiWebFluxConfigurer
  • SwaggerUiWebMvcConfigurationSwaggerUiWebMvcConfigurer
    功能基本相同。
    会发现两个Configuration都有一个条件注入,必须springfox.documentation.swagger-ui.enabled配置为true才进行配置,默认也是为true,功能也大致能推出是为了加上swagger-ui路径前缀的
@ConditionalOnProperty(
    value = "springfox.documentation.swagger-ui.enabled",
    havingValue = "true",
    matchIfMissing = true)
```java

```java
@Configuration
// 需要是 Servlet Web 环境,SpringBoot启动时会配置
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
// 配置要求,条件注入
@ConditionalOnProperty(
    value = "springfox.documentation.swagger-ui.enabled",
    havingValue = "true",
    matchIfMissing = true)
public class SwaggerUiWebMvcConfiguration {
  // 这里没有配置默认为空
  @Value("${springfox.documentation.swagger-ui.base-url:}")
  private String swaggerBaseUrl;

  // 内部才是实际配置的
  @Bean
  public SwaggerUiWebMvcConfigurer swaggerUiConfigurer() {
    return new SwaggerUiWebMvcConfigurer(fixup(swaggerBaseUrl));
  }

  private String fixup(String swaggerBaseUrl) {
    // 去掉尾巴的'/'
    return StringUtils.trimTrailingCharacter(nullToEmpty(swaggerBaseUrl), '/');
  }
}
public class SwaggerUiWebMvcConfigurer implements WebMvcConfigurer {
  private final String baseUrl;

  public SwaggerUiWebMvcConfigurer(String baseUrl) {
    this.baseUrl = baseUrl;
  }

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    // 和 SwaggerUiWebMvcConfiguration 一样,又处理了一次
    String baseUrl = StringUtils.trimTrailingCharacter(this.baseUrl, '/');
    registry.
        // 自定义路径 + swagger-ui,由这里可知,若是使用swagger的配置,要自定义baseUrl路径则必须接收swagger-ui,否则得自己继承WebMvcConfigurer配置
        addResourceHandler(baseUrl + "/swagger-ui/**")
        // 得到这个路径去哪里找资源
        .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
        .resourceChain(false);
  }

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    // baseUrl + swagger-ui 得路径自动转发到 index.html,不需要写全路径
    registry.addViewController(baseUrl + "/swagger-ui/")
        .setViewName("forward:" + baseUrl + "/swagger-ui/index.html");
  }
}

4. 自定义url配置

RestfulTool只能找到应用中得,不能找到Swagger依赖提供得一些webmvc路径,于是我引入了spring-boot-starter-actuator,喔嚯,spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER配置不行了,@EnableWebMvc也不行,就是报错。....
问题待处理

这里说的url配置是类似swagger-ui添加自定义路径映射。
继承WebMvcConfigurer接口,重写addResourceHandlersaddViewControllersaddResourceHandlers是处理资源的(可理解为html等资源),addViewControllers处理视图(可以理解为Controller)
下面不是完成配置,也并非正确配置,大致就是基本原理,可以在原本的配置下打开浏览器debug查看swagger请求了哪些地址,然后将下面的配置上,大致就是前者是添加baseUrl后路径,后续必须使用这个路径访问,而WebMvc类似会将这个路径在内部映射为原路径去访问。

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(baseUrl + "/swagger-ui.html*").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler(baseUrl + "/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    /**
     * 自定义视图控制
     * @param registry ViewControllerRegistry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addRedirectViewController(baseUrl + "/swagger-resources", "/swagger-resources");
    }
posted @ 2022-07-04 23:47  YangDanMua  阅读(356)  评论(0编辑  收藏  举报