【问题标题】:How to manage exceptions thrown in filters in Spring?Spring中如何管理过滤器中抛出的异常?
【发布时间】:2016-04-08 07:53:13
【问题描述】:

我想使用通用的方式来管理 5xx 错误代码,让我们具体说一下当我的整个 spring 应用程序中的数据库关闭时的情况。我想要一个漂亮的错误 json 而不是堆栈跟踪。

对于控制器,我有一个针对不同异常的@ControllerAdvice 类,这也捕获了数据库在请求中间停止的情况。但这并不是全部。我也碰巧有一个自定义CorsFilter 扩展OncePerRequestFilter,当我调用doFilter 时,我得到CannotGetJdbcConnectionException,它不会由@ControllerAdvice 管理。我在网上阅读了几件事,这让我更加困惑。

所以我有很多问题:

  • 我需要实现自定义过滤器吗?我找到了ExceptionTranslationFilter,但这只处理AuthenticationExceptionAccessDeniedException
  • 我想实现我自己的HandlerExceptionResolver,但这让我怀疑,我没有任何自定义异常要管理,一定有比这更明显的方法。我还尝试添加一个 try/catch 并调用 HandlerExceptionResolver 的实现(应该足够好,我的异常没什么特别的)但这没有在响应中返回任何内容,我得到一个状态 200 和一个空的主体。

有什么好的方法可以解决这个问题吗?谢谢

【问题讨论】:

标签: java spring spring-security


【解决方案1】:

在过滤器中,我们没有带有@ControllerAdvice@RestControllerAdvice 的控件来处理我们在进行身份验证时可能发生的异常。因为,DispatcherServlet 只有在 Controller 类命中后才会出现。 所以,我们需要做以下事情。

  1. 我们需要

    HttpServletResponse httpResponse = (HttpServletResponse) 响应;

“响应”对象我们可以从public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)GenericFilterBean.java 实现类传递它。 2) 我们可以使用下面的实用程序类将我们的错误 JSON 模型或 String 对象写入或打印到 ServletResponse 输出流中。

