后端框架的搭建临近尾声,在项目搭建的一些工作做了细化,配置了一个全局异常处理器,用来捕捉所有程序发生的异常,数据校验器用来对前端传来的数据做一些检查工作,避免脏数据入库,还要一个常量接口,主要用来保存我们用到的一些常量.还有一个就是自定义业务异常类,用来细分到底是哪个业务出了问题,这样找起来也好找.
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层对数据库进行增删改查等操作.
