Swagger简介
Swagger是一个规范和完整的API框架,可用于生成、描述、调用Restful风格的Web服务的接口文档。如果你在SpringBoot中使用的话,在项目启动后可以自动生成在线可调用的API文档,非常方便!
在SpringBoot中集成
首先在pom.xml引入依赖
<!--springfox swagger官方Starter-->
<dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version>
</dependency>
在apllication中配置文件
spring:mvc:pathmatch:matching-strategy: ANT_PATH_MATCHER
增加一个兼容性Bean的控制
添加Swagger的Java配置,配置好Api信息和需要生成接口文档的类扫描路径,注意在SpringBoot2.6.x以上版本整合时由于兼容性问题需要配置一个BeanPostProcessor的Bean;
/*** @description Swagger相关配置*/
@Configuration
public class Swagger2Config {@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.macro.mall.tiny.controller")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("SwaggerUI演示").description("mall-tiny").contact(new Contact("macro", null, null)).version("1.0").build();}@Beanpublic static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {return new BeanPostProcessor() {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {customizeSpringfoxHandlerMappings(getHandlerMappings(bean));}return bean;}private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {List<T> copy = mappings.stream().filter(mapping -> mapping.getPatternParser() == null).collect(Collectors.toList());mappings.clear();mappings.addAll(copy);}@SuppressWarnings("unchecked")private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {try {Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");field.setAccessible(true);return (List<RequestMappingInfoHandlerMapping>) field.get(bean);} catch (IllegalArgumentException | IllegalAccessException e) {throw new IllegalStateException(e);}}};}
}
访问地址
访问API文档信息,访问地址:http://localhost:8088/swagger-ui/
就可以看到具体的信息
开始使用
相关注解
相关配置
以下是它的一些常用配置
springfox:documentation:# 是否启用Swagger扫描代码生成文档enabled: trueopen-api:# 是否启用Swagger的open-apienabled: falseswagger-ui:# 是否启用Swagger的Web UIenabled: true# 配置文档基础路径,此时路径为:/doc/swagger-ui/index.htmlbase-url: /doc
基本使用
使用时我们只需把Swagger对应的注解添加到接口方法上即可
1.@Api
value:简要描述该类的作用。
tags:用于给 API 进行分组,通常用于 UI 界面展示。
@Api(value = "用户管理接口", tags = {"用户管理"})
public class UserController { // ...
}
2.@ApiOperation
value:简要描述该操作的主要功能。
notes:对该操作的详细说明或注意事项。
@ApiOperation(value = "获取用户信息", notes = "根据用户ID获取用户详细信息")
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable String id) { // ...
}
3. @ApiModel
实体类上的注解
@ApiModel(value = "PmsBrand",description = "商品品牌")
public class PmsBrand implements Serializable {@ApiModelProperty(value = "主键ID")private Long id;@ApiModelProperty(value = "名称")private String name;@ApiModelProperty(value = "首字母")private String firstLetter;@ApiModelProperty(value = "排序")private Integer sort;@ApiModelProperty(value = "是否为品牌制造商:0->不是;1->是")private Integer factoryStatus;@ApiModelProperty(value = "是否显示")private Integer showStatus;@ApiModelProperty(value = "产品数量")private Integer productCount;@ApiModelProperty(value = "产品评论数量")private Integer productCommentCount;@ApiModelProperty(value = "品牌logo")private String logo;@ApiModelProperty(value = "专区大图")private String bigPic;@ApiModelProperty(value = "品牌故事")private String brandStory;
}
结合Spring Security使用
我们经常会在项目中使用Spring Security实现登录认证,接下来我们来讲下如何使用Swagger整合Spring Security,实现访问需要登录认证的接口。
如何访问需要登录认证的接口?只需在访问接口时添加一个合法的Authorization请求头即可,下面是Swagger相关配置
/*** @description Swagger相关配置(带认证)*/
@Configuration
public class Swagger2Config {@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.macro.mall.tiny.controller")).paths(PathSelectors.any()).build()//添加登录认证.securitySchemes(securitySchemes()).securityContexts(securityContexts());}private List<SecurityScheme> securitySchemes() {//设置请求头信息List<SecurityScheme> result = new ArrayList<>();ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");result.add(apiKey);return result;}private List<SecurityContext> securityContexts() {//设置需要登录认证的路径List<SecurityContext> result = new ArrayList<>();result.add(getContextByPath("/brand/.*"));return result;}private SecurityContext getContextByPath(String pathRegex) {return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex(pathRegex)).build();}private List<SecurityReference> defaultAuth() {List<SecurityReference> result = new ArrayList<>();AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;result.add(new SecurityReference("Authorization", authorizationScopes));return result;}
}
我们需要在Spring Security中配置好Swagger静态资源的无授权访问,比如首页访问路径/swagger-ui/
/*** @auther macrozheng* @description SpringSecurity的配置* @date 2018/4/26* @github https://github.com/macrozheng*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {@Lazy@Autowiredprivate UmsAdminService adminService;@Autowiredprivate RestfulAccessDeniedHandler restfulAccessDeniedHandler;@Autowiredprivate RestAuthenticationEntryPoint restAuthenticationEntryPoint;@BeanSecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {httpSecurity.csrf()// 由于使用的是JWT,我们这里不需要csrf.disable().sessionManagement()// 基于token,所以不需要session.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers(HttpMethod.GET, // 允许对于网站静态资源的无授权访问"/","/swagger-ui/","/*.html","/favicon.ico","/**/*.html","/**/*.css","/**/*.js","/swagger-resources/**","/v2/api-docs/**").permitAll().antMatchers("/admin/login")// 对登录注册要允许匿名访问.permitAll().antMatchers(HttpMethod.OPTIONS)//跨域请求会先进行一次options请求.permitAll().anyRequest()// 除上面外的所有请求全部需要鉴权认证.authenticated();// 禁用缓存httpSecurity.headers().cacheControl();// 添加JWT filterhttpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);//添加自定义未授权和未登录结果返回httpSecurity.exceptionHandling().accessDeniedHandler(restfulAccessDeniedHandler).authenticationEntryPoint(restAuthenticationEntryPoint);return httpSecurity.build();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic UserDetailsService userDetailsService() {//获取登录用户信息return username -> {AdminUserDetails admin = adminService.getAdminByUsername(username);if (admin != null) {return admin;}throw new UsernameNotFoundException("用户名或密码错误");};}@Beanpublic JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {return new JwtAuthenticationTokenFilter();}}