他是swagger的升级版,在有swagger的调试功能以及接口描述的基础上,让人看着更加一目了然。
这次可能说的比较浅,主要是说怎么使用以及简单配置,还有我自己踩过的坑,因为这个东西我也第一次用。
截个图看看效果
有文档,有调试,可以代替postman了
这是重点,我踩了半天坑呢
使用方式有两种,一个是在knife4j通过接口,灵活获取。另一种是通过别的地方获取到token,粘贴到knife4j中。
不管那种方式,token都是作用到全局的
当点击按钮Authorize授权后,如果授权成功,接下来点击其余的接口进行调试时,在请求头会存在参数
Authorization
,如何在未授权之前打开了接口,则需要在授权后关闭该接口的Tab,然后重新打开
package config;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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.OAuthBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
/**
* Kni4j配置类
*
* @author haoxr
* @date 2021-02-25 15:36
*/
@Configuration
@EnableSwagger2WebMvc
@Import(BeanValidatorPluginsConfiguration.class)
@Slf4j
public class SwaggerConfiguration {
//这个是说swagger功能开启还是关闭,一般来讲生产环境关闭,其他环境开启
@Value("${swagger.enable}")
private boolean swaggerEnable;
@Bean
public Docket restApi() {
//schemas
SecurityContext securityContext = new SecurityContext(Lists.newArrayList(defaultAuth()), PathSelectors.ant("/**"));
//securityContext
List securityContexts = Lists.newArrayList(securityContext);
return new Docket(DocumentationType.SWAGGER_2)
.enable(swaggerEnable)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))//所有带@Api注解的类都能扫描到
.paths(PathSelectors.any())
.build()
.securityContexts(securityContexts)
.securitySchemes(securitySchemes())
.apiInfo(apiInfo());
}
/**
* 安全模式,这里指定token通过Authorization头请求头传递
*/
private List securitySchemes() {
// 设置请求头信息
List apiKeyList = new ArrayList();
//请求头里边有Authorization
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
return apiKeyList;
}
/**
* 默认的安全上引用
*/
private List defaultAuth() {
//Authorization作用于全局所有接口
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List securityReferences = new ArrayList<>();
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
return securityReferences;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("系统管理")
.description("测试")
.termsOfServiceUrl("https://www.youlai.tech")
.contact(new Contact("测试", "https://gitee.com/youlaiorg", "[email protected]"))
.license("Apache-2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
.version("1.0.0")
.build();
}
}
这个官方文档写了四种方式 我用的是第四种 3.19.4 密码模式(password)
3.19 OAuth2 - Knife4j 中文文档 v4.0 - 开发文档 - 文江博客
package config;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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.OAuthBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
/**
* Kni4j配置类
*/
@Configuration
@EnableSwagger2WebMvc
@Import(BeanValidatorPluginsConfiguration.class)
@Slf4j
public class SwaggerConfiguration {
//这个就是展示在页面上的url,权限验证所需的url
@Value("${knife4j.password_token_url}")
private String passwordTokenUrl;
@Value("${swagger.enable}")
private boolean swaggerEnable;
@Bean
public Docket restApi() {
//schema
List grantTypes = new ArrayList<>();
//密码模式
ResourceOwnerPasswordCredentialsGrant resourceOwnerPasswordCredentialsGrant = new ResourceOwnerPasswordCredentialsGrant(passwordTokenUrl);
grantTypes.add(resourceOwnerPasswordCredentialsGrant);
OAuth oAuth = new OAuthBuilder().name("oauth2")
.grantTypes(grantTypes).build();
//context
//scope方位
List scopes = new ArrayList<>();
scopes.add(new AuthorizationScope("read", "read resources"));
scopes.add(new AuthorizationScope("write", "write resources"));
scopes.add(new AuthorizationScope("reads", "read all resources"));
scopes.add(new AuthorizationScope("writes", "write all resources"));
SecurityReference securityReference = new SecurityReference("oauth2", scopes.toArray(new AuthorizationScope[]{}));
SecurityContext securityContext = new SecurityContext(Lists.newArrayList(securityReference), PathSelectors.ant("/**"));
//schemas
List securitySchemes = Lists.newArrayList(oAuth);
//securityContext
List securityContexts = Lists.newArrayList(securityContext);
return new Docket(DocumentationType.SWAGGER_2)
.enable(swaggerEnable)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.any())
.build()
.securityContexts(securityContexts)
.securitySchemes(securitySchemes)
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("系统管理")
.description("测试")
.termsOfServiceUrl("https://www.youlai.tech")
.contact(new Contact("测试", "https://gitee.com/youlaiorg", "[email protected]"))
.license("Apache-2.0")
.licenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
.version("1.0.0")
.build();
}
}
只能用token接口:这里要注意,如果你用的oauth2,那你就别想着自己加接口了,反正我研究半天,只能用oauth2自带的token接口。不然权限校验那里 principal会为空
而且他对返回的报文结构是有要求的,我们系统之前统一返回的是data包起来的json串,然后我在开始测试knife4j的时候,虽然接口调用成功了,但是各个接口header中的Authorition无法回填,都是undifind。直到我后来去掉外边的那层data,才回填成功
我是怎么处理的:线上正常登录用的是验证码模式。然后knife4j我用的密码模式
在token接口的实现里边,我通过模式区分,如果是验证码模式,就走原来的方法。如果是密码模式,就不做密码解密处理(为了调试方便,knife4j不就是给我们调试用的吗),而且返回的报文体也不被data包着。
不同项目中,虽然可以有互相调用关系,但是swagger配置(knife4j) 需要各写各的。
比如我们项目是网关调用权限系统,在鉴权通过之后,才能继续调用其他的服务系统接口。
然后我们项目在权限系统中有swagger(knife4j),在服务系统中还要配置swagger(knife4j),他们各走各的,互不影响。
knife4j当然还有其他的配置需要配,但是网上查查应该就可以解决,我这次主要是讲怎么和oauth结合的。
http://localhost:1234/doc.html
@Api(tags = "测试接口")
@RestController
public class SysDataSourceController {
@ApiOperation("测试下拉选")
@GetMapping("/type/options")
public Result> getTypeOptions(){
}
}
/**
** 请求实体
**/
@ApiModel("数据源搜索")
@Data
public class SourceQuery extends BasePageQuery {
@ApiModelProperty("关键字(数据源名称/数据源类型 忽略大小写搜索)")
private String keywords;
@ApiModelProperty("数据源类型下拉选id,可多选")
private List sourceTypeIds;
@ApiModelProperty("创建时间 正序ASC 倒序DESC 默认倒序")
private OrderEnum orderEnum;
}
@ApiOperation(value = "详情") @GetMapping("/{sourceId}") public Result getSourceDetail( @ApiParam("数据源ID") @PathVariable Long sourceId ) { }