[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
),可以大致看出来的一些
- annotation:注解依赖,这个可以被项目中的api模块引入从而使用它的注解
- jackson-annotations:jackson序列化注解,但是没有实际引入序列化依赖,因此在项目中需要自己引入
- mapstruct:我现在在做的项目中也使用到了这个,类似 BeanUtil.copyProperties的作用,Bean转换
- springfox-swagger-ui:默认还引入了UI界面,因此在自己封装swagger作为通用依赖的时候一般会排除掉,因为不同项目可能喜欢不同的UI界面(生产一般不引入UI)
- sl4f-api:日志门面
- 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>
同样看下它的依赖树
- jackson:jackson序列化的注解与实现
- tomcat:内嵌tomcat容器
- web:web和webmvc有什么区别还没了解过
- 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
好像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界面并不是很友好。
注
- 这次更新,移除了原来默认的swagger页面路径:
http://host/context-path/swagger-ui.html
,新增了两个可访问路径:http://host/context-path/swagger-ui/index.html
和http://host/context-path/swagger-ui/
- 通过调整日志级别,还可以看到新版本的swagger文档接口也有新增,除了以前老版本的文档接口
/v2/api-docs
之外,还多了一个新版本的/v3/api-docs
接口。
对于UI的访问地址在哪,如果没有特殊配置,直接看引入的UI的依赖,看一下首页html在哪个路径下(3.0版本之前),如下,本应不需要加上/swagger-ui
路径的,应该是在哪里配置掉了。
直接在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的外部类。
参考博客之前自己封装的一套,什么时候拜读一下
还有就是maven搜索springfox-开头的依赖,还是有很多模块的,不同模块的作用?
3. swagger-ui 路径前缀
IDEA全局搜索swagger-ui即可得到,springfox对webmvc的webflux分别使用了一套配置
SwaggerUiWebFluxConfiguration
、SwaggerUiWebFluxConfigurer
SwaggerUiWebMvcConfiguration
、SwaggerUiWebMvcConfigurer
功能基本相同。
会发现两个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
接口,重写addResourceHandlers
和addViewControllers
,addResourceHandlers
是处理资源的(可理解为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");
}