我们如何在 HandlerInterceptorAdapter 中 postHandle 异常?

Posted

技术标签:

【中文标题】我们如何在 HandlerInterceptorAdapter 中 postHandle 异常?【英文标题】:How can we postHandle an exception in HandlerInterceptorAdapter? 【发布时间】:2020-10-09 14:41:42 【问题描述】:

我目前正在尝试为 Spring Boot 实现一个自定义的错误处理程序,我已经完成了以下操作:

 public class ExceptionHandler extends HandlerInterceptorAdapter 

 public static Logger log = LoggerFactory.getLogger(LoggingInterceptor.class);

 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception 
        try 
          log.info("Service  Calling  on  finished with status ",request.getRemoteUser(), request.getMethod(), request.getRequestURI(), HttpStatus.valueOf(response.getStatus()));
         catch (Exception e) 
            // Do nothing
         finally 
            log.error("[Spring Boot Interceptor]  returned with ", handler, HttpStatus.valueOf(response.getStatus()));
    
 

不知何故这不起作用,并且仍然向客户端抛出异常,是否有某种方法可以捕获方法抛出的异常并忽略它。例如。

【问题讨论】:

你应该注册你的拦截器到注册表,检查这个***.com/questions/31082981/… 我添加了拦截器,它被执行了,但是在 postHandle 中定义的 try catch 不知何故没有处理异常(500 Internal Server Error),而是在控制台中抛出它。 我认为您需要在 afterComplete 方法中而不是在 postHandle 中处理异常。 请参考下面的帖子。 ***.com/questions/48785878/… 【参考方案1】:

管理异常的好方法是使用@ControllerAdvice,使用它您可以处理任何类型的异常并根据需要自定义响应。

正如评论中所说,你必须添加InterceptorRegistry才能注册拦截器。

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer 

    @Override
    public void addInterceptors(InterceptorRegistry registry) 
        registry.addInterceptor(new Interceptor()).addPathPatterns("/**");
    

postHandle内的catch块只有在try-catch块内发生异常时才会执行,如下所示,

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception 
    try 
        int error = 1/0;
     catch (Exception e) 
        log.info("Exception will be handled inside catch block");
     

现在让我们探索 @ControllerAdvice 来管理应用程序中的异常。这两个 API 会产生异常,我们将使用 @ExceptionHandler 管理异常

@GetMapping("/exception/404")
public void generateResourceNotFound() 
    throw new ResourceNotFoundException("resource not found");


@GetMapping("/exception/403")
public void generateAccessDenied() 
    throw new AccessDeniedException("access denied");

GlobalExceptionHandler.java

import com.learning.annotations.controller.ResourceNotFoundException;
import com.learning.annotations.dto.ErrorResponseDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler 

    public Logger log = LoggerFactory.getLogger(Interceptor.class);

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ErrorResponseDTO> handleAccessDeniedException(AccessDeniedException ex, WebRequest request) 
        ErrorResponseDTO response = new ErrorResponseDTO();
        response.setError(ex.getMessage());
        response.setMessage("You don't have authority to access the resource");
        return new ResponseEntity<>(response, HttpStatus.FORBIDDEN);
    

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponseDTO> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) 
        ErrorResponseDTO response = new ErrorResponseDTO();
        response.setError(ex.getMessage());
        response.setMessage("Resource might be moved temporary or not available");
        return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
    

要自定义响应,我们可以创建错误响应 DTO,如下所示,

import lombok.Data;

@Data
public class ErrorResponseDTO 
    private String message;
    private String error;

【讨论】:

此解决方案有效,但 Boinix1441 询问他是否可以在响应中捕获应用程序在 rest 调用时抛出的异常。不在 postHandle 中抛出异常,在 postHandle 中处理。

以上是关于我们如何在 HandlerInterceptorAdapter 中 postHandle 异常?的主要内容,如果未能解决你的问题,请参考以下文章

我们如何在php中处理动态表单

async/await 抛出 NullReferenceException 我们如何诊断我们在哪里搞砸了?

我们如何在 Prometheus 度量系列中添加我们自己的时间戳?

我们如何在 Apache Spark 中执行动态重新分区?

如何判断我们是不是在主线程中运行?

我们如何在 agora 应用中对远程流进行情感分析?