Java程序设计:spring boot(13)——全局异常与事务控制
1 Spring Boot 事务支持
在使⽤ Jdbc 作为数据库访问技术时,Spring Boot框架定义了基于jdbc的PlatformTransaction Manager 接⼝的实现 DataSourceTransactionManager,并在 Spring Boot 应⽤ 启动时⾃动进⾏配置。如果使⽤ jpa 的话 Spring Boot 同样提供了对应实现。
这⾥ Spring Boot 集成了 mybatis 框架,mybatis 底层数据访问层实现基于 jdbc 来实现,所以在 Spring Boot 环境下对事务进⾏控制,事务实现由 Spring Boot 实现并⾃动配置,在使⽤时通过注解⽅ 式标注相关⽅法加⼊事务控制即可。
声明式事务配置:
@Transactional(propagation = Propagation.REQUIRED)
public void saveUser(User user) {
AssertUtil.isTrue(StringUtils.isBlank(user.getUserName()), "⽤户名不能为空!");
AssertUtil.isTrue(StringUtils.isBlank(user.getUserPwd()),"⽤户密码不能为空!");
User temp = userMapper.queryUserByUserName(user.getUserName());
AssertUtil.isTrue(null != temp, "该⽤户已存在!");
AssertUtil.isTrue(userMapper.save(user)<1,"⽤户记录添加失败!");
}
@Transactional(propagation = Propagation.REQUIRED)
public void updateUser(User user) {
AssertUtil.isTrue(StringUtils.isBlank(user.getUserName()), "⽤户名不能为空!");
AssertUtil.isTrue(StringUtils.isBlank(user.getUserPwd()),"⽤户密码不能为空!");
User temp = userMapper.queryUserByUserName(user.getUserName());
AssertUtil.isTrue(null != temp && !(temp.getId().equals(user.getId())), "该⽤
户已存在!");
AssertUtil.isTrue(userMapper.update(user)<1,"⽤户记录添加失败!");
}
@Transactional(propagation = Propagation.REQUIRED)
public void deleteUser(Integer id){
AssertUtil.isTrue(null == id || null ==userMapper.queryById(id),"待删除记录不存
在!");
AssertUtil.isTrue(userMapper.delete(id)<1,"⽤户删除失败!");
}
2 Spring Boot 全局异常处理
SpringMvc 中对异常统⼀处理提供了相应处理⽅式,推荐⼤家使⽤的是实现接⼝ Handler ExceptionResolver的⽅式,对代码侵⼊性较⼩。
在Spring Boot 应⽤中同样提供了对异常的全局性处理,相关注解如下。
2.1 @ControllerAdvice
该注解组合了 @Component 注解功能,最常⽤的就是作为全局异常处理的切⾯类,同时通过该注解 可以指定包扫描的范围。@ControllerAdvice 约定了⼏种可⾏的返回值,如果是直接返回 model 类的 话,需要使⽤@ResponseBody 进⾏ json 转换。
2.2 @ExceptionHandler
该注解在 Spring 3.X 版本引⼊,在处理异常时标注在⽅法级别,代表当前⽅法处理的异常类型有哪些 具体应⽤以 Restful 接⼝为例,测试保存⽤户接⼝。
2.3 全局异常应用
2.3.1 异常抛出与全局异常捕获
UserController 查询接⼝:
@ApiOperation(value = "根据⽤户id查询⽤户记录")
@ApiImplicitParam(name = "userId",value = "⽤户ID",required = true, paramType =
"path")
@GetMapping("user/id/{userId}")
public User queryUserByUserId(@PathVariable Integer userId){
return userService.queryUserByUserId(userId);
}
UserService 查询业务⽅法,抛出 ParamExceptions 异常:
public User queryUserByUserId(Integer userId){
// 抛出异常
AssertUtil.isTrue(true,"异常测试...");
return userMapper.queryById(userId);
}
全局异常处理类 GlobalExceptionHandler 定义:
@ControllerAdvice
public class GlobalExceptionHandler{
/**
* 全局异常处理 返回json
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResultInfo exceptionHandler(Exception e){
ResultInfo resultInfo = new ResultInfo();
resultInfo.setCode(300);
resultInfo.setMsg("操作失败!");
if(e instanceof ParamsException){
ParamsException pe = (ParamsException) e;
resultInfo.setMsg(pe.getMsg());
resultInfo.setCode(pe.getCode());
}
return resultInfo;
}
}
Postman 执⾏测试效果:
2.3.2 特定异常处理
通过 @ExceptionHandler 标注⽅法处理特定异常,这⾥以⽤户未登录异常为例,通过全局异常进 ⾏统⼀处理:
/**
* ⽤户未登录异常特殊处理 返回json
* @param authExceptions
* @return
*/
@ExceptionHandler(value = NoLoginException.class)
@ResponseBody
public ResultInfo userNotLoginHandler(NoLoginException authExceptions){
System.out.println("⽤户未登录异常处理。。。");
ResultInfo resultInfo = new ResultInfo();
resultInfo.setCode(authExceptions.getCode());
resultInfo.setMsg(authExceptions.getMsg());
return resultInfo;
}
在⽤户修改接⼝中抛出未登录异常为例进⾏测试:
/**
* 修改⽤户
* @param user
* @return
*/
@ApiOperation(value = "更新⽤户")
@ApiImplicitParam(name = "user", value = "⽤户对象")
@PostMapping("/user")
public ResultInfo updateUser(@RequestBody User user) {
if(1 == 1){
throw new NoLoginException();
}
ResultInfo resultInfo = new ResultInfo();
userService.updateUser(user);
return resultInfo;
}
Postman 执⾏测试效果: