springboot 集成完整的swagger2


 

springboot 在集成swagger中會不會遇到各種問題:

1、swagger  進行接口鑒權(比如設置header的token,接口進行攔截處理)。

2、swagger 進行實體屬性解析(pojo類的屬性注解無法解析)。

3、swagger 進行響應碼統一(code狀態嗎標識、200響應成功,響應體解析)。

4、swagger 設置接口共用參數(統一每個接口都存在的參數)。 

以下是解決問題配置信息

一、引入依賴包

      使用之前請更新或直接引用該版本依賴包

        更新版本地址:接口依賴jar https://mvnrepository.com/artifact/io.springfox/springfox-swagger2

                              ui   依賴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>

 

二、創建swagger 配置類

  1、全局參數

        

    2、全局響應參數,每個接口都存在響應值,方便溝通

        

  3、設置安全認證

   點擊 authorize 按鈕輸入驗證信息,則每次調試接口都會傳響應的信息

      

 廢話少說!上配置代碼

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;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;


/**
 *
 * @author niunafei
 *
 * @Profile 注解 標識加載在dev和test文件使用
 */
@Configuration
@EnableSwagger2
//@Profile({"dev", "test"})
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("spring-test-interface")
                //加載配置信息
                .apiInfo(apiInfo())
                //設置全局參數
                .globalOperationParameters(globalParamBuilder())
                //設置全局響應參數
                .globalResponseMessage(RequestMethod.GET,responseBuilder())
                .globalResponseMessage(RequestMethod.POST,responseBuilder())
                .globalResponseMessage(RequestMethod.PUT,responseBuilder())
                .globalResponseMessage(RequestMethod.DELETE,responseBuilder())
                .select()
                //加載swagger 掃描包
                .apis(RequestHandlerSelectors.basePackage("com.example"))
                .paths(PathSelectors.any()).build()
                //設置安全認證
                .securitySchemes(security());

    }

    /**
     * 獲取swagger創建初始化信息
     * @return
     */
    private ApiInfo apiInfo() {
        Contact contact = new Contact("niunafei", "", "niunafei0315@163.com");
        return new ApiInfoBuilder().title("swagger 測試文檔").description("dev by niunafei").contact(contact)
                .version("1.0.0").build();
    }

    /**
     * 安全認證參數
     * @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 ResponseMessageBuilder().code(200).message("響應成功").build());
        responseMessageList.add(new ResponseMessageBuilder().code(500).message("服務器內部錯誤").build());
        return responseMessageList;
    }

}

  以上代碼中 @Profile({"dev", "test"})注解是在開發環境和測試環境的時候加載該類,線上生產環境為安全不建議創建swagger的bean

 三、引入配置文件,並且配置好掃描類,但是仍然不能訪問swagger 頁面,這時候請考慮springboot的mvc指定訪問路徑

   addResourceHandlers 方法中已經指定swagger-ui訪問頁的路徑

   同時該配置中處理了mvc 跨域的問題

     addCorsMappings 方法中是在攔截 addInterceptors 方法執行后進行的跨域設置
     corsFilter可以解決所有跨域問題
 
        
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 niunafei0315@163.com
 * @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/");
    }

    /**
     * 攔截后的跨域解決
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowCredentials(true).allowedHeaders("*").allowedOrigins("*").allowedMethods("GET",
                "POST", "PUT", "OPTIONS");
    }

    /**
     * 處理攔截前處理檢測 授權跨域問題
     *
     * @return
     */
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig());
        return new CorsFilter(source);
    }

    /**
     * @return
     */
    private CorsConfiguration corsConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 請求常用的三種配置,*代表允許所有,當時你也可以自定義屬性(比如header只能帶什么,只能是post方式等等)
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setMaxAge(3600L);
        return corsConfiguration;
    }

}

 

四、swagger 返回掃描的問題

 接口層請使用泛型返回,個人定義的統一返回類

ApiModel是生成swagger時掃描的實體注解
ApiModelProperty 是屬性注解
ApiHttpCode 是一個響應值的枚舉類

 
 
package com.example.config.response;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * @author niunafei
 * @function
 * @email niunafei0315@163.com
 * @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 niunafei0315@163.com
 * @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 niunafei0315@163.com
 * @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 {

    }
}

 

 

 

token出現驗證異常 https://www.cnblogs.com/fengli9998/p/7852685.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM