Day07 SpringBoot異常處理、事務處理
阿新 • • 發佈:2018-12-31
- 一、事務處理
需求:當同時插入兩條資料,若有一條資料插入失敗,則兩條資料都將不插入。
分析:不用事務的話,成功的那條資料會被插入進去,導致資料不統一。
解決方案:
增加事務處理。只需要在插入資料的業務邏輯處理方法上面增加@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,"未知錯誤");
}
}
}