spring boot项目集成 knife4j 2.0.5并实现入参分组校验显示

Updated on in 编程技术 with 0 views and 0 comments

之前写过一篇:前后端分离时如何优雅的编写 API 文档

不过其中的部分配置还不够完善,本次对其进行一定的优化。

1 路径分组配置

项目中,有的路径需要登录,有的不需要登录,需要登录的接口还可能需要配置全局 header,用于传输校验使用的 token 等

这里是使用路径进行是否需要登录的匹配,其中,路径包含/pub,则不需要登录,否则,需要登录,同时扫描多个路径,路径之前用英文逗号(,)隔开即可

具体实现如下:

 1@Autowired
 2    private SwaggerProperties properties;
 3	
 4	@Bean(value = "defaultApi")
 5    public Docket defaultApi() {
 6        return new Docket(DocumentationType.SWAGGER_2)
 7                .useDefaultResponseMessages(false)
 8                .apiInfo(apiInfo())
 9                .groupName(properties.getGroupName() + "-待认证")
10                .select()
11                .apis(getPredicate())
12                .paths(PathSelectors.regex("^((?!pub).)*$"))
13                .build()
14                .securitySchemes(securitySchemes())
15                .securityContexts(securityContexts());
16    }
17
18    @Bean(value = "pubApi")
19    public Docket pubApi() {
20        return new Docket(DocumentationType.SWAGGER_2)
21                .useDefaultResponseMessages(false)
22                .apiInfo(apiInfo())
23                .groupName(properties.getGroupName() + "-无认证")
24                .select()
25                .apis(getPredicate())
26                .paths(PathSelectors.regex("^.*pub.*$"))
27                .build();
28    }
29    
30    //拼接多路径扫描以实现多包扫描支持
31    private Predicate getPredicate() {
32        String[] split = properties.getBasePackage().split(",");
33        Predicate predicate = null;
34        for (String s : split) {
35            Predicate secPredicate = RequestHandlerSelectors.basePackage(s);
36            predicate = predicate == null ? secPredicate : Predicates.or(secPredicate, predicate);
37        }
38        return predicate;
39    }
40
41    private List<ApiKey> securitySchemes() {
42        return newArrayList(
43                new ApiKey(properties.getHeader(), properties.getHeader(), "header"));
44    }
45
46    private List<SecurityContext> securityContexts() {
47        return newArrayList(
48                SecurityContext.builder()
49                        .securityReferences(defaultAuth())
50                        .forPaths(PathSelectors.regex("^((?!pub).)*$"))
51                        .build()
52        );
53    }
54
55    private List<SecurityReference> defaultAuth() {
56        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
57        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
58        authorizationScopes[0] = authorizationScope;
59        return newArrayList(
60                new SecurityReference(properties.getHeader(), authorizationScopes));
61    }

SwaggerProperties 配置文件只是把变化的配置放到了配置文件中进行配置

这样,访问 http://{IP}:{port}/doc.html 地址,即可看到效果

2 访问控制

knife 提供了简单的 basic 认证,其中

登录访问:SecurityBasicAuthFilter、生产环境屏蔽:ProductionSecurityFilter

由于项目自定义了部分配置,为了统一,自己实现注入时机

 1@Bean
 2    @ConditionalOnMissingBean(SecurityBasicAuthFilter.class)
 3    @ConditionalOnProperty(name = "swagger.certifiable", havingValue = "true")
 4    public SecurityBasicAuthFilter securityBasicAuthFilter(SwaggerProperties properties) {
 5        return new SecurityBasicAuthFilter(properties.getCertifiable(), properties.getUsername(), properties.getPassword());
 6    }
 7
 8    @Bean
 9    @ConditionalOnMissingBean(ProductionSecurityFilter.class)
10    @ConditionalOnProperty(name = "swagger.prod", havingValue = "true")
11    public ProductionSecurityFilter productionSecurityFilter(SwaggerProperties properties) {
12        return new ProductionSecurityFilter(properties.getProd());
13    }

这样,在 SwaggerProperties 中配置相应的信息,即可实现相关功能

3 入参分组

在开发的时候,会遇到这样一个情况:

一个 VO 对象在新增的时候某些字段为必填,在更新的时候又非必填。比如用户新增和编辑功能,新增时 id 不是必填,编辑时是必须的,其他的字段如用户名等都是一样新增、编辑都为必填。

而在 swagger 中,不属于新增接口的 id 字段,就不应该显示到文档上,避免前端集成接口不知如何传参的问题

以前是新增、编辑使用不同的实体,或者编辑继承新增实体,再加上 id 字段,但是这样会造成项目中有很多的实体,类臃肿

基于此需求,可以借助 javax.validation.groups 分组功能以及@Validated 来实现,同时扩展 swagger 的功能,此处参考:https://blog.csdn.net/jianzhang11/article/details/119632467

3.1 自定义分组

 1import javax.validation.groups.Default;
 2
 3public interface ValidGroup extends Default {
 4    interface Create extends ValidGroup {
 5    }
 6
 7    interface Update extends ValidGroup {
 8    }
 9
10    interface Query extends ValidGroup {
11    }
12
13    interface Delete extends ValidGroup {
14    }
15}

3.2 使用

controller 层入参上添加分组信息,如:

新增:ValidGroup.Create.class

1public RestResult<String> insertUser(@RequestBody @Validated(ValidGroup.Create.class) UserBO user) {
2    return usersService.insertUser(user);
3}

编辑:ValidGroup.Update.class

1public RestResult<String> updateUser(@RequestBody @Validated(ValidGroup.Update.class) UserBO user) {
2    return usersService.updateUser(user);
3}

入参实体中:

1public class UserBO implements Serializable {
2    private static final long serialVersionUID = 5699245096095831445L;
3
4    @ApiModelProperty(value = "ID")
5    @Null(groups = ValidGroup.Create.class)
6    @NotNull(groups = ValidGroup.Update.class, message = "ID不可为空")
7    private Long id;
8}

这样,再访问新增、编辑接口,即可看到效果。


标题:spring boot项目集成 knife4j 2.0.5并实现入参分组校验显示
作者:kangaroo1122
地址:https://kangaroohy.com/articles/2021/09/19/1632019364298.html
声明:如非特别说明,版权归kangaroo1122 所有,转载请注明出处,谢谢!
签名:No pains, no gains.