後端架構的搭建臨近尾聲,在項目搭建的一些工作做了細化,配置了一個全局異常處理器,用來捕捉所有程式發生的異常,資料校驗器用來對前端傳來的資料做一些檢查工作,避免髒資料入庫,還要一個常量接口,主要用來儲存我們用到的一些常量.還有一個就是自定義業務異常類,用來細分到底是哪個業務出了問題,這樣找起來也好找.
1.全局異常處理器(GlobeExceptionHandler)
隻要出現異常,就會走全局異常處理器
當程式抛出異常時,對異常進行攔截處理,根據異常的對象的資訊,将這些資訊轉化為JSON資料傳回給用戶端
package com.zw.common.handler;
/**
* 隻要出現異常,就會走全局異常處理器
* 當程式抛出異常時,對異常進行攔截處理,根據異常的對象的資訊,将這些資訊轉化為JSON資料傳回給用戶端
*/
import com.zw.common.CodeMsg;
import com.zw.common.Result;
import com.zw.common.exception.BussiException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @ClassName:GlobeExceptionHandler
* @Description: 全局異常處理器
* @Author: KevinZeng
* @Date 2020/1/8 下午 9:44
*/
@ControllerAdvice
public class GlobeExceptionHandler {
/**
* 處理異常
* @param exception 發生異常的對象
* @return
*/
@ExceptionHandler
@ResponseBody
public Result bussiExceptionHandler(Exception exception){
System.err.println(exception.getMessage());
//判斷抛出的異常是否是程式員自定義的業務異常
if(exception instanceof BussiException){
BussiException bussiException = (BussiException) exception;
Result rs = new Result();
rs.setCode(bussiException.getCode());
rs.setMsg(bussiException.getMsg());
System.out.println(rs);
return rs;
}
//是程式報錯
return new Result(CodeMsg.ERROR);
}
}
2.自定義業務異常類
package com.zw.common.exception;
/**
* 當程式出現資料異常時就抛出異常資訊
* 兩種情況:
* 1.當資料校驗不通過時,抛出異常資訊
* 2.當資料操作出現異常時,抛出異常資訊,也是為了資料復原
*/
/**
* @ClassName:BussiException
* @Description: 自定義業務異常類:
* @Author: KevinZeng
* @Date 2020/1/8 下午 9:39
*/
public class BussiException extends RuntimeException{
/**
* 異常編碼
*/
private Integer code;
/**
* 異常資訊
*/
private String msg;
public BussiException() {
}
public BussiException(Integer code, String msg) {
super(code+":"+msg);
this.code = code;
this.msg = msg;
}
//getters and setters 略
}
3.資料校驗器
package com.zw.common.validator;
/**
* 用于校驗請求的資料
* 請求的參數,有各種類型,各種類别,有一樣存在公共點,例如:
* 請求的參數不能為空
* 請求的參數 最大 最小值
* 請求的資料的字元串長度
* 使用者名:不能為空 長度
*/
import java.util.Set;
import com.zw.common.Constant;
import com.zw.common.exception.BussiException;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
/**
* @ClassName:Validator
* @Description: 資料校驗器
* @Author: KevinZeng
* @Date 2020/1/9 下午 6:00
*/
public class ValidatorUtil {
/**
* 資料校驗器
*/
static final Validator validator;
static {
//擷取一個資料校驗器
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
public static void validator(Object form) {
Set<ConstraintViolation<Object>> validate = validator.validate(form);
for (ConstraintViolation<Object> constraintValidation : validate) {
//校驗不通過的資訊
String message = constraintValidation.getMessage();
//校驗不通過 抛出異常
throw new BussiException(Constant.FORM_DATA_CHECK_ERROR_CODE, message);
}
}
}
4.常量接口
package com.zw.common;
/**
* 常量接口
*/
public interface Constant {
/**
* 表單資料校驗錯誤碼
*/
Integer FORM_DATA_CHECK_ERROR_CODE = 4001001;
}
5.對form類進行修改不用繼承了,直接使用裡面的屬性就夠了,在form裡面可以進行資料的一些限制.
package com.zw.sys.form;
/**
* 比如insert操作,以前的資料都是将前端傳來的資料封裝成user對象,現在用form包下的對象去接收,
* 于是我們的SysUsersForm去繼承SysUsers,
*/
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
/**
* @ClassName:SysUsersForm
* @Description: 用于接收更新user表的資料的類
* @Author: KevinZeng
* @Date 2020/1/8 下午 11:01
*/
public class SysUsersForm {
/**
* 使用者編号
*/
private Integer id;
/**
* 登入名
*/
@NotBlank(message = "使用者登入名不能為空")
@Length(min = 6, max = 15, message = "使用者登入名隻能為6-15個字元")
private String loginName;
/**
* 登入密碼
*/
private String password;
/**
* 身份證号碼
*/
private String idCard;
/**
* 真實名稱
*/
private String realName;
/**
* 性别 1男 2女
*/
private Integer sex;
/**
* 位址
*/
private String address;
/**
* 電話
*/
private String phone;
/**
* 使用者頭像
*/
private String img;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
}
5.我出現的問題
在編寫的過程中遇到一個問題,就是不能将null資料轉化為json資料,輸出到頁面上,使用postman工具也沒有成功.
第一次出現這個問題
結果是這樣的
{
"code": 1001,
"msg":"程式員進ICU了"
}
正常來說,是應該要有
"data:null",
剛開始沒有注意問題的所在,于是到處調試,
後來我想到将msg設定為null還會有嗎?
結果是這樣子的,
{
"code": 1001
}
看來的确value為null的鍵值對,确實在後端傳送到前端時被過濾到了,
于是我到處去網上翻貼,搜尋傳回json資料,屬性值為null或空被省略的問題。
解決了,真的解決了,解決方案有很多,我的原因是包到導入問題,後來導入jack_json的相關jar包就好了,在其中也了解到了fastjson可以在springmvc.xml配置檔案中配置json轉換器.
6.系統流程
分析:
用戶端在通過url通路伺服器傳回的頁面之前,首先有一個攔截器,比如登入攔截器,登入攔截器如何實作以後在寫,不難,攔截過後,會走controller層處理前端傳過來的資料,這個資料應該是form對象,首先我們在controller層會進行一個資料的校驗,這裡主要就是資料的規範性,如果不合法,我們抛出異常,讓異常處理器去處理,然後将經過處理的異常資訊傳回給用戶端,如果沒有發生異常,controller層的crud操作的資料傳到service層,這裡面也有一些驗證的過程,不細說了,也是和controller層的一些校驗道理差不多,隻不過資料校驗的可能側重于資料的合法性(比如不能有相同的手機号等),之後就是service将CRUD操作的資料傳到mapper層,由mapper層對資料庫進行增删改查等操作.
