knife4j官网: https://doc.xiaominfo.com/guide/useful.html#java%E5%BC%80%E5%8F%91
    这玩艺就swagger的升级版,但是用起来比swagger方便多了,至少不会出现莫名的版本兼容问题
    下面记录一个配置示例

    1. 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

      1. 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

    1. 2. 配置类
    2. ```java
    3. package com.example.knife4j.demo.config;
    4. import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
    5. import org.springframework.context.annotation.Bean;
    6. import org.springframework.context.annotation.Configuration;
    7. import org.springframework.context.annotation.Import;
    8. import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
    9. import springfox.documentation.builders.ApiInfoBuilder;
    10. import springfox.documentation.builders.PathSelectors;
    11. import springfox.documentation.builders.RequestHandlerSelectors;
    12. import springfox.documentation.service.ApiInfo;
    13. import springfox.documentation.spi.DocumentationType;
    14. import springfox.documentation.spring.web.plugins.Docket;
    15. import springfox.documentation.swagger2.annotations.EnableSwagger2;
    16. @Configuration
    17. @EnableSwagger2
    18. @EnableKnife4j
    19. @Import(BeanValidatorPluginsConfiguration.class)
    20. public class SwaggerConfiguration {
    21. @Bean(value = "defaultApi2")
    22. public Docket defaultApi2() {
    23. Docket docket=new Docket(DocumentationType.SWAGGER_2)
    24. .apiInfo(apiInfo())
    25. //分组名称
    26. .groupName("2.X版本")
    27. .select()
    28. //这里指定Controller扫描包路径(项目路径也行)
    29. .apis(RequestHandlerSelectors.basePackage("com.example.knife4j.demo"))
    30. .paths(PathSelectors.any())
    31. .build();
    32. return docket;
    33. }
    34. private ApiInfo apiInfo() {
    35. return new ApiInfoBuilder()
    36. .title("不重要")
    37. .description("测试名称不重要")
    38. .termsOfServiceUrl("http://localhost:88888/")
    39. .contact("10086@mail.com")
    40. .version("1.0")
    41. .build();
    42. }
    43. }
    1. 模型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;

    1. public Integer getId() {
    2. return id;
    3. }
    4. public void setId(Integer id) {
    5. this.id = id;
    6. }
    7. public String getName() {
    8. return name;
    9. }
    10. public void setName(String name) {
    11. this.name = name;
    12. }
    13. @Override
    14. public String toString() {
    15. return "DemoDoctor [id=" + id + ", name=" + name + "]";
    16. }

    }

    1. 5. 接口
    2. ```java
    3. package com.example.knife4j.demo.controller;
    4. import io.swagger.annotations.Api;
    5. import io.swagger.annotations.ApiOperation;
    6. import org.springframework.web.bind.annotation.GetMapping;
    7. import org.springframework.web.bind.annotation.RestController;
    8. @Api(value = "IndexController测试接口")
    9. @RestController
    10. public class IndexController {
    11. @ApiOperation(value = "测试index接口", nickname = "测试IndexController的index接口")
    12. @GetMapping("/index")
    13. public String index() {
    14. return "测试IndexController的index接口...";
    15. }
    16. }
    1. package com.example.knife4j.demo.controller;
    2. import com.example.knife4j.demo.beans.UserEntity;
    3. import io.swagger.annotations.Api;
    4. import io.swagger.annotations.ApiImplicitParam;
    5. import io.swagger.annotations.ApiImplicitParams;
    6. import io.swagger.annotations.ApiOperation;
    7. import org.springframework.web.bind.annotation.*;
    8. @Api(value = "用户接口")
    9. @RestController
    10. public class UserController {
    11. @ApiOperation(value = "获取用户信息接口", nickname = "根据用户ID获取用户相关信息")
    12. @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int")
    13. @PostMapping("/postMember")
    14. public UserEntity postMember(@RequestParam Integer id) {
    15. UserEntity userEntity = new UserEntity();
    16. userEntity.setId(id);
    17. userEntity.setName("admin");
    18. return userEntity;
    19. }
    20. @ApiOperation(value = "添加用户", nickname = "添加用户接口1", notes = "入参是复杂对象", produces = "application/json")
    21. @PostMapping("/postUser")
    22. @ResponseBody
    23. @ApiImplicitParam(paramType = "query", name = "userId", value = "用户id", required = true, dataType = "int")
    24. public UserEntity postUser(@RequestBody UserEntity user, @RequestParam("userId") int userId) { // 这里用包装类竟然报错
    25. if (user.getId() == userId) {
    26. return user;
    27. }
    28. return new UserEntity();
    29. }
    30. @ApiOperation(value = "添加用户", nickname = "添加用户接口2", notes = "入参是简单对象", produces = "application/json")
    31. @PostMapping("/addUser")
    32. @ResponseBody
    33. @ApiImplicitParams({
    34. @ApiImplicitParam(paramType = "query", name = "userName", value = "用户姓名", required = true, dataType = "String"),
    35. @ApiImplicitParam(paramType = "query", name = "id", value = "用户id", required = true, dataType = "int")})
    36. public UserEntity addUser(String userName, int id) {
    37. UserEntity userEntity = new UserEntity();
    38. userEntity.setName(userName);
    39. userEntity.setId(id);
    40. return userEntity;
    41. }
    42. }
    1. 启动类 ```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 {

    1. public static void main(String[] args) {
    2. SpringApplication.run(Knife4jDemoApplication.class, args);
    3. }
    4. @Override
    5. public void addResourceHandlers(ResourceHandlerRegistry registry) {
    6. registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
    7. registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    8. }

    }

    1. 这样简单一配置,就ok了,浏览器访问: [http://127.0.0.1:8080/doc.html#/home](http://127.0.0.1:8080/doc.html#/home)<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/2693613/1655805421424-fad331ee-fb94-4e20-8ecf-1ebb708bf089.png#clientId=ua7a6b795-e906-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u29b8042d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=609&originWidth=1147&originalType=url&ratio=1&rotation=0&showTitle=false&size=46415&status=done&style=none&taskId=u2027862e-83d1-4f93-9743-c1be5f062df&title=)<br />不过,在项目中我使用了 ResponseBodyAdvice 接口对项目接口响应内容做统一处理, 然后使用knife4j就出问题了。<br />ResponseBodyAdvice接口实现如下:
    2. ```java
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.core.MethodParameter;
    5. import org.springframework.http.MediaType;
    6. import org.springframework.http.converter.HttpMessageConverter;
    7. import org.springframework.http.server.ServerHttpRequest;
    8. import org.springframework.http.server.ServerHttpResponse;
    9. import org.springframework.web.bind.annotation.RestControllerAdvice;
    10. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    11. import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
    12. /**
    13. * 自定义advise ,对restful请求响应体进行统一规范
    14. */
    15. @EnableWebMvc
    16. @Configuration
    17. @RestControllerAdvice
    18. public class ResponseAdvise implements ResponseBodyAdvice<Object> {
    19. @Override
    20. public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    21. return true;
    22. }
    23. @Override
    24. public Object beforeBodyWrite(Object object, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    25. if (object instanceof ResponseData) {
    26. return object;
    27. }
    28. return ResponseData.of().setData(object);
    29. }
    30. }

    请求报错
    image.png
    而且后台还说找不到映射路径

    1. 2020-03-10 23:31:01.533 WARN 7940 --- [nio-8080-exec-1] o.s.web.servlet.PageNotFound : No mapping for GET /service-worker.js
    2. 2020-03-10 23:31:01.560 WARN 7940 --- [nio-8080-exec-4] o.s.web.servlet.PageNotFound : No mapping for GET /favicon.ico
    3. 2020-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类上声明只对本项目的响应体内容进行统一处理

    1. @RestControllerAdvice(basePackages = "com.example.knife4j.demo")