springboot will encounter various problems in an integrated swagger in:
1, swagger authentication interface (such as setting the token header, the interface to intercept process).
2, swagger for physical property parse (attribute notes pojo class can not be resolved).
3, swagger be unified response code (code identification state it, a successful response 200, in response to parsing the body).
4, swagger provided an interface common parameter (for each parameter in a uniform interfaces are present).
The following configuration information to solve the problem
First, the introduction of dependencies
Please refer to the updated version dependencies or before use
An updated version of the address: the interface dependent JAR https://mvnrepository.com/artifact/io.springfox/springfox-swagger2
ui Yo赖Jar Https://Mvnrepository.Com/artifact/io.Springfox/springfox-swagger-ui
<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>
Second, create a swagger configuration class
1, global parameters
2, the overall response parameter, the value of each interface there is a response, to facilitate communication
3, set the security certification
Click to authorize button to enter this information each time debug interface will transmit the response information
Without further ado! The configuration code
package com.example.config.swagger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.web.bind.annotation.RequestMethod; import springfox.documentation.builders.*; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; importspringfox.documentation.swagger2.annotations.EnableSwagger2; Import java.util.ArrayList; Import java.util.List; / ** * * @author niunafei * * @Profile annotation identifies loaded using the dev and test file * / @Configuration @ EnableSwagger2 // @Profile ({ "dev", "Test"}) public class SwaggerConfig { @Bean public Docket No. createRestApi () { return new new Docket No. (DocumentationType.SWAGGER_2) .groupName ( "Spring-Test-interface" ) // load configuration information .apiInfo (apiInfo ()) // set global parameters .globalOperationParameters (globalParamBuilder ()) // set the global response parameters .globalResponseMessage (RequestMethod.GET, ResponseBuilder ()) .globalResponseMessage (RequestMethod.POST, ResponseBuilder ()) .globalResponseMessage (RequestMethod.PUT, ResponseBuilder () ) .globalResponseMessage (RequestMethod.DELETE, ResponseBuilder ()) .Select () // load swagger scan package .apis (RequestHandlerSelectors.basePackage ( "the com.example" )) .paths (PathSelectors.any ()). Build () / / set safety certification .securitySchemes (security ()); } / ** * Create initialization information acquired swagger * @return * / Private ApiInfo apiInfo () { Business Card Contact = new new Business Card ( "niunafei", "", "[email protected]" ); return new new . ApiInfoBuilder () title ( "swagger test documents") .description ( "dev by niunafei" ) .contact (Business Card) .version ( "1.0.0" ) .build (); } / ** * security authentication parameter * @return * / Private List <apiKey> Security () { List <apiKey>list=new ArrayList<>(); list.add(new ApiKey("token", "token", "header")); return list; } /** * 构建全局参数列表 * @return */ private List<Parameter> globalParamBuilder(){ List<Parameter> pars = new ArrayList<>(); pars.add(parameterBuilder("token","令牌","string","header",false).build()); return pars; } /** * 创建参数 * @return */ private ParameterBuilder parameterBuilder(String name,String desc,String type ,String parameterType,boolean required) { ParameterBuilder tokenPar = new ParameterBuilder(); tokenPar.name(name).description(desc).modelRef(new ModelRef(type)).parameterType(parameterType).required(required).build(); return tokenPar; } /** * 创建全局响应值 * @return */ private List<ResponseMessage> responseBuilder() { List<ResponseMessage> responseMessageList = new ArrayList<>(); responseMessageList.add(new new . ResponseMessageBuilder () code (200 is) .message ( "Success Response" ) .build ()); responseMessageList.add ( new new . ResponseMessageBuilder () code (500) .message ( "Internal Server Error" ) .build ()) ; return responseMessageList; } }
The above code @Profile ({ "dev", " test"}) annotation class is loaded in the development environment and test environment when the production environment for online security is not recommended to create swagger of bean
Third, the introduction of the configuration file, and configure scan classes, but still can not access the page swagger, this time to consider mvc specify the access path springboot
addResourceHandlers method has been specified swagger-ui Access Page path
Meanwhile, the configuration addressed the issue of cross-domain mvc
AD dCorsMappings cross-domain method is provided for intercepting the execution method addInterceptors
corsFilter can solve all cross-domain issues
package com.example.config.mvc; //import com.example.config.interceptor.LoginInterceptor; import org.springframework.beans.factory.annotation.Autowired; 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; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** * @author niunafei * @function * @email [email protected] * @date 2019/6/28 下午12:28 */ @Configuration public class WebMvcConfigurerAdapter extends WebMvcConfigurationSupport { // @Autowired // private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 添加拦截接口请求处理, // registry.addInterceptor(loginInterceptor).addPathPatterns("/api/**"); } @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { //定向swagger 位置 registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); * * * after the interception to solve cross-domain/ ** }@param Registry * / @Override public void addCorsMappings (CorsRegistry Registry) { registry.addMapping ( "/ **"). allowCredentials ( to true ) .allowedHeaders ( "*"). allowedOrigins ( "*"). allowedMethods ( "the GET" , "the POST", "the PUT", "the OPTIONS" ); } / ** * pretreatment process knockdown detected cross-domain authorization problems * * @return * / @Bean public corsFilter corsFilter () { UrlBasedCorsConfigurationSource Source = new new UrlBasedCorsConfigurationSource (); source.registerCorsConfiguration("/ **" , corsConfig ()); return new new CorsFilter (Source); } / ** * @return * / Private CorsConfiguration corsConfig () { CorsConfiguration corsConfiguration = new new CorsConfiguration (); // request three common configuration, * allow all representatives, then you can also customize the attributes (such as header only with what can only be post way, etc.) corsConfiguration.addAllowedOrigin ( "*" ); corsConfiguration.addAllowedHeader ( "*" ); corsConfiguration.addAllowedMethod ( "*" ); corsConfiguration.setAllowCredentials ( to true ); corsConfiguration.setMaxAge(3600L); return corsConfiguration; } }
Four, swagger return of scan
Interface Layer use generics to return, unified personally defined class return
ApiModel entity is scanned annotations generating swagger
ApiModelProperty is an attribute comment
ApiHttpCode enumeration response is a class value
package com.example.config.response; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; /** * @author niunafei * @function * @email [email protected] * @date 2019/6/28 下午2:00 */ @ApiModel() public class ApiResult<T> { private static final Object RESULT_OBJECT=new Object(); @ApiModelProperty(value = "编码", name = "code", dataType = "int", example = "200") private Integer code; @ApiModelProperty(value = "提示", name = "msg", dataType = "string", example = "success") private String msg; @ApiModelProperty(value = "内容", name = "data", dataType = "t") private T data; public ApiResult() { } public ApiResult(ApiHttpCode code, T data) { this.code = code.getCode(); this.msg = code.getDesc(); this.data = data; } public ApiResult(Integer code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public static ApiResult<Object> ok() { return ApiResult.ok(ApiHttpCode.SUCCESS, RESULT_OBJECT); } public static <T> ApiResult<T> ok(T data) { return ApiResult.ok(ApiHttpCode.SUCCESS, data); } public static <T> ApiResult<T> ok(ApiHttpCode code, T data) { return ApiResult.ok(code.getCode(), code.getDesc(), data); } public static <T> ApiResult<T> ok(Integer code, String msg, T data) { return new ApiResult(code, msg, data); } public static ApiResult<Object> error() { return ApiResult.error(ApiHttpCode.ERROR, new Object()); } public static <T> ApiResult<T> error(T data) { return ApiResult.error(ApiHttpCode.ERROR, data); } public static <T> ApiResult<T> error(ApiHttpCode code) { return ApiResult.error(code.getCode(),code.getDesc(),null); } public static <T> ApiResult<T> error(ApiHttpCode code, T data) { return ApiResult.error(code.getCode(), code.getDesc(), data); } public static <T> ApiResult<T> error(Integer code, String msg) { return ApiResult.error(code, msg, null); } public static <T> ApiResult<T> error(Integer code, String msg, T data) { return new ApiResult(code, msg, data); } public Integer getCode() { return code; } public String getMsg() { return msg; } public T getData() { return data; } }
ApiHttpCode枚举类
package com.example.config.response; /** * @author niunafei * @function * @email [email protected] * @date 2019/6/28 下午2:02 */ public enum ApiHttpCode { /** * 响应成功 */ SUCCESS(200, "OK"), /** * 服务器异常 */ ERROR(500, "ERROR"), /** * 未授权访问 */ UNAUTHORIZED(401, "访问未授权"); private int code; private String desc; ApiHttpCode(int code, String desc) { this.code = code; this.desc = desc; } public int getCode() { return code; } public String getDesc() { return desc; } public static ApiHttpCode valueOf(int value) { for (ApiHttpCode role : ApiHttpCode.values()) { if (role.code == value) { return role; } } return null; } }
五、接口层引用
@Api注解添加
接口方法上添加@ApiOperation 才可以生成文档
@ApiImplicitParams 用来定义接口参数,并指定描述的,
@ApiResponses 用来定义添加额外的响应值,与配置类中的全局响应功能一致。
访问接口页面 http://localhost:8888/spring-demo/swagger-ui.html
访问格式:http://IP地址或域名:端口/应用名称/swagger-ui.html
无关后话,与swagger 无关:授权检测的创建继承HandlerInterceptorAdapter 方法
package com.example.config.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author niunafei * @function * @email [email protected] * @date 2019/6/28 下午12:31 */ @Component public class LoginInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //未开启权限检测 跳过 return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }