全局异常设计的好坏,关系到整个系统的健壮性,需要能够适配所有微服务项目。
@ControllerAdvice+@ExceptionHandler全局处理Controller层异常。
捕获controller层的异常,处理指定类型的异常;
返回前端一个ResponseEntity对象;
不足之处:只能处理Controller抛出的异常,对于Interceptor(拦截器)及其他层面的异常,无能为力。
1)在方法的后面使用throws关键字对外声明该方法有可能发生异常
2)调用者在调用方法时,就明确地知道该方法有异常,并且必须在程序中对异常进行处理,否则编译无法通过
3)编译时异常的特点是Java编译器会对其进行检查,如果出现异常就必须对异常进行处理,否则程序无法编译通过。
4)运行时异常一般是程序中的逻辑错误引起的,在程序运行时无法修复。例如 数据取值越界。
5)自定义异常,项目中也有自定义异常类啊,全局异常设计。在Java中允许用户自定义异常,但自定义的异常类必须继承自Exception或其子类。
出现异常,返回给前端一个ResponseEntity对象,里面包含异常信息。
是否需要区分异常级别?
package com.yunque.www.springbootdemo.exceptions;
import com.yunque.www.springbootdemo.pojo.BaseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.servlet.http.HttpServletRequest;
//@ControllerAdvice(annotations = RestController.class)
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private String JSON_FORMAT_TEMP = "{\"code\": \"%s\",\"message\": \"%s\",\"from\": \"%s\",\"path\": \"%s\"}";
private HttpHeaders headers = null;
public GlobalExceptionHandler() {
this.headers = new HttpHeaders();
this.headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
}
/**
* 是否要区分异常级别,是error级别还是warn级别?
*
* @param serviceException
* @param request
* @return
*/
@ExceptionHandler(value = ServiceException.class)
public ResponseEntity<BaseResult> handlerServiceException(ServiceException serviceException, HttpServletRequest request) {
return processException(serviceException.getCode(), serviceException.getMessage(), serviceException, request, Level.ERROR);
}
@ExceptionHandler(value = SystemException.class)
public ResponseEntity<BaseResult> handlerSystemException(SystemException systemException, HttpServletRequest request) {
//如果日志文件中错误码为500000,系统级异常
return processException(PicaResultCode.SYSTEM_EXCEPTION.getCode(), PicaResultCode.SYSTEM_EXCEPTION.getMessage(), systemException, request, Level.ERROR);
}
/**
* 处理异常信息
*
* @param code
* @param message
* @param exception
* @param request
* @param level
* @return
*/
private ResponseEntity<BaseResult> processException(String code, String message, Exception exception, HttpServletRequest request, Level level) {
String json = String.format(JSON_FORMAT_TEMP, code, message, request.getRemoteAddr(), request.getRequestURI() + "?" + request.getQueryString());
if (level == Level.ERROR) {
logger.error(json, exception);
}
//todo:返回给前端一个ResponseEntity对象,里面包含错误的信息
return new ResponseEntity<BaseResult>(new BaseResult().Builder().setCode(code).setMessage(message).build(), headers, HttpStatus.OK);
}
@Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
logger.error(ex.getMessage(), ex);
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
request.setAttribute("javax.servlet.error.exception", ex, WebRequest.SCOPE_REQUEST);
}
return new ResponseEntity<Object>(body, headers, status);
}
}