zoukankan      html  css  js  c++  java
  • springboot全局响应类与swagger冲突

    近日,在学习springboot全局异常处理与全局响应对象时,因为项目本身使用了swagger,启用全局响应处理类后,swagger页面无法使用,如下图

    全局响应类需集成ResponseBodyAdvice接口,并添加注解@ControllerAdvice和@Component,交由spring进行管理 

    经排查后,是由于全局响应类中supports方法拦截了请求,在supports方法的返回值前增加过滤判断,是swagger的Docket类则返回false

    改动后代码如下:

     1 package com.myfather.demo3.exception;
     2 
     3 import com.myfather.demo3.common.AjaxResponse;
     4 import org.springframework.core.MethodParameter;
     5 import org.springframework.http.HttpStatus;
     6 import org.springframework.http.MediaType;
     7 import org.springframework.http.server.ServerHttpRequest;
     8 import org.springframework.http.server.ServerHttpResponse;
     9 import org.springframework.stereotype.Component;
    10 import org.springframework.web.bind.annotation.ControllerAdvice;
    11 import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
    12 import springfox.documentation.spring.web.plugins.Docket;
    13 
    14 /**
    15  * @Description 全局响应类
    16  * @Author liangZai
    17  * @Date 2020/12/17 22:09
    18  * @Version 1.0
    19  */
    20 @Component
    21 @ControllerAdvice
    22 public class GlobalResponseAdvice implements ResponseBodyAdvice {
    23     /**
    24      * Whether this component supports the given controller method return type
    25      * and the selected {@code HttpMessageConverter} type.
    26      *
    27      * @param returnType    the return type
    28      * @param converterType the selected converter type
    29      * @return {@code true} if {@link #beforeBodyWrite} should be invoked;
    30      * {@code false} otherwise
    31      */
    32     @Override
    33     public boolean supports(MethodParameter returnType, Class converterType) {
    34         //默认结果为false,表示支持哪些方法,改为true之后为支持所有方法
    35 //        return false;
    36         return !returnType.getDeclaringClass().equals(Docket.class);
    37 //        return true;
    38     }
    39 
    40     /**
    41      * Invoked after an {@code HttpMessageConverter} is selected and just before
    42      * its write method is invoked.
    43      *
    44      * @param body                  the body to be written
    45      * @param returnType            the return type of the controller method
    46      * @param mediaType   the content type selected through content negotiation
    47      * @param selectedConverterType the converter type selected to write to the response
    48      * @param request               the current request
    49      * @param response              the current response
    50      * @return the body that was passed in or a modified (possibly new) instance
    51      */
    52     @Override
    53     public Object beforeBodyWrite(Object body,
    54                                   MethodParameter returnType,
    55                                   MediaType mediaType,
    56                                   Class selectedConverterType,
    57                                   ServerHttpRequest request,
    58                                   ServerHttpResponse response) {
    59 
    60         if(mediaType.equalsTypeAndSubtype(MediaType.APPLICATION_JSON)){
    61             if(body instanceof AjaxResponse){
    62                 response.setStatusCode(HttpStatus.valueOf((
    63                         (AjaxResponse)body).getCode()
    64                 ));
    65                 return body;
    66             }
    67             else {
    68                 response.setStatusCode(HttpStatus.OK);
    69                 return AjaxResponse.success(body);
    70             }
    71         }
    72         return null;
    73     }
    74 }
    View Code

    改动前

     代码改动后

    以下贴出代码

    统一响应类

    package com.myfather.demo3.common;
    
    import com.myfather.demo3.exception.CustomException;
    import com.myfather.demo3.exception.CustomExceptionType;
    import lombok.Data;
    
    /**
     * @Description
     * @Author liangZai
     * @Date 2020/12/17 21:49
     * @Version 1.0
     */
    @Data
    public class AjaxResponse {
    
        private boolean isok;
    
        private int code;
    
        private String message;
    
        private Object data;
    
        private AjaxResponse() {
        }
    
        /**
         * 请求成功参数封装
         * @return
         */
        public static AjaxResponse success(){
            AjaxResponse response = new AjaxResponse();
            response.setIsok(true);
            response.setCode(200);
            response.setMessage("请求成功!");
            return response;
        }
    
        /**
         * 请求成功带参
         * @param obj
         * @return
         */
        public static AjaxResponse success(Object obj){
            AjaxResponse response = new AjaxResponse();
            response.setIsok(true);
            response.setCode(200);
            response.setMessage("请求成功!");
            response.setData(obj);
            return response;
        }
    
        /**
         * 请求成功带参且自定义消息
         * @param obj
         * @param message
         * @return
         */
        public static AjaxResponse success(Object obj,String message){
            AjaxResponse response = new AjaxResponse();
            response.setIsok(true);
            response.setCode(200);
            response.setMessage(message);
            response.setData(obj);
            return response;
        }
    
        /**
         * 请求异常参数封装
         * @param e
         * @return
         */
        public static AjaxResponse error(CustomException e){
            AjaxResponse response = new AjaxResponse();
            response.setIsok(false);
            response.setCode(e.getCode());
            response.setMessage(e.getMessage());
            return response;
        }
    
        /**
         * 请求异常带参数且自定义消息
         * @param customExceptionType
         * @param message
         * @return
         */
        public static AjaxResponse error(CustomExceptionType customExceptionType,String message){
            AjaxResponse response = new AjaxResponse();
            response.setIsok(false);
            response.setCode(customExceptionType.getCode());
            response.setMessage(message);
            return response;
        }
    }
    View Code

    自定义异常类

    package com.myfather.demo3.exception;
    
    import lombok.Data;
    
    /**
     * @Description
     * @Author liangZai
     * @Date 2020/12/17 21:44
     * @Version 1.0
     */
    @Data
    public class CustomException extends RuntimeException {
    
        private int code;
        private String message;
    
        private CustomException() {
        }
    
        public CustomException(CustomExceptionType customExceptionType,String message) {
            this.code = customExceptionType.getCode();
            this.message = message;
        }
    
        public CustomException(CustomExceptionType customExceptionType) {
            this.code = customExceptionType.getCode();
            this.message = customExceptionType.getDesc();
        }
    }
    View Code

    自定义异常code枚举类

    package com.myfather.demo3.exception;
    
    /**
     * 异常类型
     */
    public enum CustomExceptionType {
        USER_INPUT_ERROR(400,"用户输入参数有误!"),
        SYSTEM_ERROR(500,"服务器异常!"),
        OTHER_ERROR(999,"系统出现未知异常,请联系管理员!"),
        ;
        private int code;
        private String desc;
    
        CustomExceptionType(int code, String desc) {
            this.code = code;
            this.desc = desc;
        }
    
        public int getCode() {
            return code;
        }
    
        public String getDesc() {
            return desc;
        }
    }
    View Code

    全局异常处理类

    package com.myfather.demo3.exception;
    
    import com.myfather.demo3.common.AjaxResponse;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @Description
     * @Author liangZai
     * @Date 2020/12/17 22:02
     * @Version 1.0
     */
    @ControllerAdvice
    public class WebExceptionHandler {
    
        @ExceptionHandler(CustomException.class)
        @ResponseBody
        public AjaxResponse customerException(CustomException e){
            return AjaxResponse.error(e);
        }
    
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public AjaxResponse customerException(Exception e){
            return AjaxResponse.error(new CustomException(CustomExceptionType.OTHER_ERROR));
        }
    }
    View Code

    swagger配置类

    package com.myfather.demo3;
    
    import io.swagger.annotations.Api;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    /**
     * swagger配置文件
     *
     * @author liangZai
     */
    @Configuration
    @EnableSwagger2
    @ComponentScan(basePackages = {"com.myfather.demo3"})
    @ConditionalOnProperty(prefix = "myconfig", name = "swagger-ui-open", havingValue = "true")
    public class SwaggerConfig {
    
        @Bean
        public Docket createAccepterRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    //分组名,不指定默认为default
                    .groupName("我的API")
                    .select()
                    .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                    // 定义要生成文档的Api的url路径规则
                    .paths(PathSelectors.any())
                    .build()
                    // 设置swagger-ui.html页面上的一些元素信息
                    .apiInfo(apiInfo())
                    .enable(true);
        }
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("我的RESTful API")
                    .description("提供各种牛掰功能")
                    .version("1.0")
                    .build();
        }
    }
    View Code
    
    
  • 相关阅读:
    对实时的视屏流进行处理
    opencv读取并播放avi视屏
    opencv中读取显示图像
    为什么既要有IP地址还要有MAC地址
    继承中构造、析构 与 拷贝构造、赋值中的调用区别
    拷贝构造函数和赋值符函数——转
    inline修饰虚函数的问题
    菱形继承产生的问题及解决
    迭代器模式
    备忘录模式
  • 原文地址:https://www.cnblogs.com/diaoye/p/14155154.html
Copyright © 2011-2022 走看看