背景:
对于前后端分离的项目,前后端的工程师协同开发,在这种开发模式下,维持一份及时更新且完整的 Rest API 文档将会极大的提高我们的工作效率。
传统意义上的文档都是后端开发人员手动编写的,相信大家也都知道这种方式很难保证文档的及时性,这种文档久而久之也就会失去其参考意义,反而还会加大我们的沟通成本。而Swagger 给我们提供了一个全新的维护 API 文档的方式,其优点如下:
- 使用方便,只需要少量的注解,Swagger 就可以根据代码自动生成 API 文档,很好的保证了文档的时效性。
- 可创建自动化测试,可直接对功能模块实现单元测试
配置:
-
添加maven依赖:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
-
配置类:
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi() { Docket docket = new Docket(DocumentationType.SWAGGER_2); // ApiInfoBuilder 用于在Swagger界面上添加各种信息 ApiInfoBuilder builder = new ApiInfoBuilder(); builder.title("在线办公系统Swagger测试"); ApiInfo apiInfo = builder.build(); docket.apiInfo(apiInfo); // ApiSelectorBuilder 用来设置哪些类中的方法会生成到REST API中 ApiSelectorBuilder selectorBuilder = docket.select(); selectorBuilder.paths(PathSelectors.any()); //所有包下的类 //使用@ApiOperation的方法会被提取到REST API中 selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)); docket = selectorBuilder.build(); /* * 下面的语句是开启对JWT的支持,当用户用Swagger调用受JWT认证保护的方法, * 必须要先提交参数(例如令牌) */ //存储用户必须提交的参数 List<ApiKey> apikey = new ArrayList(); //规定用户需要输入什么参数 apikey.add(new ApiKey("token", "token", "header")); docket.securitySchemes(apikey); //如果用户JWT认证通过,则在Swagger中全局有效 AuthorizationScope scope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] scopeArray = {scope}; //存储令牌和作用域 SecurityReference reference = new SecurityReference("token", scopeArray); List refList = new ArrayList(); refList.add(reference); SecurityContext context = SecurityContext.builder().securityReferences(refList).build(); List cxtList = new ArrayList(); cxtList.add(context); docket.securityContexts(cxtList); return docket; } }
-
常用注解说明
@Api 注解可以用来标记 Controller 的功能 @ApiOperation 注解用来标记一个方法的作用 @ApilmplicitParam 注解用来描述一个参数,可以配置参数的中文含义,也可以给参数设置默认值,这样在接口测试的时候可以避免手动输入 @ApilmplicitParams 如果有多个参数,则需要使用多个 @ApilmplicitParam 注解来描述, 多个 @ApilmplicitParam 注解需要放在一个 @ApilmplicitParams 注解中 @ApiModel 如果参数是一个对象,则需要在对象所在的类上加上此注解 @ApiModelProperty 如果参数是一个对象,则需要在对应的属性上加上此注解,还需要在对象所在的类上加上 @ApiModel @ApiIgnore 注解标识此参数可以忽略
使用:
-
创建测试类:
@RestController @RequestMapping("/test") //@Api:放在请求的类上,与 @Controller 并列,说明类的作用,如用户模块,订单类等。 @Api("测试Web接口") public class TestController { // @GetMapping("/sayHello") @PostMapping("/sayHello")//因为要传参,所以需要用postmapping //@ApiOperation:方法的说明 @ApiOperation("最简单的测试方法") public R sayHello(@Valid @RequestBody TestSayHelloForm form) { return R.ok().put("message", "Hello," + form.getName()); } }
-
访问:
-
因为配置了Shiro做鉴权,所以对于Swagger的访问路径应该放开权限
@Configuration public class ShiroConfig { //... @Bean("shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager,OAuth2Filter oAuth2Filter) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); //oauth过滤 Map<String, Filter> filters = new HashMap<>(); filters.put("oauth2", oAuth2Filter); shiroFilter.setFilters(filters); Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/druid/**", "anon"); filterMap.put("/app/**", "anon"); filterMap.put("/sys/login", "anon"); //------Swagger权限放行------ filterMap.put("/webjars/**", "anon"); filterMap.put("/swagger/**", "anon"); filterMap.put("/v2/api-docs", "anon"); filterMap.put("/swagger-ui.html", "anon"); filterMap.put("/swagger-resources/**", "anon"); filterMap.put("/test/**", "anon"); //------------------------ filterMap.put("/captcha.jpg", "anon"); filterMap.put("/user/register", "anon"); filterMap.put("/user/login", "anon"); filterMap.put("/**", "oauth2"); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; } //... }
-
根据路径配置可进行访问,本项目的Swagger接口调试访问路径为:
http://localhost:8080/emos-wx-api/swagger-ui.html
-
-
使用:测试sayHello方法
-
TestSayHelloForm
//@ApiModel:用于JavaBean上面,表示一个JavaBean @ApiModel @Data public class TestSayHelloForm { //非空 @NotBlank //正则表达式:是要中文,且在2~15个汉字之间 //使用了validation框架测试 @Pattern(regexp = "^[\\u4e00-\\u9fa5]{2,15}$") // @ApiModelProperty:用在JavaBean的属性上面,说明属性的含义 @ApiModelProperty("姓名") private String name; }
-
点击具体接口的Try it out即可测试
-
因为在配置中增加了JWT的认证保护,所以没有存token时无法进行接口接口测试
docket.securitySchemes(apikey);
-
存入token才能进行测试
-
成功单元测试:
-