How can we postHandle an exception in HandlerInterceptorAdapter?

回眸只為那壹抹淺笑 提交于 2021-01-28 09:55:18

问题


I am currently trying to implement a customized error handler for spring boot and I have done it with the following:

 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()));
    }
 }

Somehow this does not work, and the exception is still thrown to the client, is there some way to catch the exception thrown by the method and ignore it for example.


回答1:


A good way to manage the exception is using @ControllerAdvice, using this you may handle any kind of exception and customize the response as required.

As said in the comment, you have to add InterceptorRegistry to register the interceptor.

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("/**");
    }
}

The catch block inside postHandle will only be executed if an exception occurred inside the try-catch block as below,

@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");
    } 
}

Now let's explore the @ControllerAdvice to manage the exception within the application. These two APIs will generate the exceptions and we will manage the exceptions using @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);
    }
}

To customize the response we can create error response DTO as follows,

import lombok.Data;

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


来源:https://stackoverflow.com/questions/62468646/how-can-we-posthandle-an-exception-in-handlerinterceptoradapter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!