巧妙的设计一种全局异常处理,业务代码无需重复书写参数校验等判断,
参数校验错误直接通过全局异常处理抛出
- 参数校验异常
我们用不符合我们参数的形式去请求接口会返回异常
但是页面无法捕获,如何拦截这些异常并将错误信息返回给页面是这里要做的

2. 全局异常捕获
我们定义一个统一的全局异常返回
知识点1:@ControllerAdvice是一个增强的 Controller
定义全局异常Controller,
这个ExceptionHandler可以在捕获我们下面定义的异常时自动向前台返回Result信息
从而使得我们无需自己判断这些异常
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(value=Exception.class)
public Result<String> exceptionHandler(HttpServletRequest request, Exception e){
if(e instanceof BindException) {
BindException ex = (BindException)e;
List<ObjectError> errors = ex.getAllErrors();
ObjectError error = errors.get(0);
String msg = error.getDefaultMessage();
return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg));
}else {
return Result.error(CodeMsg.SERVER_ERROR);
}
}
}
其中在CodeMsg中添加方法fillArgs(msg)用于返回当前Code内容
添加一种异常BIND_ERROR
知识点1:Java中可变参数写法public CodeMsg fillArgs(Object... args)
知识点2:String.format(this.msg, args);将后面的数组转成字符串放入%s的位置
public static CodeMsg BIND_ERROR = new CodeMsg(500101, "参数校验异常:%s");
public CodeMsg fillArgs(Object... args) {
int code = this.code;
String message = String.format(this.msg, args);
return new CodeMsg(code, message);
}
这时候我们已经完成了自动捕获绑定异常
- 全局异常定义
我们可以再定义一个全局异常类GlobalException 用于捕获全部的异常
这样所有异常信息便无需判断!
全局异常类中添加private CodeMsg cm;从而让前台按照我们的信息执行。
package com.liuyang.seckill.exception;
import com.liuyang.seckill.result.CodeMsg;
public class GlobalException extends RuntimeException{
private static final long serialVersionUID = 1L;
private CodeMsg cm;
public GlobalException(CodeMsg cm) {
super(cm.toString());
this.cm = cm;
}
public CodeMsg getCm() {
return cm;
}
}
全局异常控制类增加全局异常控制
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(value=Exception.class)
public Result<String> exceptionHandler(HttpServletRequest request, Exception e){
e.printStackTrace();
if(e instanceof GlobalException) {
GlobalException ex = (GlobalException)e;
return Result.error(ex.getCm());
}else if(e instanceof BindException) {
BindException ex = (BindException)e;
List<ObjectError> errors = ex.getAllErrors();
ObjectError error = errors.get(0);
String msg = error.getDefaultMessage();
return Result.error(CodeMsg.BIND_ERROR.fillArgs(msg));
}else {
return Result.error(CodeMsg.SERVER_ERROR);
}
}
}
Service业务代码中遇到问题直接抛出异常
前面GlobalExceptionHandler 可以直接返回Result
public boolean login(LoginVo loginVo) {
if(loginVo == null) {
throw new GlobalException(CodeMsg.SERVER_ERROR);
}
String mobile = loginVo.getMobile();
String formPass = loginVo.getPassword();
//判断手机号是否存在
SeckillUser user = getById(Long.parseLong(mobile));
if(user == null) {
throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
}
//验证密码
String dbPass = user.getPassword();
String saltDB = user.getSalt();
String calcPass = MD5Util.formPassToDBPass(formPass, saltDB);
if(!calcPass.equals(dbPass)) {
throw new GlobalException(CodeMsg.PASSWORD_ERROR);
}
return true;
}
这时候Controller代码无需进行判断
直接在最后返回成功即可
@ResponseBody
@RequestMapping("/do_login")
public Result<Boolean> doLogin(@Valid LoginVo loginVo) {
log.info(loginVo.toString());
seckillUserService.login(loginVo);
return Result.success(true);
}
- 测试
http://localhost:8080/login/do_login?mobile=18844118879&password=12345678912345678912345678900012

本文介绍了一种全局异常处理策略,通过使用@ControllerAdvice注解和自定义异常类,实现业务代码中参数校验错误的自动捕获与处理,避免了重复的异常判断,简化了代码并提高了异常处理的统一性和效率。
149

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



