在Java中,让Swagger产生一个更符合我们诉求的描述文档,并根据需要决定显示或隐藏指定内容需要一定的功夫。那么,这篇文档就和大家聊聊如何用好swagger,让它真正成为我们项目交付过程中的法宝。更改接口文档的通用标题和描述默认情况下,Swagger接口整个文档的名称和描述都是通用值,这样会让人拿到文档后一头雾水,分不清是哪个项目,哪个系统以及哪个服务给它提供了接口,不知道是哪个团队负责接口,哪个开发者维护的。例如如下:为了体现接口文档的专业性,方便大家了解接口文档的系统、对应版本、维护团队等信息,我们可以根据需要在代码中自定义相关内容.例如:@BeanpublicDocketcreateRestApi(){ApiInfoapiInfo=newApiInfoBuilder().title("资源管理系统接口文档").description("APP/WEB调用资源管理模块接口的详细文档说明").version("v1.0.0").contact(newContact("架构启蒙","https://juejin.cn/user/1028798616709294","veezean@outlook.com")).termsOfServiceUrl("https://juejin.cn/user/1028798616709294").license("ApacheLicense").licenseUrl("http://xxx").build();返回新的Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select()。build();}重启查看界面,可以发现界面上的相关内容已经改成了我们自定义的内容,是不是比改之前更加清晰专业了?上述swagger支持自定义描述字段信息,整理如下:字段含义描述title文档接口文档标题description详细接口文档整体描述说明版本接口文档对应的版本信息termsOfServiceUrl团队提供该接口文档的团队对应的url地址contact负责该部分接口的联系方式,包括name,email,homepageurladdress等license指定license协议的版本后面是接口licenseUrllicense协议的详细介绍后面是接口url地址根据需要显示/隐藏相关接口内容需要根据实际情况灵活控制文件中需要写入的接口内容,以及文件中的字段信息接口的请求响应主体——因为不是所有的接口都提供系统中的ded需要体现在接口文档中,暴露给调用者知道你知道,比如有一些系统状态监控接口,只需要在内部使用。对于Swagger来说,在生成接口文档时,默认是扫描所有@Controller中的所有接口方法,并显示在文档中,但其他的也考虑到了实际应用中按需隐藏或显示接口内容的需求,以及提供了多种不同的方式来支持它。下面我们一起来看看吧。为单个接口隐藏在单个接口方法上面添加@ApiOperation注解,指定hidden=true对swagger接口隐藏接口:@GetMapping("/test")@ApiOperation(value="internaltestInterface",hidden=true)publicStringtest(){return"OK";}启动流程,查看Swagger接口,发现接口上没有出现接口:如果整个Controller下的所有接口都隐藏接口在整个Controller类中class都需要隐藏,可以在Conntroller类中加上@ApiIgnore注解。@RestController@RequestMapping("/test")@ApiIgnorepublicclassTestController{//...ignore...}修改后重启进程,然后打开swagger界面,发现整个TestController类的界面不显示。这里补充一下,因为用来描述Controller类接口含义的注解@Api也有一个hidden属性,看看它的源码注解,如果设置hidden=true,应该也会把Controller类隐藏为一个所有的。但实际上,测试发现并没有生效。使用这个要小心(基于swagger2.7.0版本测试,不确定是不是BUG)。@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Inheritedpublic@interfaceApi{/***隐藏该资源下的操作。**@returntrueiftheapishouldbehiddenfromtheswaggerdocumentation*/booleanhidden()defaultfalse;}只显示指定包路径下的接口。我们的项目中经常会依赖或者引用一些第三方的jar包,有时候这些第三方的jar包也会提供一些接口,这些接口也会出现在我们的接口文档中。这样一来,就会显得接口文档中有很多不确定的内容。例如:因为业务代码中没有提供这部分逻辑,所以我们无法通过修改源码,通过上述方式添加hidden=true来控制其不显示。这时候就需要具备根据包进行白名单控制的能力。Swagger也支持基于给定的basePackage和路径的组合控制,只显示给定包下指定路径下的接口。@BeanpublicDocketcreateRestApi(){ApiInfoapiInfo=newApiInfoBuilder().title("资源管理系统接口文档").description("APP/WEB调用资源管理模块接口的详细文档说明").version("v1.0.0").build();ApiSelectorBuilderselectorBuilder=(newDocket(DocumentationType.SWAGGER_2)).apiInfo(apiInfo).select();selectorBuilder.apis(RequestHandlerSelectors.basePackage("com.jiagouwudao.resmanage"));selectorBuilder.paths(PathSelectors.any());returnselectorBuilder.build();}这样可以保证接口文档中出现的所有接口都是我们自己定义的接口。重启并刷新界面,你会发现swagger界面上只显示了指定包目录下的Controller界面。隐藏响应中不愿暴露的属性在项目开发过程中,如果我们的代码没有强制性的VO和DO分区,为了减少编码量,我们可能会使用同一个对象进行内部处理和外部交互.例如:定义一个OperateLog对象,它是数据库中T_OPERATE_LOG表对应的实体类,用于记录每个用户的操作行为;同时作为recordOperateLog接口的请求体,传递需要记录的用户操作信息。上例中:作为数据表实体类进行逻辑处理时,需要使用唯一主键id信息作为recordOperateLog接口的请求体时,调用者不需要指定这条记录的id值(ID值会在DB中存储时,DB会自动生成一个唯一的自增主键)在这种场景下,我们希望在提供的接口文档中,id字段不应该体现在字段描述中recordOperateLog接口的requestbody,避免调用者混淆,不知道调用时id应该如何分配。我们可以通过在指定字段上添加@ApiModelProperty注解并指定hidden=true将其隐藏在接口文档中。例如:@Data@ApiModel("操作记录信息")publicclassOperateLog{@ApiModelProperty(value="记录唯一ID,无意义",hidden=true)privatelongid;@ApiModelProperty("操作类型,取值说明:1,添加;2,更新;3,删除;4,查询")privateintoperateType;@ApiModelProperty("操作用户")privateString用户;@ApiModelProperty(value="operationdetails")privateStringdetail;}那么接口中的接口文档是不会显示id的相关信息的(注意:只是接口文档不反映,不会影响实际值)特定请求或响应中的此字段)。关闭生产环境的swagger考虑到生产环境的安全性,对于一些比较重要的系统,我们一般都不愿意暴露生产环境的接口文件,以免给系统的运行带来隐患。在SpringBoot项目中,我们会针对不同的环境提供不同的配置文件,然后通过--spring.active.profile来指定启动时加载哪些配置。如果我们需要使Swagger可访问,我们可以通过在代码中添加@EnableSwagger2注解来实现。如果限制在开发或测试环境只允许swagger访问,生产环境不允许开启,只需要让@EnableSwagger2注解的类根据当前运行环境决定是否加载即可。借助SpringBoot提供的@Profile注解,我们可以这样实现:@Configuration@EnableSwagger2@Profile({"DEV","TEST"})publicclassSwaggerConfig{}这样,SwaggerConfig类就可以不当profile=PROD时会被加载,swagger的开关不会打开。使用--spring.active.profile=PROD启动进程,尝试访问swagger界面,发现打不开:为Swagger换皮肤。默认的swagger界面显示的是居中列出的所有内容,然后需要逐层展开。上面的操作并不太方便,整体的界面风格也不太符合一个“文档”的外观。为了提升用户体验,可以使用开源的knife4j框架让swagger更好用。使用方法非常简单。在现有swagger依赖的基础上,在pom.xml中添加如下引用依赖:
