• springboot2整合knife4j


    knife4j官网: https://doc.xiaominfo.com/guide/useful.html#java%E5%BC%80%E5%8F%91

    这玩艺就swagger的升级版,但是用起来比swagger方便多了,至少不会出现莫名的版本兼容问题

    下面记录一个配置示例

    1. 代码结构

    2.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">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.5.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>knife4j-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>knife4j-demo</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>com.github.xiaoymin</groupId>
                <artifactId>knife4j-spring-boot-starter</artifactId>
                <!--在引用时请在maven中央仓库搜索最新版本号-->
                <version>2.0.2</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.58</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.10</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    View Code

    3.配置类

    package 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();
        }
    }

    4. 模型bean

    package com.example.knife4j.demo.beans;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    
    /**
     * 创建时间: 23:09 2018/9/19
     * 修改时间:
     * 编码人员: ZhengQf
     * 版   本: 0.0.1
     * 功能描述:
     */
    @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;
        }
    
        @Override
        public String toString() {
            return "DemoDoctor [id=" + id + ", name=" + name + "]";
        }
    
    }
    View Code

    5.两个接口controller

    package 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测试接口")
    @RestController
    public class IndexController {
        @ApiOperation(value = "测试index接口", nickname = "测试IndexController的index接口")
        @GetMapping("/index")
        public String index() {
            return "测试IndexController的index接口...";
        }
    
    }
    View Code
    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 = "用户接口")
    @RestController
    public 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;
        }
    
    }
    View Code

    6. srpingboot项目启动类

    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);
        }
        @Override
        public 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

    不过,在项目中我使用了 ResponseBodyAdvice 接口对项目接口响应内容做统一处理, 然后使用knife4j就出问题了。

    ResponseBodyAdvice接口实现如下:

    import 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
    @RestControllerAdvice
    public class ResponseAdvise implements ResponseBodyAdvice<Object> {
        @Override
        public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
            return true;
        }
    
        @Override
        public 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.js
    2020-03-10 23:31:01.560  WARN 7940 --- [nio-8080-exec-4] o.s.web.servlet.PageNotFound             : No mapping for GET /favicon.ico
    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类上声明只对本项目的响应体内容进行统一处理

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

    这样,就完全ok!

  • 相关阅读:
    frp服务器搭建
    vue cli工具UI,AXIOS开发流程
    vue-cli 3.0之跨域请求代理配置及axios路径配置
    利用CSS、JavaScript及Ajax实现图片预加载的三大方法
    Preload图片预加载(jQuery插件)
    Unigui Basic jQuery学习
    emqtt 系统主题
    变量命名法
    Excel-VBA常用对象(Application、Workbook、Worksheet、Range)
    SqlServer对select * from (select *from table) 支持
  • 原文地址:https://www.cnblogs.com/z-qinfeng/p/12459733.html
Copyright © 2020-2023  润新知