public static void handleUnAuthorizedError(ServletResponse response,Exception e)
{
    ErrorModel error = null;
    if(e!=null)
        error = new ErrorModel(ErrorCodes.ACCOUNT_UNAUTHORIZED, e.getMessage());
    else
        error = new ErrorModel(ErrorCodes.ACCOUNT_UNAUTHORIZED, ApplicationConstants.UNAUTHORIZED);
    
    JsonUtils jsonUtils = new JsonUtils();
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
    httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    try {
        httpResponse.getOutputStream().println(jsonUtils.convertToJSON(error));
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}


public String convertToJSON(Object inputObj) {
        ObjectMapper objectMapper = new ObjectMapper();
        String orderJson = null;
        try {
            orderJson = objectMapper.writeValueAsString(inputObj);
        }
        catch(Exception e){
            e.printStackTrace();
        }
        return orderJson;
    }

【讨论】:

  • OutputStream 没有方法 'println',但您可以通过传递字符串并调用 string.getBytes() 来使用 'write'
【解决方案2】:

我在 webflux 中遇到了同样的问题,主题是有人希望在那里重用 @ControllerAdvice,你不想在 webfilter 中抛出直接异常或返回单声道错误,但是你想设置响应成为单声道错误。

    public class YourFilter implements WebFilter {


    @Override
    public Mono<Void> filter(final ServerWebExchange exchange, final WebFilterChain chain) {
        exchange.getResponse().writeWith(Mono.error(new YouException()));
        return chain.filter(exchange)
    }
}

【讨论】:

    【解决方案3】:

    您无需为此创建自定义过滤器。我们通过创建扩展 ServletException 的自定义异常(从 doFilter 方法抛出,如声明中所示)解决了这个问题。这些然后由我们的全局错误处理程序捕获和处理。

    编辑:语法

    【讨论】:

    • 您介意分享您的全局错误处理程序的代码 sn-p 吗?
    • 它对我不起作用。我做了自定义异常,扩展了 ServletException,在 ExceptionHandler 中添加了对这个异常的支持,但是那里没有被拦截。
    【解决方案4】:

    您可以在 catch 块中使用以下方法:

    response.sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid token")
    

    请注意,您可以使用任何 HttpStatus 代码和自定义消息。

    【讨论】:

      【解决方案5】:

      我想提供一个基于the answer of @kopelitsa 的解决方案。主要区别在于:

      1. 通过使用HandlerExceptionResolver重用控制器异常处理。
      2. 在 XML 配置上使用 Java 配置

      首先,您需要确保您有一个类来处理常规 RestController/Controller 中发生的异常(使用 @RestControllerAdvice@ControllerAdvice 注释的类和使用 @ExceptionHandler 注释的方法)。这会处理您在控制器中发生的异常。下面是一个使用 RestControllerAdvice 的示例:

      @RestControllerAdvice
      public class ExceptionTranslator {
      
          @ExceptionHandler(RuntimeException.class)
          @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
          public ErrorDTO processRuntimeException(RuntimeException e) {
              return createErrorDTO(HttpStatus.INTERNAL_SERVER_ERROR, "An internal server error occurred.", e);
          }
      
          private ErrorDTO createErrorDTO(HttpStatus status, String message, Exception e) {
              (...)
          }
      }
      

      要在 Spring Security 过滤器链中重用此行为,您需要定义一个过滤器并将其挂钩到您的安全配置中。过滤器需要将异常重定向到上面定义的异常处理。这是一个例子:

      @Component
      public class FilterChainExceptionHandler extends OncePerRequestFilter {
      
          private final Logger log = LoggerFactory.getLogger(getClass());
      
          @Autowired
          @Qualifier("handlerExceptionResolver")
          private HandlerExceptionResolver resolver;
      
          @Override
          protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                  throws ServletException, IOException {
      
              try {
                  filterChain.doFilter(request, response);
              } catch (Exception e) {
                  log.error("Spring Security Filter Chain Exception:", e);
                  resolver.resolveException(request, response, null, e);
              }
          }
      }
      

      然后需要将创建的过滤器添加到 SecurityConfiguration。你需要很早就把它挂到链中,因为所有前面的过滤器的异常都不会被捕获。就我而言,在LogoutFilter 之前添加它是合理的。查看默认过滤器链及其顺序in the official docs。这是一个例子:

      @Configuration
      @EnableWebSecurity
      public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
      
          @Autowired
          private FilterChainExceptionHandler filterChainExceptionHandler;
      
          @Override
          protected void configure(HttpSecurity http) throws Exception {
              http
                  .addFilterBefore(filterChainExceptionHandler, LogoutFilter.class)
                  (...)
          }
      
      }
      

      【讨论】:

      • 看起来很有希望...您将如何修改它以处理 validators 引发的异常?它们还运行之前 Controller
      • FilterChainExceptionHandler 仅适用于运行时异常。对于 MethodArgumentNotValidExceptionServletRequestBindingException .etc 等 Checked Exceptions 的处理方法
      • 非常感谢你让我度过了愉快的一天,我花了很多时间来处理,但最后我看到了它,它的效果很棒
      • 过滤器如何“将异常重定向到上面定义的异常处理”?
      • 这似乎是处理错误的最佳方式。我曾尝试手动写入响应,但时间戳没有被正确序列化并且得到部分 JSON 响应。手动调用异常解析器效果很好。
      【解决方案6】:

      在阅读了上述答案中建议的不同方法后,我决定使用自定义过滤器来处理身份验证异常。我能够使用以下方法使用错误响应类来处理响应状态和代码。

      我创建了一个自定义过滤器并使用 addFilterAfter 方法修改了我的安全配置,并在 CorsFilter 类之后添加。

      @Component
      public class AuthFilter implements Filter {
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
          //Cast the servlet request and response to HttpServletRequest and HttpServletResponse
          HttpServletResponse httpServletResponse = (HttpServletResponse) response;
          HttpServletRequest httpServletRequest = (HttpServletRequest) request;
      
          // Grab the exception from the request attribute
          Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
          //Set response content type to application/json
          httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
      
          //check if exception is not null and determine the instance of the exception to further manipulate the status codes and messages of your exception
          if(exception!=null && exception instanceof AuthorizationParameterNotFoundException){
              ErrorResponse errorResponse = new ErrorResponse(exception.getMessage(),"Authetication Failed!");
              httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
              PrintWriter writer = httpServletResponse.getWriter();
              writer.write(convertObjectToJson(errorResponse));
              writer.flush();
              return;
          }
          // If exception instance cannot be determined, then throw a nice exception and desired response code.
          else if(exception!=null){
                  ErrorResponse errorResponse = new ErrorResponse(exception.getMessage(),"Authetication Failed!");
                  PrintWriter writer = httpServletResponse.getWriter();
                  writer.write(convertObjectToJson(errorResponse));
                  writer.flush();
                  return;
              }
              else {
              // proceed with the initial request if no exception is thrown.
                  chain.doFilter(httpServletRequest,httpServletResponse);
              }
          }
      
      public String convertObjectToJson(Object object) throws JsonProcessingException {
          if (object == null) {
              return null;
          }
          ObjectMapper mapper = new ObjectMapper();
          return mapper.writeValueAsString(object);
      }
      }
      

      SecurityConfig 类

          @Configuration
          public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
          @Autowired
          AuthFilter authenticationFilter;
          @Override
          protected void configure(HttpSecurity http) throws Exception {
              http.addFilterAfter(authenticationFilter, CorsFilter.class).csrf().disable()
                      .cors(); //........
              return http;
           }
         }
      

      错误响应类

      public class ErrorResponse  {
      private final String message;
      private final String description;
      
      public ErrorResponse(String description, String message) {
          this.message = message;
          this.description = description;
      }
      
      public String getMessage() {
          return message;
      }
      
      public String getDescription() {
          return description;
      }}
      

      【讨论】:

        【解决方案7】:

        只是为了补充提供的其他很好的答案,因为我最近也想要一个简单的 SpringBoot 应用程序中的 single 错误/异常处理组件,其中包含可能抛出异常的过滤器,其他异常可能从控制器抛出方法。

        幸运的是,似乎没有什么可以阻止您将控制器建议与 Spring 的默认错误处理程序的覆盖相结合,以提供一致的响应负载,允许您共享逻辑,检查过滤器中的异常,捕获特定的服务抛出异常,等等。

        例如

        
        @ControllerAdvice
        @RestController
        public class GlobalErrorHandler implements ErrorController {
        
          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler(ValidationException.class)
          public Error handleValidationException(
              final ValidationException validationException) {
            return new Error("400", "Incorrect params"); // whatever
          }
        
          @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
          @ExceptionHandler(Exception.class)
          public Error handleUnknownException(final Exception exception) {
            return new Error("500", "Unexpected error processing request");
          }
        
          @RequestMapping("/error")
          public ResponseEntity handleError(final HttpServletRequest request,
              final HttpServletResponse response) {
        
            Object exception = request.getAttribute("javax.servlet.error.exception");
        
            // TODO: Logic to inspect exception thrown from Filters...
            return ResponseEntity.badRequest().body(new Error(/* whatever */));
          }
        
          @Override
          public String getErrorPath() {
            return "/error";
          }
        
        }
        

        【讨论】:

          【解决方案8】:

          所以,这就是我基于上述答案的合并所做的事情......我们已经有一个带有 @ControllerAdvice 注释的 GlobalExceptionHandler,我还想找到一种方法来重用该代码来处理异常来自过滤器。

          我能找到的最简单的解决方案是不理会异常处理程序,并按如下方式实现错误控制器:

          @Controller
          public class ErrorControllerImpl implements ErrorController {
            @RequestMapping("/error")
            public void handleError(HttpServletRequest request) throws Throwable {
              if (request.getAttribute("javax.servlet.error.exception") != null) {
                throw (Throwable) request.getAttribute("javax.servlet.error.exception");
              }
            }
          }
          

          因此,由异常引起的任何错误首先通过ErrorController,并通过在@Controller 上下文中重新抛出它们被重定向到异常处理程序,而任何其他错误(不是由异常直接引起的)通过ErrorController 不做修改。

          为什么这实际上是一个坏主意?

          【讨论】:

          • 感谢现在测试这个解决方案,但在我的情况下工作完美。
          • 为 spring boot 2.0+ 增加了一个干净简单的添加,你应该添加 @Override public String getErrorPath() { return null; }
          • 您可以使用 javax.servlet.RequestDispatcher.ERROR_EXCEPTION 代替“javax.servlet.error.exception”
          【解决方案9】:

          我自己也遇到了这个问题,我执行了以下步骤来重用我的 ExceptionController,它带有 @ControllerAdvise 注释,用于在注册过滤器中抛出的 Exceptions

          显然有很多方法可以处理异常,但就我而言,我希望由我的ExceptionController 处理异常,因为我很固执,也因为我不想复制/粘贴相同的代码(即我在ExceptionController 中有一些处理/日志记录代码)。我想返回漂亮的JSON 响应,就像其他不是从过滤器抛出的异常一样。

          {
            "status": 400,
            "message": "some exception thrown when executing the request"
          }
          

          无论如何,我设法利用了我的ExceptionHandler,我必须做一些额外的事情,如下所示:

          步骤


          1. 您有一个自定义过滤器,它可能会也可能不会抛出异常
          2. 您有一个使用 @ControllerAdvise 即 MyExceptionController 处理异常的 Spring 控制器

          示例代码

          //sample Filter, to be added in web.xml
          public MyFilterThatThrowException implements Filter {
             //Spring Controller annotated with @ControllerAdvise which has handlers
             //for exceptions
             private MyExceptionController myExceptionController; 
          
             @Override
             public void destroy() {
                  // TODO Auto-generated method stub
             }
          
             @Override
             public void init(FilterConfig arg0) throws ServletException {
                 //Manually get an instance of MyExceptionController
                 ApplicationContext ctx = WebApplicationContextUtils
                            .getRequiredWebApplicationContext(arg0.getServletContext());
          
                 //MyExceptionHanlder is now accessible because I loaded it manually
                 this.myExceptionController = ctx.getBean(MyExceptionController.class); 
             }
          
             @Override
              public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                      throws IOException, ServletException {
                  HttpServletRequest req = (HttpServletRequest) request;
                  HttpServletResponse res = (HttpServletResponse) response;
          
                  try {
                     //code that throws exception
                  } catch(Exception ex) {
                    //MyObject is whatever the output of the below method
                    MyObject errorDTO = myExceptionController.handleMyException(req, ex); 
          
                    //set the response object
                    res.setStatus(errorDTO .getStatus());
                    res.setContentType("application/json");
          
                    //pass down the actual obj that exception handler normally send
                    ObjectMapper mapper = new ObjectMapper();
                    PrintWriter out = res.getWriter(); 
                    out.print(mapper.writeValueAsString(errorDTO ));
                    out.flush();
          
                    return; 
                  }
          
                  //proceed normally otherwise
                  chain.doFilter(request, response); 
               }
          }
          

          现在是在正常情况下处理Exception 的示例 Spring 控制器(即通常不会在过滤器级别抛出的异常,我们希望将其用于过滤器中抛出的异常)

          //sample SpringController 
          @ControllerAdvice
          public class ExceptionController extends ResponseEntityExceptionHandler {
          
              //sample handler
              @ResponseStatus(value = HttpStatus.BAD_REQUEST)
              @ExceptionHandler(SQLException.class)
              public @ResponseBody MyObject handleSQLException(HttpServletRequest request,
                      Exception ex){
                  ErrorDTO response = new ErrorDTO (400, "some exception thrown when "
                          + "executing the request."); 
                  return response;
              }
              //other handlers
          }
          

          与希望将ExceptionController 用于过滤器中的Exceptions 的人分享解决方案。

          【讨论】:

          • 好吧,欢迎您分享您自己的听起来不错的解决方案 :)
          • 如果您想避免将控制器连接到您的过滤器(这是@Bato-BairTsyrenov 所指的我假设),您可以轻松地将创建 ErrorDTO 的逻辑提取到它自己的@ 987654335@ 类并在过滤器和控制器中使用它。
          • 我不完全同意你的观点,因为在你的过滤器中注入一个特定的控制器不是很干净。
          • 正如answer 中提到的,这是其中一种方式!我没有声称这是最好的方法。感谢您分享您的担忧@psv 我相信社区会欣赏您想到的解决方案:)
          【解决方案10】:

          这是我通过覆盖默认 Spring Boot /错误处理程序的解决方案

          package com.mypackage;
          
          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.boot.autoconfigure.web.ErrorAttributes;
          import org.springframework.core.annotation.AnnotationUtils;
          import org.springframework.http.HttpStatus;
          import org.springframework.http.ResponseEntity;
          import org.springframework.util.Assert;
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.ResponseStatus;
          import org.springframework.web.bind.annotation.RestController;
          import org.springframework.web.context.request.RequestAttributes;
          import org.springframework.web.context.request.ServletRequestAttributes;
          
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.util.Map;
          
          /**
           * This controller is vital in order to handle exceptions thrown in Filters.
           */
          @RestController
          @RequestMapping("/error")
          public class ErrorController implements org.springframework.boot.autoconfigure.web.ErrorController {
          
              private final static Logger LOGGER = LoggerFactory.getLogger(ErrorController.class);
          
              private final ErrorAttributes errorAttributes;
          
              @Autowired
              public ErrorController(ErrorAttributes errorAttributes) {
                  Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
                  this.errorAttributes = errorAttributes;
              }
          
              @Override
              public String getErrorPath() {
                  return "/error";
              }
          
              @RequestMapping
              public ResponseEntity<Map<String, Object>> error(HttpServletRequest aRequest, HttpServletResponse response) {
                  RequestAttributes requestAttributes = new ServletRequestAttributes(aRequest);
                  Map<String, Object> result =     this.errorAttributes.getErrorAttributes(requestAttributes, false);
          
                  Throwable error = this.errorAttributes.getError(requestAttributes);
          
                  ResponseStatus annotation =     AnnotationUtils.getAnnotation(error.getClass(), ResponseStatus.class);
                  HttpStatus statusCode = annotation != null ? annotation.value() : HttpStatus.INTERNAL_SERVER_ERROR;
          
                  result.put("status", statusCode.value());
                  result.put("error", statusCode.getReasonPhrase());
          
                  LOGGER.error(result.toString());
                  return new ResponseEntity<>(result, statusCode) ;
              }
          
          }
          

          【讨论】:

          • 它会影响任何自动配置吗?
          • 请注意,HandlerExceptionResolver 不一定会处理异常。所以它可能会像 HTTP 200 一样失败。在调用它之前使用 response.setStatus(..) 似乎更安全。
          【解决方案11】:

          当您想测试应用程序的状态并且在出现问题时返回 HTTP 错误时,我建议您使用过滤器。下面的过滤器处理所有 HTTP 请求。 Spring Boot 中带有 javax 过滤器的最短解决方案。

          在执行中可以有各种条件。在我的情况下,applicationManager 测试应用程序是否准备就绪。

          import ...ApplicationManager;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Component;
          
          import javax.servlet.*;
          import javax.servlet.http.HttpServletResponse;
          import java.io.IOException;
          
          @Component
          public class SystemIsReadyFilter implements Filter {
          
              @Autowired
              private ApplicationManager applicationManager;
          
              @Override
              public void init(FilterConfig filterConfig) throws ServletException {}
          
              @Override
              public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                  if (!applicationManager.isApplicationReady()) {
                      ((HttpServletResponse) response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "The service is booting.");
                  } else {
                      chain.doFilter(request, response);
                  }
              }
          
              @Override
              public void destroy() {}
          }
          

          【讨论】:

            【解决方案12】:

            这就是我所做的:

            我阅读了有关过滤器的基础知识here,我发现我需要创建一个自定义过滤器,该过滤器将位于过滤器链中的第一个,并且将有一个 try catch 来捕获可能在那里发生的所有运行时异常。然后我需要手动创建 json 并将其放入响应中。

            这是我的自定义过滤器:

            public class ExceptionHandlerFilter extends OncePerRequestFilter {
            
                @Override
                public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
                    try {
                        filterChain.doFilter(request, response);
                    } catch (RuntimeException e) {
            
                        // custom error response class used across my project
                        ErrorResponse errorResponse = new ErrorResponse(e);
            
                        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
                        response.getWriter().write(convertObjectToJson(errorResponse));
                }
            }
            
                public String convertObjectToJson(Object object) throws JsonProcessingException {
                    if (object == null) {
                        return null;
                    }
                    ObjectMapper mapper = new ObjectMapper();
                    return mapper.writeValueAsString(object);
                }
            }
            

            然后我将它添加到 CorsFilter 之前的 web.xml 中。它有效!

            <filter> 
                <filter-name>exceptionHandlerFilter</filter-name> 
                <filter-class>xx.xxxxxx.xxxxx.api.controllers.filters.ExceptionHandlerFilter</filter-class> 
            </filter> 
            
            
            <filter-mapping> 
                <filter-name>exceptionHandlerFilter</filter-name> 
                <url-pattern>/*</url-pattern> 
            </filter-mapping> 
            
            <filter> 
                <filter-name>CorsFilter</filter-name> 
                <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
            </filter> 
            
            <filter-mapping>
                <filter-name>CorsFilter</filter-name>
                <url-pattern>/*</url-pattern>
            </filter-mapping>
            

            【讨论】:

            • 你能发布你的 ErrorResponse 类吗?
            • @Shivakumar ErrorResponse 类可能是一个具有简单代码/消息属性的简单 DTO。
            • 这不会重用ControllerAdvice / RestControllerAdvice,是吗?
            【解决方案13】:

            如果你想要一个通用的方式,你可以在web.xml中定义一个错误页面:

            <error-page>
              <exception-type>java.lang.Throwable</exception-type>
              <location>/500</location>
            </error-page>
            

            并在 Spring MVC 中添加映射:

            @Controller
            public class ErrorController {
            
                @RequestMapping(value="/500")
                public @ResponseBody String handleException(HttpServletRequest req) {
                    // you can get the exception thrown
                    Throwable t = (Throwable)req.getAttribute("javax.servlet.error.exception");
            
                    // customize response to what you want
                    return "Internal server error.";
                }
            }
            

            【讨论】:

            • 但在休息 api 中使用位置重定向并不是一个好的解决方案。
            • @jmattheis 以上不是重定向。
            • 没错,我看到了位置,并认为它与 http 位置有关。那么这就是我需要的(:
            • 如果存在的话,能否添加与 web.xml 等效的 Java 配置?
            • @k-den 我认为当前规范中没有等效的 Java 配置,但您可以混合使用 web.xml 和 Java 配置。
            【解决方案14】:

            这很奇怪,因为 @ControllerAdvice 应该可以工作,你是否捕获了正确的异常?

            @ControllerAdvice
            public class GlobalDefaultExceptionHandler {
            
                @ResponseBody
                @ExceptionHandler(value = DataAccessException.class)
                public String defaultErrorHandler(HttpServletResponse response, DataAccessException e) throws Exception {
                   response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
                   //Json return
                }
            }
            

            也尝试在 CorsFilter 中捕获此异常并发送 500 错误,类似这样

            @ExceptionHandler(DataAccessException.class)
            @ResponseBody
            public String handleDataException(DataAccessException ex, HttpServletResponse response) {
                response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
                //Json return
            }
            

            【讨论】:

            • 在 CorsFilter 中处理异常是可行的,但它不是很干净。事实上,我真正需要的是处理所有过滤器的异常
            • Filter 抛出的异常可能无法被 @ControllerAdvice 捕获,因为 in 可能无法到达 DispatcherServlet
            猜你喜欢
            • 2015-12-12
            • 2021-08-09
            • 2017-04-20
            • 2017-10-17
            • 2018-12-27
            • 2021-05-19
            • 2018-06-04
            • 2017-06-29
            相关资源
            最近更新 更多