Springboot2整合knife4j過程解析
knife4j官網(wǎng):https://doc.xiaominfo.com/guide/useful.html
這玩藝就swagger的升級(jí)版,但是用起來比swagger方便多了,至少不會(huì)出現(xiàn)莫名的版本兼容問題
下面記錄一個(gè)配置示例
1.代碼結(jié)構(gòu)

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>
<!--在引用時(shí)請(qǐng)?jiān)趍aven中央倉庫搜索最新版本號(hào)-->
<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>
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掃描包路徑(項(xiàng)目路徑也行)
.apis(RequestHandlerSelectors.basePackage("com.example.knife4j.demo"))
.paths(PathSelectors.any())
.build();
return docket;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("不重要")
.description("測(cè)試名稱不重要")
.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;
/**
* 創(chuàng)建時(shí)間: 23:09 2018/9/19
* 修改時(shí)間:
* 編碼人員: 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 + "]";
}
}
5.兩個(gè)接口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測(cè)試接口")
@RestController
public class IndexController {
@ApiOperation(value = "測(cè)試index接口", nickname = "測(cè)試IndexController的index接口")
@GetMapping("/index")
public String index() {
return "測(cè)試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 = "用戶接口")
@RestController
public class UserController {
@ApiOperation(value = "獲取用戶信息接口", nickname = "根據(jù)用戶ID獲取用戶相關(guān)信息")
@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 = "入?yún)⑹菑?fù)雜對(duì)象", 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) { // 這里用包裝類竟然報(bào)錯(cuò)
if (user.getId() == userId) {
return user;
}
return new UserEntity();
}
@ApiOperation(value = "添加用戶", nickname = "添加用戶接口2", notes = "入?yún)⑹呛?jiǎn)單對(duì)象", 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;
}
}
6.srpingboot項(xiàng)目啟動(dòng)類
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/");
}
}
這樣簡(jiǎn)單一配置,就ok了,瀏覽器訪問:http://127.0.0.1:8080/doc.html

不過,在項(xiàng)目中我使用了ResponseBodyAdvice接口對(duì)項(xiàng)目接口響應(yīng)內(nèi)容做統(tǒng)一處理,然后使用knife4j就出問題了。
ResponseBodyAdvice接口實(shí)現(xiàn)如下:
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 ,對(duì)restful請(qǐng)求響應(yīng)體進(jìn)行統(tǒng)一規(guī)范
*/
@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);
}
}
請(qǐng)求報(bào)錯(cuò)

而且后臺(tái)還說找不到映射路徑
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方法中打上斷點(diǎn),發(fā)現(xiàn)我將swagger的請(qǐng)求內(nèi)容進(jìn)行了修改,以至于報(bào)了404。
最后在ResponseAdvise類上聲明只對(duì)本項(xiàng)目的響應(yīng)體內(nèi)容進(jìn)行統(tǒng)一處理
@RestControllerAdvice(basePackages = "com.example.knife4j.demo")
這樣,就完全ok!
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解mybatis.generator配上最新的mysql 8.0.11的一些坑
這篇文章主要介紹了詳解mybatis.generator配上最新的mysql 8.0.11的一些坑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10
Spring?boot?RedisTemplate?序列化服務(wù)化配置方式
這篇文章主要介紹了Springboot?RedisTemplate序列化服務(wù)化配置方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
java數(shù)據(jù)結(jié)構(gòu)與算法之馬踏棋盤
這篇文章主要為大家詳細(xì)介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之馬踏棋盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
SpringIOC容器Bean的作用域及生命周期實(shí)例
這篇文章主要為大家介紹了SpringIOC容器Bean的作用域及生命周期實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
向Spring IOC 容器動(dòng)態(tài)注冊(cè)bean實(shí)現(xiàn)方式
這篇文章主要為大家介紹了向Spring IOC 容器動(dòng)態(tài)注冊(cè)bean實(shí)現(xiàn)方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
詳解SpringBoot項(xiàng)目整合Vue做一個(gè)完整的用戶注冊(cè)功能
本文主要介紹了SpringBoot項(xiàng)目整合Vue做一個(gè)完整的用戶注冊(cè)功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
Mybatis調(diào)用MySQL存儲(chǔ)過程的簡(jiǎn)單實(shí)現(xiàn)
本篇文章主要介紹了Mybatis調(diào)用MySQL存儲(chǔ)過程的簡(jiǎn)單實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-04-04

