knife4j官网: https://doc.xiaominfo.com/guide/useful.html#java%E5%BC%80%E5%8F%91
这玩艺就swagger的升级版,但是用起来比swagger方便多了,至少不会出现莫名的版本兼容问题
下面记录一个配置示例
POM ```xml <?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">
4.0.0 org.springframework.boot spring-boot-starter-parent 2.2.5.RELEASE com.example knife4j-demo 0.0.1-SNAPSHOT knife4j-demo Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine com.github.xiaoymin knife4j-spring-boot-starter 2.0.2 com.alibaba fastjson 1.2.58 org.projectlombok lombok 1.18.10 org.springframework.boot spring-boot-maven-plugin
2. 配置类```javapackage com.example.knife4j.demo.config;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.service.ApiInfo;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration@EnableSwagger2@EnableKnife4j@Import(BeanValidatorPluginsConfiguration.class)public class SwaggerConfiguration {@Bean(value = "defaultApi2")public Docket defaultApi2() {Docket docket=new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())//分组名称.groupName("2.X版本").select()//这里指定Controller扫描包路径(项目路径也行).apis(RequestHandlerSelectors.basePackage("com.example.knife4j.demo")).paths(PathSelectors.any()).build();return docket;}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("不重要").description("测试名称不重要").termsOfServiceUrl("http://localhost:88888/").contact("10086@mail.com").version("1.0").build();}}
- 模型Bean ```java package com.example.knife4j.demo.beans;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty;
@ApiModel(value = “用户模型”) public class UserEntity { @ApiModelProperty(value=”id” ,required= true,example = “123”) private Integer id; @ApiModelProperty(value=”用户姓名” ,required=true,example = “郑钦锋”) private String name;
public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "DemoDoctor [id=" + id + ", name=" + name + "]";}
}
5. 接口```javapackage com.example.knife4j.demo.controller;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@Api(value = "IndexController测试接口")@RestControllerpublic class IndexController {@ApiOperation(value = "测试index接口", nickname = "测试IndexController的index接口")@GetMapping("/index")public String index() {return "测试IndexController的index接口...";}}
package com.example.knife4j.demo.controller;import com.example.knife4j.demo.beans.UserEntity;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import io.swagger.annotations.ApiOperation;import org.springframework.web.bind.annotation.*;@Api(value = "用户接口")@RestControllerpublic class UserController {@ApiOperation(value = "获取用户信息接口", nickname = "根据用户ID获取用户相关信息")@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int")@PostMapping("/postMember")public UserEntity postMember(@RequestParam Integer id) {UserEntity userEntity = new UserEntity();userEntity.setId(id);userEntity.setName("admin");return userEntity;}@ApiOperation(value = "添加用户", nickname = "添加用户接口1", notes = "入参是复杂对象", produces = "application/json")@PostMapping("/postUser")@ResponseBody@ApiImplicitParam(paramType = "query", name = "userId", value = "用户id", required = true, dataType = "int")public UserEntity postUser(@RequestBody UserEntity user, @RequestParam("userId") int userId) { // 这里用包装类竟然报错if (user.getId() == userId) {return user;}return new UserEntity();}@ApiOperation(value = "添加用户", nickname = "添加用户接口2", notes = "入参是简单对象", produces = "application/json")@PostMapping("/addUser")@ResponseBody@ApiImplicitParams({@ApiImplicitParam(paramType = "query", name = "userName", value = "用户姓名", required = true, dataType = "String"),@ApiImplicitParam(paramType = "query", name = "id", value = "用户id", required = true, dataType = "int")})public UserEntity addUser(String userName, int id) {UserEntity userEntity = new UserEntity();userEntity.setName(userName);userEntity.setId(id);return userEntity;}}
- 启动类 ```java package com.example.knife4j.demo;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import springfox.documentation.spring.web.SpringfoxWebMvcConfiguration;
@ConditionalOnClass(SpringfoxWebMvcConfiguration.class) @SpringBootApplication public class Knife4jDemoApplication implements WebMvcConfigurer {
public static void main(String[] args) {SpringApplication.run(Knife4jDemoApplication.class, args);}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}
这样简单一配置,就ok了,浏览器访问: [http://127.0.0.1:8080/doc.html#/home](http://127.0.0.1:8080/doc.html#/home)<br /><br />不过,在项目中我使用了 ResponseBodyAdvice 接口对项目接口响应内容做统一处理, 然后使用knife4j就出问题了。<br />ResponseBodyAdvice接口实现如下:```javaimport org.springframework.context.annotation.Configuration;import org.springframework.core.MethodParameter;import org.springframework.http.MediaType;import org.springframework.http.converter.HttpMessageConverter;import org.springframework.http.server.ServerHttpRequest;import org.springframework.http.server.ServerHttpResponse;import org.springframework.web.bind.annotation.RestControllerAdvice;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/*** 自定义advise ,对restful请求响应体进行统一规范*/@EnableWebMvc@Configuration@RestControllerAdvicepublic class ResponseAdvise implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object object, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if (object instanceof ResponseData) {return object;}return ResponseData.of().setData(object);}}
请求报错
而且后台还说找不到映射路径
2020-03-10 23:31:01.533 WARN 7940 --- [nio-8080-exec-1] o.s.web.servlet.PageNotFound : No mapping for GET /service-worker.js2020-03-10 23:31:01.560 WARN 7940 --- [nio-8080-exec-4] o.s.web.servlet.PageNotFound : No mapping for GET /favicon.ico2020-03-10 23:31:14.468 WARN 7940 --- [nio-8080-exec-8] o.s.web.servlet.PageNotFound : No mapping for GET /service-worker.js
然后,我在 ResponseAdvise# beforeBodyWrite方法中打上断点,发现我将swagger的请求内容进行了修改,以至于报了404。
最后在ResponseAdvise类上声明只对本项目的响应体内容进行统一处理
@RestControllerAdvice(basePackages = "com.example.knife4j.demo")
