工程创建
当然,首先是创建一个Spring Boot项目,加入web依赖,创建成功后,加入两个Swagger2相关的依赖,完整的依赖如下:
<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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Swagger2配置
Swagger2的配置也是比较容易的,在项目创建成功之后,只需要开发者自己提供一个Docket的Bean即可,如下:
@Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .pathMapping("/") .select() .apis(RequestHandlerSelectors.basePackage("com.nvn.controller")) .paths(PathSelectors.any()) .build().apiInfo(new ApiInfoBuilder() .title("SpringBoot整合Swagger") .description("SpringBoot整合Swagger,详细信息......") .version("9.0") .contact(new Contact("啊啊啊啊","blog.csdn.net","aaa@gmail.com")) .license("The Apache License") .licenseUrl("http://www.baidu.com") .build()); } }
这里提供一个配置类,首先通过@EnableSwagger2注解启用Swagger2,然后配置一个Docket Bean,这个Bean中,配置映射路径和要扫描的接口的位置,在apiInfo中,主要配置一下Swagger2文档网站的信息,例如网站的title,网站的描述,联系人的信息,使用的协议等等。
如此,Swagger2就算配置成功了,非常方便。
此时启动项目,输入http://localhost:8080/swagger-ui.html,能够看到如下页面,说明已经配置成功了:
创建接口
接下来就是创建接口了,Swagger2相关的注解其实并不多,而且很容易懂,下面我来分别向小伙伴们举例说明:
@RestController @Api(tags = "用户管理相关接口") @RequestMapping("/user") public class UserController { @PostMapping("/") @ApiOperation("添加用户的接口") @ApiImplicitParams({ @ApiImplicitParam(name = "username", value = "用户名", defaultValue = "李四"), @ApiImplicitParam(name = "address", value = "用户地址", defaultValue = "深圳", required = true) } ) public RespBean addUser(String username, @RequestParam(required = true) String address) { return new RespBean(); } @GetMapping("/") @ApiOperation("根据id查询用户的接口") @ApiImplicitParam(name = "id", value = "用户id", defaultValue = "99", required = true) public User getUserById(@PathVariable Integer id) { User user = new User(); user.setId(id); return user; } @PutMapping("/{id}") @ApiOperation("根据id更新用户的接口") public User updateUserById(@RequestBody User user) { return user; } }
这里边涉及到多个API,我来向小伙伴们分别说明:
- @Api注解可以用来标记当前Controller的功能。
- @ApiOperation注解用来标记一个方法的作用。
- @ApiImplicitParam注解用来描述一个参数,可以配置参数的中文含义,也可以给参数设置默认值,这样在接口测试的时候可以避免手动输入。
- 如果有多个参数,则需要使用多个@ApiImplicitParam注解来描述,多个@ApiImplicitParam注解需要放在一个@ApiImplicitParams注解中。
- 需要注意的是,@ApiImplicitParam注解中虽然可以指定参数是必填的,但是却不能代替@RequestParam(required = true),前者的必填只是在Swagger2框架内必填,抛弃了Swagger2,这个限制就没用了,所以假如开发者需要指定一个参数必填,@RequestParam(required = true)注解还是不能省略。
- 如果参数是一个对象(例如上文的更新接口),对于参数的描述也可以放在实体类中。例如下面一段代码:
@ApiModel public class User { @ApiModelProperty(value = "用户id") private Integer id; @ApiModelProperty(value = "用户名") private String username; @ApiModelProperty(value = "用户地址") private String address; //getter/setter }
config 配置实例(实战已经用过的配置)
package com.kmair.offical.member.config; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import springfox.documentation.RequestHandler; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 @Profile({ "dev", "test", "predeploy" }) public class SwaggerConfig { private ApiInfo apiInfo() { return new ApiInfoBuilder().title("api").description("仅供测试,开发,产品参考") // 服务条款网址 .termsOfServiceUrl("").version("1.0") .contact(new Contact("name", "http://name.cn", "ssstt.com")).build(); } @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select() // 自行修改为自己的包路径 .apis(SwaggerConfig.basePackage( "com.kmair.offical.common,com.kmair.offical.member")) .paths(PathSelectors.any()).build(); } public static Predicate<RequestHandler> basePackage(final String basePackage) { return input -> declaringClass(input).transform(handlerPackage(basePackage)).or(true); } private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) { return input -> { for (String strPackage : basePackage.split(",")) { boolean isMatch = input.getPackage().getName().startsWith(strPackage); if (isMatch) { return true; } } return false; }; } private static Optional<? extends Class<?>> declaringClass(RequestHandler input) { return Optional.fromNullable(input.declaringClass()); } }
解决不能访问的问题
/** * LY.com Inc. * Copyright (c) 2004-2017 All Rights Reserved. */ package com.kmair.offical.member.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration @EnableWebMvc @ComponentScan(basePackages = "com.kmair.offical") public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 解决swagger-ui不能访问问题 registry.addResourceHandler("swagger-ui.html") .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); super.addResourceHandlers(registry); } // @Override // public void addCorsMappings(CorsRegistry registry) { // // 设置允许跨域访问 // registry.addMapping("/**") // .allowedHeaders("*") // .allowedMethods("*") // .allowedOrigins("*"); // } /*@Bean public GsonHttpMessageConverter responseBodyConverter() { GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter(); gsonHttpMessageConverter.setDefaultCharset(Charset.forName("UTF-8")); gsonHttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON_UTF8)); gsonHttpMessageConverter.setGson(new GsonBuilder().serializeNulls().setDateFormat("yyyy-MM-dd").create()); return gsonHttpMessageConverter; } @Bean RiskHandlerInterceptor riskInterceptor() { return new RiskHandlerInterceptor(); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { super.configureMessageConverters(converters); converters.add(responseBodyConverter()); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(riskInterceptor()).addPathPatterns("/**"); }*/ }
跨域配置
package com.kmair.offical.member.config; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; @Configuration public class CorsConfig { @Bean public FilterRegistrationBean corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允许cookies跨域 config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin config.addAllowedHeader("*");// #允许访问的头信息,*表示全部 config.setMaxAge(1800L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许 source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); // 跨域的过滤器要放在第一位 return bean; } }
在Security中的配置
如果我们的Spring Boot项目中集成了Spring Security,那么如果不做额外配置,Swagger2文档可能会被拦截,此时只需要在Spring Security的配置类中重写configure方法,添加如下过滤即可:
@Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers("/swagger-ui.html") .antMatchers("/v2/**") .antMatchers("/swagger-resources/**"); }