介绍
在Java中异常可以分为Error和Exception,@ControllerAdvice用来处理系统中的Exception,ErrorController处理系统中的Error。
ErrorController
在项目中我们遇到404找不到的错误、或者500服务器错误都需要配置相应的页面给用户一个友好的提示,而在Spring Boot中我们需要如何设置。
当系统出现404或者405等错误信息时,springboot默认的访问路径为/error,所以实现ErrorController并重写。
ErrorController源码
package org.springframework.boot.web.servlet.error;
import org.springframework.stereotype.Controller;
/**
* Marker interface used to indicate that a {@link Controller @Controller} is used to
* render errors. Primarily used to know the error paths that will not need to be secured.
*
* @author Phillip Webb
* @since 2.0.0
*/
@FunctionalInterface
public interface ErrorController {
/**
* Returns the path of the error page.
* @return the error path
*/
String getErrorPath();
}
重写ErrorController样例
/**
* 全局Error/404处理
* @author geekidea
* @date 2018-11-08
*/
@ApiIgnore
@RestController
@Slf4j
public class GlobalErrorController implements ErrorController {
private static final String ERROR_PATH = "/error";
@RequestMapping(ERROR_PATH)
public ApiResult<?> handleError(HttpServletRequest request,HttpServletResponse response){
int status = response.getStatus();
switch (status){
case HttpServletResponse.SC_UNAUTHORIZED:
return ApiResult.fail(ApiCode.UNAUTHORIZED);
case HttpServletResponse.SC_FORBIDDEN:
return ApiResult.fail(ApiCode.NOT_PERMISSION);
case HttpServletResponse.SC_NOT_FOUND:
return ApiResult.fail(ApiCode.NOT_FOUND);
default:
break;
}
return ApiResult.fail(ApiCode.FAIL);
}
@Override
public String getErrorPath() {
log.error("errorPath....");
return ERROR_PATH;
}
}
@ControllerAdvice
ControllerAdvice用来处理发生Exception错误的注解。需要注意的是不能使用try catch 捕获
@ControllerAdvice样例
/**
* @author geekidea
* @date 2018-11-08
*/
@ControllerAdvice
@RestController
@Slf4j
public class GlobalExceptionHandler {
/**
* 非法参数验证异常
*
* @param ex
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(value = HttpStatus.OK)
public ApiResult<List<String>> handleMethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
printRequestDetail();
BindingResult bindingResult = ex.getBindingResult();
List<String> list = new ArrayList<>();
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
list.add(fieldError.getDefaultMessage());
}
Collections.sort(list);
log.error(getApiCodeString(ApiCode.PARAMETER_EXCEPTION) + ":" + JSON.toJSONString(list));
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION, list);
}
/**
* 系统登录异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = SysLoginException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> sysLoginExceptionHandler(SysLoginException exception) {
printRequestDetail();
printApiCodeException(ApiCode.LOGIN_EXCEPTION, exception);
return ApiResult.fail(ApiCode.LOGIN_EXCEPTION);
}
/**
* HTTP解析请求参数异常
*
* @param exception
* @return
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> httpMessageNotReadableException(HttpMessageNotReadableException exception) {
printRequestDetail();
printApiCodeException(ApiCode.PARAMETER_EXCEPTION, exception);
return ApiResult.fail(ApiCode.PARAMETER_EXCEPTION);
}
/**
* HTTP
*
* @param exception
* @return
*/
@ExceptionHandler(value = HttpMediaTypeException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> httpMediaTypeException(HttpMediaTypeException exception) {
printRequestDetail();
printApiCodeException(ApiCode.HTTP_MEDIA_TYPE_EXCEPTION, exception);
return ApiResult.fail(ApiCode.HTTP_MEDIA_TYPE_EXCEPTION);
}
/**
* 自定义业务/数据异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = {SpringBootPlusException.class})
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> springBootPlusExceptionHandler(SpringBootPlusException exception) {
printRequestDetail();
log.error("springBootPlusException:", exception);
int errorCode;
if (exception instanceof BusinessException) {
errorCode = ApiCode.BUSINESS_EXCEPTION.getCode();
} else if (exception instanceof DaoException) {
errorCode = ApiCode.DAO_EXCEPTION.getCode();
} else if (exception instanceof VerificationCodeException) {
errorCode = ApiCode.VERIFICATION_CODE_EXCEPTION.getCode();
} else {
errorCode = ApiCode.SPRING_BOOT_PLUS_EXCEPTION.getCode();
}
return new ApiResult<Boolean>()
.setCode(errorCode)
.setMessage(exception.getMessage());
}
/**
* 登录授权异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = AuthenticationException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> authenticationExceptionHandler(AuthenticationException exception) {
printRequestDetail();
printApiCodeException(ApiCode.AUTHENTICATION_EXCEPTION, exception);
return ApiResult.fail(ApiCode.AUTHENTICATION_EXCEPTION);
}
/**
* 未认证异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = UnauthenticatedException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> unauthenticatedExceptionHandler(UnauthenticatedException exception) {
printRequestDetail();
printApiCodeException(ApiCode.UNAUTHENTICATED_EXCEPTION, exception);
return ApiResult.fail(ApiCode.UNAUTHENTICATED_EXCEPTION);
}
/**
* 未授权异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = UnauthorizedException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> unauthorizedExceptionHandler(UnauthorizedException exception) {
printRequestDetail();
printApiCodeException(ApiCode.UNAUTHORIZED_EXCEPTION, exception);
return ApiResult.fail(ApiCode.UNAUTHORIZED_EXCEPTION);
}
/**
* JWT Token解析异常
*
* @param exception
* @return
*/
@ExceptionHandler(value = JWTDecodeException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> jWTDecodeExceptionHandler(JWTDecodeException exception) {
printRequestDetail();
printApiCodeException(ApiCode.JWTDECODE_EXCEPTION, exception);
return ApiResult.fail(ApiCode.JWTDECODE_EXCEPTION);
}
/**
* 默认的异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<String> httpRequestMethodNotSupportedExceptionHandler(Exception exception) {
printRequestDetail();
printApiCodeException(ApiCode.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION, exception);
return ApiResult.fail(ApiCode.HTTP_REQUEST_METHOD_NOT_SUPPORTED_EXCEPTION.getCode(), exception.getMessage());
}
/**
* 默认的异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseStatus(HttpStatus.OK)
public ApiResult<Boolean> exceptionHandler(Exception exception) {
printRequestDetail();
printApiCodeException(ApiCode.SYSTEM_EXCEPTION, exception);
return ApiResult.fail(ApiCode.SYSTEM_EXCEPTION);
}
/**
* 打印请求详情
*/
private void printRequestDetail() {
RequestDetail requestDetail = RequestDetailThreadLocal.getRequestDetail();
if (requestDetail != null) {
log.error("异常来源:ip: {}, path: {}", requestDetail.getIp(), requestDetail.getPath());
}
}
/**
* 获取ApiCode格式化字符串
*
* @param apiCode
* @return
*/
private String getApiCodeString(ApiCode apiCode) {
if (apiCode != null) {
return String.format("errorCode: %s, errorMessage: %s", apiCode.getCode(), apiCode.getMessage());
}
return null;
}
/**
* 打印错误码及异常
*
* @param apiCode
* @param exception
*/
private void printApiCodeException(ApiCode apiCode, Exception exception) {
log.error(getApiCodeString(apiCode), exception);
}
}
本文介绍了在Java中,@ControllerAdvice用于处理Exception,而ErrorController则处理Error。详细讲解了ErrorController的源码和重写样例,以及@ControllerAdvice的使用示例,帮助理解Spring Boot中如何优雅地处理错误信息。
472

被折叠的 条评论
为什么被折叠?



