一.响应正文的结果类型
- 当响应正文时,只要方法的返回值是自定义的数据类型,则Spring MVC 框架就一定会调用jackson-databind中的转换器,就可以将结果转换为 JSON格式的字符串
- 通常,在项目开发中,会定义一个“通用”的数据类型,无论是哪个控制 器的哪个处理请求的方法,最终都将返回此类型,显示的通用返回类型如下:
-
public class JsonResult<T> { private Integer state; // 业务返回码 private String message; // 消息 private T data; // 数据 // Setters & Getters private JsonResult() { } public static JsonResult<Void> ok() { return ok(null); } public static <T> JsonResult<T> ok(T data) { JsonResult<T> jsonResult = new JsonResult<>(); jsonResult.state = State.OK.getValue(); jsonResult.data = data; return jsonResult; } public static JsonResult<Void> fail(State state, String message) { JsonResult<Void> jsonResult = new JsonResult<>(); jsonResult.state = state.getValue(); jsonResult.message = message; return jsonResult; } public enum State { OK(20000), ERR_USERNAME(40400), ERR_PASSWORD(40600); Integer value; State(Integer value) { this.value = value; } public Integer getValue() { return value; } } }
二.统一的异常处理机制
1. Spring MVC框架提供了统一处理异常的机制,使得特定种类的异常对应 一段特定的代码,后续,当编写代码时,无论在任何位置,都可以将异常 直接抛出,由统一处理异常的代码进行处理即可
2.无论哪种异常(包括RuntimeException及其子孙类异常),只要没有显式的使用 try...catch语法进行捕获并处理,均视为抛出
3.关于统一处理异常,需要自定义方法对异常进行处理,关于此方法:
- 注解:必须添加@ExceptionHandler注解
- 访问权限:应该是公有的
- 返回值类型:可参考处理请求的方法的返回值类型
- 方法名称:自定义
- 参数列表:必须包含1个异常类型的参数,并且可按需添加HttpServletRequest、 HttpServletResponse等少量特定的类型的参数,不可以随意添加参数
例如,创建GlobalExceptionHandler类,代码如下:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
public String handleException(NullPointerException e) {
return "Error, NullPointerException!";
}
}
4.处理的方法的参数中的异常类型,就是Spring MVC框架将统一处理的异 常类型,例如将参数声明为Throwable类型时,所有异常都可被此方法进 行处理!但是,在处理过程中,应该判断当前异常对象所归属的类型,以 针对不同类型的异常进行不同的处理
5.Spring MVC允许存在多个统一处理异常的方法,这些方法可以在不同的 类中,只要处理的异常的类型不冲突即可(允许继承)
- 例如:如果有2个或多个方法都处理NullPointerException,是错误的
- 例如:如果同时存在2个方法,分别处理NullPointerException和 RuntimeException,是允许的
@ExceptionHandler
public String handleNullPointerException(NullPointerException e) {
return "Error, NullPointerException!";
}
@ExceptionHandler
public String handleNumberFormatException(NumberFormatException e) {
return "Error, NumberFormatException!";
}
@ExceptionHandler
public String handleThrowable(Throwable e) {
e.printStackTrace();
return "Error, Throwable!";
}
6.在开发实践中,通常都会有handleThrowable()方法(方法名是自定义 的),以避免某个异常没有被处理而导致500错误!
- 此方法中应该输出异常的相关信息,甚至跟踪信息,否则,当程序运行此至处时,可 能不便于观察、分析、记录出现异常
7.@ExceptionHandler注解还可用于配置被注解的方法能够处理的异常的 类型,其效力的优先级高于在方法的参数上指定异常类型
8.在开发实践中,建议为每一个@ExceptionHandler配置注解参数,在注 解参数中指定需要处理异常的类型,而处理异常的方法的参数类型只需要 包含@ExceptionHandler配置的类型即可,甚至可以是Throwable
@ExceptionHandler({
NullPointerException.class,
ClassCastException.class
})
public String handleNullPointerException(Throwable e) {
return "Error, NullPointerException or ClassCastException!";
}
@ExceptionHandler(NumberFormatException.class)
public String handleNumberFormatException(Throwable e) {
return "Error, NumberFormatException!";
}
@ExceptionHandler(Throwable.class)
public String handleThrowable(Throwable e) {
return "Error, Throwable!";
}