捕获spring RestController中的异常,并记录日志

在使用spring的时候,如果Controller中抛出异常,会被spring显示在客户端界面,而日志中一般没有记录。
客户端对异常的显示也是经spring处理后的信息,没有堆栈,这不方便找错和改错。

可以通过RestControllerAdvice注解定义一个异常处理类来解决这个问题。

代码如下
注:也可以不继承ResponseEntityExceptionHandler类,此处继承只是省了一些通用异常的处理。
import java.util.HashMap;
import java.util.Map;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
 
 
/**
 * 
 * RestController执行过程中发生异常会被此处捕获处理
 *
 */
@RestControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
    private static final Log log = LogFactory.getLog(ControllerExceptionHandler.class);
     
    /**
     * 通过ExceptionHandler来设置待捕获的异常,Throwable可捕获任何异常,但优先级最低,因此
     * HttpRequestMethodNotSupportedException HttpMediaTypeNotSupportedException
     * HttpMediaTypeNotAcceptableException MissingPathVariableException
     * MissingServletRequestParameterException ServletRequestBindingException
     * ConversionNotSupportedException TypeMismatchException
     * HttpMessageNotReadableException HttpMessageNotWritableException
     * MethodArgumentNotValidException MissingServletRequestPartException
     * BindException NoHandlerFoundException AsyncRequestTimeoutException
     * 等已经在父类声明捕获的异常不会被此方法处理。
     */
    @ExceptionHandler(Throwable.class)
    @ResponseBody
    ResponseEntity<Object> handleControllerException(Throwable ex, WebRequest request) {
        Map<String,String> responseBody = new HashMap<>();
        // 这里控制返回给客户端的信息
        responseBody.put("message","internal server error. " + ex.getMessage());
         
        Exception e;
        if(ex instanceof Exception) {
            e = (Exception) ex;
        }else {
            e = new Exception(ex);
        }
        return handleExceptionInternal(e, responseBody, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
    }
 
    /**
     * 需要覆盖这个方法,并且在此方法里记录日志;查看ResponseEntityExceptionHandler源码可知,
     * 有些异常被父类捕获,不会进入此类的handleControllerException,因此如果在handleControllerException
     * 记录异常日志,会导致部分异常无日志
     */
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
        if(log.isErrorEnabled()) {
            log.error("内部错误", ex);
        }
        return super.handleExceptionInternal(ex, body, headers, status, request);
    }
}

此方法还可改变发生异常时给客户端传递的信息;无法通过Bean Validation时默认传递的信息太丰富了,可能被有恶意的利用。

最后,做个小广告,免费课程:用Spring Boot编写RESTful API

http://study.163.com/course/introduction.htm?courseId=1005213034

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Spring Cloud,我们可以通过自定义全局异常处理器来处理应用程序的所有异常。以下是实现全局异常处理器的步骤: 1. 创建一个全局异常处理器类,该类应该实现Spring的ErrorController接口。 2. 在处理器类,使用@RequestMapping注解来定义处理所有错误请求的路由。 3. 在路由方法,获取请求异常信息,并根据异常类型返回相应的错误响应。 4. 在应用程序的配置文件,将Spring的默认错误处理器禁用,并将全局异常处理器类注册为错误处理器。 以下是一个简单的全局异常处理器示例: ``` @RestController @ControllerAdvice public class GlobalExceptionHandler implements ErrorController { @RequestMapping("/error") public ResponseEntity<ErrorResponse> handleAllExceptions(HttpServletRequest request) { ErrorResponse errorResponse = new ErrorResponse(); errorResponse.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); errorResponse.setErrorMessage("An error occurred during the request."); errorResponse.setRequestedURI(request.getRequestURI()); return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } @Override public String getErrorPath() { return "/error"; } } ``` 在上面的代码,我们实现了Spring的ErrorController接口,并使用@ControllerAdvice注解来指定该类为全局异常处理器。在handleAllExceptions方法,我们获取请求异常信息,并根据异常类型返回相应的错误响应。最后,我们将该类注册为错误处理器,并将Spring的默认错误处理器禁用。 ### 回答2: Spring Cloud是一个用于构建微服务架构的框架,它提供了许多功能和组件来简化微服务的开发和管理。其之一就是全局异常处理器。 全局异常处理器是一个用于捕获和处理应用程序发生的异常的组件。在微服务架构,由于各个服务之间的调用和交互,很可能会出现许多不同种类的异常,例如网络异常、数据库异常、业务异常等。而全局异常处理器的作用就是捕获这些异常,并根据具体情况进行统一处理。 使用Spring Cloud的全局异常处理器,可以帮助我们实现以下功能: 1. 统一异常处理:无论是哪个服务发生了异常,全局异常处理器都能捕获并进行处理,避免异常导致系统崩溃或无响应。 2. 异常信息返回:全局异常处理器可以将捕获到的异常信息封装成特定的响应格式,方便客户端或其他服务进行处理。 3. 异常分类处理:根据异常的类型和来源,全局异常处理器可以将异常分类处理,例如数据库异常可以跳转到指定的错误页面,业务异常可以返回特定的错误码等。 4. 日志记录:全局异常处理器可以将捕获到的异常信息进行日志记录,方便开发人员进行问题排查和分析。 总之,Spring Cloud的全局异常处理器是一个非常实用的组件,能够帮助我们捕获和处理微服务架构异常,并保证系统的稳定性和可靠性。通过合理配置和使用全局异常处理器,我们可以更好地管理和维护我们的微服务应用程序。 ### 回答3: Spring Cloud全局异常处理器是用来统一处理系统出现的异常情况。在微服务架构,由于系统由多个服务组成,每个服务都可能出现异常,如果每个服务都单独处理异常,会造成代码冗余和维护困难。因此,引入全局异常处理器可以统一处理所有服务的异常,提高代码的可维护性和可读性。 Spring Cloud全局异常处理器的工作原理如下:首先,在服务启动时,通过配置文件或代码,将异常处理器注册到Spring容器。当服务发生异常时,Spring容器会捕获异常,并根据异常类型和处理器的配置,将异常交给对应的处理器进行处理。处理器可以通过捕获异常的类型来判断异常的种类,并根据不同的异常类型进行不同的处理,例如返回给前端用户友好的错误信息、记录异常日志等。 使用全局异常处理器的好处如下:首先,可以减少代码的冗余,不需要在每个服务都编写相同的异常处理代码;其次,可以提高代码的可读性,将异常处理的逻辑集在一个地方,便于理解和维护;还可以提高系统的容错性和稳定性,可以捕获并处理各种异常情况,避免系统因为异常导致崩溃或无法正常运行。 总结而言,Spring Cloud全局异常处理器是一个集处理系统异常情况的机制,能够统一处理微服务架构各个服务的异常,提高代码的可维护性和系统的容错性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值