在项目中,自定义全局异常处理器可以带来以下几个好处:
-
统一异常处理:通过自定义全局异常处理器,你可以集中处理整个应用程序中出现的异常情况。这样可以确保异常处理的一致性,避免在每个Controller或业务逻辑代码中重复编写异常处理的代码。
-
错误信息定制:通过自定义全局异常处理器,你可以对异常信息进行定制,以满足项目的具体需求。你可以选择返回自定义的错误消息、错误码或错误对象,从而提供更有意义的错误响应给客户端。
-
异常分类处理:通过自定义全局异常处理器,你可以根据异常类型进行分类处理。不同类型的异常可以被映射到不同的处理方法,从而提供特定的处理逻辑。例如,你可以处理业务异常、数据库异常、网络异常等,并返回不同的响应或执行相应的补救措施。
-
异常日志记录:自定义全局异常处理器还可以用于记录异常日志,方便后续的问题排查和故障诊断。你可以在处理异常时记录异常信息、请求参数、堆栈跟踪等相关信息,以帮助定位问题。
总之,通过自定义全局异常处理器,你可以提高代码的可维护性和可读性,提供更好的用户体验,并更好地管理和处理应用程序中的异常情况。
觉得麻烦 简单点记就是你开发个app总不能给用户返回这个吧
这只是个例子,当然这种错误在生产环境基本不会发生 这属于很低级的错误 但是如果发生了一些错误总不能把错误返回给用户吧,用户又不懂
这个时候可以写一个自定义全局异常 到时候可以给用户端返回一个比较友好的信息
1.定义一个错误的枚举
package com.example.myrestcontrolleradvice.RestControllerAdvice;
import lombok.Getter;
@Getter
public enum ResultCodeEnum {
UNKNOWN_REASON(false, 20001, "未知错误"),
SERVER_ERROR(false, 500, "服务器忙,请稍后在试"),
ORDER_CREATE_FAIL(false, 601, "订单下单失败");
private Boolean success;
private Integer code;
private String message;
private ResultCodeEnum(Boolean success, Integer code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
}
2.异常封装
package com.example.myrestcontrolleradvice.RestControllerAdvice;
import lombok.*;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@ToString
public class ErrorHandler {
// 异常的状态码
private Integer status;
// 异常的消息,写用户看得懂的异常
private String message;
// 异常信息
private String exception;
public static ErrorHandler fail(String errorName) {
ErrorHandler errorHandler = new ErrorHandler();
errorHandler.setMessage("操作失败");
errorHandler.setStatus(500);
errorHandler.setException(errorName);
return errorHandler;
}
}
3.使用@ControllerAdvice
注解和@ExceptionHandler
注解来定义全局异常处理器
package com.example.myrestcontrolleradvice.RestControllerAdvice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.UndeclaredThrowableException;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 对服务器端出现500异常进行统一处理
*/
@ExceptionHandler(value = RuntimeException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorHandler makeExcepton(Throwable e, HttpServletRequest request) {
String message = e.getMessage();
if (e instanceof UndeclaredThrowableException){
Throwable undeclaredThrowable = ((UndeclaredThrowableException) e).getUndeclaredThrowable();
message = undeclaredThrowable.getMessage();
}
ErrorHandler errorHandler = ErrorHandler.fail(e.getClass().getName()+ ": " +message);
log.error("请求的地址:{},出现的异常:{}", request.getRequestURL(), e);
System.out.println("RuntimeException");
return errorHandler;
}
/**
* 空指针异常 统一处理
*/
@ExceptionHandler(value =NullPointerException.class)
@ResponseBody
public ErrorHandler exceptionHandler(NullPointerException e, HttpServletRequest request){
String message = e.getMessage();
ErrorHandler errorHandler = ErrorHandler.fail(e.getClass().getName()+ ": " +message);
log.error("请求的地址:{},出现的空指针异常:{}", request.getRequestURL(), e);
System.out.println("NullPointerException");
return errorHandler;
}
/**
* 未知异常 统一处理
*/
@ExceptionHandler(value =Exception.class)
@ResponseBody
public ErrorHandler exceptionHandler(Exception e, HttpServletRequest request){
String message = e.getMessage();
if (e instanceof UndeclaredThrowableException){
Throwable undeclaredThrowable = ((UndeclaredThrowableException) e).getUndeclaredThrowable();
message = undeclaredThrowable.getMessage();
}
ErrorHandler errorHandler = ErrorHandler.fail(e.getClass().getName()+ ": " +message);
log.error("请求的地址:{},出现的异常:{}", request.getRequestURL(), e);
System.out.println("Exception");
return errorHandler;
}
}
4.写一个controller试一下
package com.example.myrestcontrolleradvice.controller;
import com.example.myrestcontrolleradvice.domain.User;
import com.example.myrestcontrolleradvice.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("api")
public class UserController {
@Resource
private UserService userService;
@GetMapping("error1")
public Integer error1(Integer id) {
//0<=id<4可以正常返回id 如果id>=5 则java.lang.ArrayIndexOutOfBoundsException: 5
Integer[] i=new Integer[5];
Integer c=i[id];
return id;
}
@GetMapping("error2")
public Integer error2() {
//java.lang.NullPointerException: null
String str = null;
Integer length = str.length();
return length;
}
@GetMapping("error3")
public List<User> error3() {
List<User> users = userService.selectList();
return users;
}
}
运行error1接口的结果
运行error2接口的结果
运行error3接口的结果
user类中写的是pwd
package com.example.myrestcontrolleradvice.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
/**
*
* @TableName user
*/
@TableName(value ="user")
@Data
public class User implements Serializable {
/**
*
*/
private String uname;
/**
*
*/
private String pwd;
/**
*
*/
private String sex;
}
数据库中的user表是upwd
所以会报找不到pwd的错误
不出意外的话现在返回的异常信息应该都是
{
"status": 500,
"message": "操作失败",
"exception": ""
}格式的了
当然这个可以根据自己需要来改