持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
一、swagger
相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。其实无论是前端调用后端,还是后端调用后端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码起来,最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。
下面来使用swagger3来进行演示说明,针对swagger2,官网文档总结主要修改如下几点:
- 1、删除了对springfox-swagger2的依赖;
- 2、删除所有@EnableSwagger2…注解;
- 3、添加了springfox-boot-starter依赖项;
- 4、移除了guava等第三方依赖;
- 5、文档访问地址改为http://ip:port/project/swagger-ui/index.html。
1-1、swagger的添加
1-1-1、添加依赖
目前swagger已经出3.0版本,因此我这边直接使用3.0版本,springboot使用2.6.7。因此直接引入swagger的启动器即可。
老版本可以引入如下依赖:
<!--
swagger 是一系列REST接口的描述和UI展示的规范(json)
springfox 整合springmvc和swagger 将代码中的注解转换为符合swagger的规范的json文件
-->
<!-- 核心包 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- ui界面的依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
我这边引入依赖为:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
1-1-2、创建swagger配置类
需要注意的是引入的Contact一定要使用swaggerfox的。这个配置类主要告诉swagger怎么去生成规范的数据,其中包括一些文档相关信息,自己可根据需求进行修改
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2) //生成swagger2规范的文档
.pathMapping("/") //设置哪些接口映射到文档中
.select() //接口选择器,
.apis(RequestHandlerSelectors.basePackage("com.jony.controller")) //告诉springfox哪些接口需要生成swagger文档
.paths(PathSelectors.any()) //设置哪些接口会生成在swagger文档上(下面设置的是所有)
//下面为描述文档的主体信息--可根据自己需要修改
.build().apiInfo(new ApiInfoBuilder()
.title("SpringBoot整合Swagger")
.description("SpringBoot整合Swagger,详细信息......")
.version("1.0")
.contact(new Contact("jony","www.jony.cn","123@qq.com"))
.build());
}
}
1-1-3、启动调试
这时候启动会报错,导致原因为:Springfox的Spring MVC 的路径匹配策略是 ant-path-matcher,而 Spring Boot 2.6.x版本的默认匹配策略是 path-pattern-matcher,这就造成了下面的报错。
1-1-3-1、springboot2.6.x添加swagger3.0错误解决
上面提到由于springfox和springboot的默认策略不一致导致,因此我们在配置文件里面修改springboot的策略为ant-path-matcher即可,如下:
这样就可以启动成功了,下面我们进行访问swagger3.0默认访问地址为:http://localhost:8080/swagger-ui/index.html
可以看到上部分即为我们在配置文件中设置的swagger相关信息,下面即为我们的控制器里面的方法以及请求类型。
通过以上可以解决报错并且可以对swagger进行访问,但是在某些服务启动时会失效,原因是使用springboot执行器的时候就失效了。因为执行器将始终使用基本路径模式的解析也就是默认策略(path-pattern-matcher)。因此在springboot2.6.x及高版本中并且与执行器一起使用时,则需要对Springfox进行修改。解决方案我这边也是在网上找到的方案,具体就是在swagger配置类中添加如下bean:
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
最终是否起作用,后面在使用执行器的时候再进行测试,如果大家有兴趣,可以去测试一下。
1-2、使用swagger测试
通过刚刚打开的swagger不仅可以看到我们控制器中的方法,同时还可以进行调用测试,下面来进行操作一下
1-2-1、点击要测试的接口
1-2-2、点击try it out
点击try it out,并输入参数,点击Execute
1-2-3、查看返回数据信息
通过以上方式我们就可以使用swagger进行接口调用测试了,同时也可以给前端人员,让前端人员进行接口调用。不过刚刚看到的全是英文界面,包括Controller以及里面的接口方法和接口需要传的参数都没有说明,这样是极其不友好的,别说前端人员,即使我们自己再过段时间,也不知道接口是干嘛的了,因此我们需要对相关信息添加一些描述信息。
1-3、swagger的相关注解
1-3-1、注解整体说明
1-3-1-1、用于 controller 类上
| 注解 | 说明 |
|---|---|
| @Api | 对请求类的说明 |
1-3-1-1-1、在Controller中使用
1-3-1-1-2、打开swagger页面查看
1-3-1-1-3、@Api其他参数描述说明
1-3-1-2、用于方法上面 (说明参数的含义):
| 注解 | 说明 |
|---|---|
| @ApiOperation | 方法的说明 |
| @ApiImplicitParams、@ApiImplicitParam | 方法的参数的说明;@ApiImplicitParams 用于指定单个参数的说明 |
1-3-1-2-1、在代码中使用
一个参数使用方法
@ApiOperation("通过用户ID查询用户信息")
@ApiImplicitParam(name="id",value = "用户ID")
@GetMapping("/{id}")
public Result getUser(@PathVariable Integer id) {
User user = userService.getUserById(id);
return new Result<>(200, "messge", user);
}
多参数使用方法
@ApiOperation(value="用户登录",notes="随边说点啥")
@ApiImplicitParams({
@ApiImplicitParam(name="mobile",value="手机号",required=true,paramType="form"),
@ApiImplicitParam(name="password",value="密码",required=true,paramType="form"),
@ApiImplicitParam(name="age",value="年龄",required=true,paramType="form",dataType="Integer")
})
@PostMapping("/login")
public Result login(@RequestParam String mobile, @RequestParam String password,
@RequestParam Integer age){
//...
return new Result<>(200, "messge");
}
1-3-1-2-2、swagger界面查看方法和参数描述效果
1-3-1-2-3、@ApiOperation的相关其他参数说明
1-3-1-2-4、@ApiImplicitParams的相关其他参数说明
1-3-1-3、用于方法上面 (返回参数或对象的说明):
返回这个一般不使用
| 注解 | 说明 |
|---|---|
| @ApiResponses、@ApiResponse | 方法返回值的说明 ;@ApiResponses 用于指定单个参数的说明 |
1-3-1-4、对象类:
| 注解 | 说明 |
|---|---|
| @ApiModel | 用在 JavaBean 类上,说明 JavaBean 的 用途 |
| @ApiModelProperty | 用在 JavaBean 类的属性上面,说明此属性的的含议 |
1-3-1-4-1、在模型中使用@ApiModel和@ApiModelProperty
在控制器中,我们会经常使用我们的对象模型,使用@ApiModel就可以给对象模型进行说明,并且使用@ApiModelProperty给模型属性进行说明
1-3-1-4-2、在swagger中查看效果
如下在Model中已经对user做出了相关描述
1-3-1-4-3、@ApiModel的其他相关参数说明
1-3-1-4-4、@ApiModelProperty的其他参数说明
以上即为swagger的相关经常使用的注解,其他相关注解感兴趣的同学可以自行搜索使用。
1-4、swagger页面的美化及文档下载
通过上的配置使用,我们就可以比较顺畅的使用swagger了,但是页面实在有点接受不了,同时文档也没办法导出,下面我们就开始进行页面的美化及文档导出。
1-4-1、添加依赖
<!--整合Knife4j-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
1-4-2、在swagger的配置类上添加@EnableKnife4j
1-4-3、测试访问
之前我这边本地访问的时候使用:
http://localhost:8080/swagger-ui/index.html
如果还是用这个连接是不行的。
我们需要使用如下地址:
http://localhost:8080/doc.html
效果展示:
是不是漂亮了很多,兼职天壤之别啊。
1-4-4、使用knife4j的swagger
1-4-4-1、控制器说明
下面这块就会把我们所有的控制器展示出来,点击之后,也可以看到里面的接口,以及对应的请求类型
1-4-4-1-1、查看接口
点击接口,就可以查看接口的详细信息,请求信息、响应信息一目了然
1-4-4-1-2、接口调试
输入相关参数,点击发送,就可以看到相关返回的数据信息
1-4-4-2、文档管理
在文档管理中、就可以添加全局参数、下载文档、以及相关个性化设置
1-4-4-2-1、全局参数设置
1-4-4-2-2、离线文档下载
1-4-4-2-3、个性化设置
1-4-4-3、Models查看
在swagger Models中就可以查看相关的model信息了。
二、通过AOP用swagger注解实现日志功能
一般日志,我们仅会输出调用当前方法的一些简略信息,这样在后面进行日志解读的时候多少有些不方便,比如调用了方法的名称、参数名称等。下面我们就可以使用AOP来实现日志功能
2-1、引入aop启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2-2、编写aop类
@Aspect
@Component
public class LogAspect {
@Around("execution(* com.jony.controller..*.*(..)) && @annotation(apiOperation)")
public Object around(JoinPoint pjp,ApiOperation apiOperation) {
Object result = null;
try {
//获取类对象
Class<?> controller = pjp.getThis().getClass();
//获取swagger接口对象
Api annotation = controller.getAnnotation(Api.class);
//获取类接口的内容
System.out.println("调用接口为:"+ annotation.value()+"-"+apiOperation.value());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}
}
2-3、调用接口查看输出信息
我这边只是简单的输出了一下,相关AOP的知识点,可以查看我之前的文章