Day07 SpringBoot异常处理、事务处理

  • 一、事务处理

需求:当同时插入两条数据,若有一条数据插入失败,则两条数据都将不插入。

分析:不用事务的话,成功的那条数据会被插入进去,导致数据不统一。

解决方案:
增加事务处理。只需要在插入数据的业务逻辑处理方法上面增加@Transactional注解

注意:必须将mysql引擎改为InnoDB才会生效
事务

controller:

@GetMapping(value = "/girls")
    public void InsertTwo(){
        girlService.InsertTwo();
    }

Service:

@Autowired
    private GirlRepository girlRepository;
    //若不加事务,grilB出现数据异常,则B不会插入进去,A却会插入进去
    @Transactional
    public void InsertTwo(){
        Girl girlA = new Girl();
        girlA.setAge(25);
        girlA.setCup("C");
        girlRepository.save(girlA);


        Girl girlB = new Girl();
        girlB.setAge(28);
        girlB.setCup("CCC");
        girlRepository.save(girlB);
    }
  • 二、异常处理

需求:在实际的项目开发中,无论调用接口成功还是失败,往往要求返回值有一个标准格式,来供大家查看异常。
成功:

{
  "code": 1,
  "msg": "success",
  "data": {
   //json格式的数据信息
  }
}

失败:返回错误及错误信息

{
  "code": 0,
  "msg": "error",
  "data": null
}

项目目录结构:
项目目录结构

  • 1.创建返回结果集用的类(Result.java)
    具体返回的数据用泛型表示(不确定会返回什么数据,用泛型,对返回的数据不会进行限制)
package com.demo.springbootdemo.domain;

public class Result<T> {
    //错误码
    private Integer code;
    //提示信息
    private  String msg;
    //具体的内容
    private T data;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
  • 2.写一个返回结果集的工具类(ResultUtil)
    为了使代码更加简洁,复用率强。
    在这里定义成功方法和返回方法,具体编写成功或返回应该封装的result数据。
package com.demo.springbootdemo.utils;

import com.demo.springbootdemo.domain.Result;

public class ResultUtil {
    public static Result success(Object object){
        Result result = new Result();
        result.setCode(0);
        result.setMsg("成功");
        result.setData(object);
        return result;
    }

    public static Result success(){
        return null;
    }

    public static Result error(Integer code, String msg){
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
}

-3. 写结果枚举类(ResultEnum)统一维护
防止code,msg自己书写导致写重复,和,code,msg管理不方便。

package com.demo.springbootdemo.enums;

//统一维护,code,message
public enum ResultEnum {
    UNKONW_ERROR(-1,"未知错误"),
    success(0,"成功"),
    PRIMARY_SCHOOL(100,"你可能还在上小学"),
    MIDDLE_SCHOOL(101,"你在上初中吧");

    private Integer code;
    private String msg;

    ResultEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}
  • 4.自定义异常类(GirlException)
    在遇到异常的时候,希望能通过code判断{成功/自定义异常/系统未知错误}这里建议自定义一个异常类。
    由于spring框架在处理Exception时不会进行事务回滚,在处理RuntimeException时会进行事务回滚,故应继承RuntimeException
package com.demo.springbootdemo.exception;

import com.demo.springbootdemo.enums.ResultEnum;

public class GirlException extends RuntimeException{
    private Integer code;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public GirlException(ResultEnum resultEnum) {
        super(resultEnum.getMsg());
        this.code = resultEnum.getCode();
    }
}

-5.Controller调用

@PostMapping(value = "/girlcheckTry")
    public Result<Girl> girlAddCheckTry(@Valid Girl girl, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
           return null; //捕获异常
            //如果验证出错,输出错误信息

           /*return ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage());*/
        }
        girl.setAge(girl.getAge());
        girl.setCup(girl.getCup());
        return ResultUtil.success(girlRepository.save(girl));
    }

@GetMapping(value = "/girls/getAge/{id}")
    public void getAge(@PathVariable("id") Integer id) throws Exception {
        girlService.getAge(id);
    }

Service业务层具体使用时抛出异常,等待统一处理

public Girl getAge(Integer id) throws Exception {
        Optional<Girl> girl = girlRepository.findById(id);
        Integer age =girl.get().getAge();
        if(age < 10){
            throw new GirlException(ResultEnum.PRIMARY_SCHOOL);
        }else if(age > 10 && age < 16){
            throw new GirlException(ResultEnum.MIDDLE_SCHOOL);
        }
        return girl.get();
    }
  • 6.ExceptionHandle

在异常抛出后,创建一个类捕获程序运行中出现的所以异常,集中处理。

注意:在这里捕获处理过的异常,控制台不会自动打印,因此在这里捕捉到了系统错误,处理时需手动打印,以免实际运行中找不到错误原因

package com.demo.springbootdemo.handle;

import com.demo.springbootdemo.domain.Result;
import com.demo.springbootdemo.exception.GirlException;
import com.demo.springbootdemo.utils.ResultUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;


@ControllerAdvice
public class ExceptionHandle {

    private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
    //捕获异常类
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result handle(Exception e){
        if(e instanceof GirlException){
            GirlException girlException = (GirlException) e;
            return ResultUtil.error(girlException.getCode(),girlException.getMessage());
        }else{
            logger.error("系统异常{}",e);
            return ResultUtil.error(-1,"未知错误");
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值