版权声明:转载原创博客请附上原文链接 https://blog.csdn.net/weixin_43495590/article/details/89434578
一:场景与设计
1.1 实战场景
- 入参
参数过多
,需要进行多维度校验
如空值、范围值、格式等 - 校验规则
修改较频繁
1.2 设计思想
- 根据HTTP协议异常分类思想实现异常枚举、策略维度划分
- 门面将策略组装,屏蔽上层模块校验策略实现
二:优点
- 异常信息枚举+自定义异常有益于异常定位以及异常管理
- 策略抽象划分校验维度符合
单一职责原则
- 门面组装让上层模块屏蔽掉校验策略实现,符合
迪米特法则
- 最主要丢掉上层模块大批量出现if - else 判断,避免出现多次修改后出现的
重复校验、校验层次混乱
问题
三:缺点
- 代码量上升,可读性相对于直接使用if - else某些层面有所下降
- 现有检验规则修改还是不可避免需要修改检验策略类
四:代码实现
4.1 异常信息枚举
将异常编码与信息根据校验维度使用枚举类进行封装,统一管理异常
/**
* @EnumName: ParameterLenthEnum
* @Description 参数空值检验信息异常枚举
* @Author: zsl
* @Data: 2019/4/17 10:46
* @Version 1.0
**/
public enum ParameterNullValueEnum {
REQUEST_MESSAGE(5000,"请求报文空值异常"),
MESSAGE_HEAD(5001,"报文头空值异常"),
MESSAGE_BODY(5002,"报文体空值异常"),
VERSION(5003,"接口版本号空值异常"),
......
REQURL(5011,"接口请求地址空值异常");
private Integer code;
private String message;
private ParameterNullValueEnum(Integer _code, String _message){
this.code = _code;
this.message = _message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
/**
* @EnumName: ParameterLegalEnum
* @Description 参数合法校验异常枚举
* @Author: zsl
* @Data: 2019/4/17 13:16
* @Version 1.0
**/
public enum ParameterLegalEnum {
PROVINCE(5201,"省份编码属性值非法"),
SOURCE_CODE(5202,"数据来源编码属性值非法"),
MESTYPE(5203,"报文类型编码属性值非法");
private Integer code;
private String message;
private ParameterLegalEnum(Integer _code,String _message){
this.code = _code;
this.message = _message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
4.2 自定义异常类
使用异常信息枚举对象自定义异常类
/**
* @ClassName: ParameterNullValueException
* @Description 参数空值异常
* @Author: zsl
* @Data: 2019/4/17 10:16
* @Version 1.0
**/
public class ParameterNullValueException extends NullPointerException{
private ParameterNullValueEnum nve;
public ParameterNullValueException(ParameterNullValueEnum _nve){
this.nve = _nve;
}
public ParameterNullValueEnum getNve() {
return nve;
}
public void setNve(ParameterNullValueEnum nve) {
this.nve = nve;
}
@Override
public String getMessage() {
return "异常编码: "+this.nve.getCode() +" 异常信息:"+ this.nve.getMessage();
}
}
/**
* @ClassName: ParameterLegalException
* @Description 参数合法性异常
* @Author: zsl
* @Data: 2019/4/17 13:24
* @Version 1.0
**/
public class ParameterLegalException extends IllegalArgumentException{
private ParameterLegalEnum ple;
public ParameterLegalException(ParameterLegalEnum _ple){
this.ple = _ple;
}
public ParameterLegalEnum getPle() {
return ple;
}
public void setPle(ParameterLegalEnum ple) {
this.ple = ple;
}
@Override
public String getMessage() {
return "异常编码: "+this.ple.getCode() +" 异常信息:"+ this.ple.getMessage();
}
}
4.3 策略抽象封装
封装维度根据入参、返回值下的空值校验、异常非法值校验等几方面
/**
* @InterfaceName: CheckStrategy
* @Description 校验策略
* @Author: zsl
* @Data: 2019/4/17 10:08
* @Version 1.0
**/
public interface CheckStrategy {
void checkMethod() throws ParameterNullValueException, ParameterLegalException;
}
/**
* @ClassName: AbstractParameterCheck
* @Description 参数检验抽象
* @Author: zsl
* @Data: 2019/4/17 11:09
* @Version 1.0
**/
public abstract class AbstractCheck implements CheckStrategy{
private RequestMessage rm;
protected AbstractCheck(RequestMessage _rm){
this.rm = _rm;
}
protected RequestMessage getRm() {
return rm;
}
protected void setRm(RequestMessage rm) {
this.rm = rm;
}
}
/**
* @ClassName: ParameterCheckStrategy
* @Description 参数校验空值策略
* @Author: zsl
* @Data: 2019/4/17 10:13
* @Version 1.0
**/
public class ParameterNullCheckStrategy extends AbstractCheck {
public ParameterNullCheckStrategy(RequestMessage _rm) {
super(_rm);
}
@Override
public void checkMethod() throws ParameterNullValueException {
// 对象空值检验
RequestMessage rm = this.getRm();
if (rm == null)
throw new ParameterNullValueException(ParameterNullValueEnum.REQUEST_MESSAGE);
......
}
}
/**
* @ClassName: ParameterLegalCheckStrategy
* @Description 参数合法校验策略
* @Author: zsl
* @Data: 2019/4/17 13:14
* @Version 1.0
**/
public class ParameterLegalCheckStrategy extends AbstractCheck {
public ParameterLegalCheckStrategy(RequestMessage _rm) {
super(_rm);
}
@Override
public void checkMethod() throws ParameterLegalException {
RequestMessage rm = this.getRm();
MessageHead mh = rm.getMh();
// 省份编码合法校验
if (ProvinceEnum.valueOf(mh.getProvince()) == null)
throw new ParameterLegalException(ParameterLegalEnum.PROVINCE);
......
// 渠道来源编码有效监测
Integer sourceCode = mh.getSourceCode();
if(!(99 < sourceCode && sourceCode < 111)
|| (119 < sourceCode && sourceCode < 125)
|| (129 < sourceCode && sourceCode < 134)
|| (199 < sourceCode && sourceCode < 208)
|| (219 < sourceCode && sourceCode < 224)
|| (229 < sourceCode && sourceCode < 235)
|| (sourceCode == 999))
throw new ParameterLegalException(ParameterLegalEnum.SOURCE_CODE);
}
}
4.4 门面组装
屏蔽上层模块校验策略实现
/**
* @ClassName: CheckFacade
* @Description 校验策略门面组装、新增校验策略类继承抽象类AbstractCheck
* 补充对应策略类实例对象作为属性即可
* @Author: zsl
* @Data: 2019/4/19 11:35
* @Version 1.0
**/
public class CheckFacade {
private RequestMessage rm;
private ParameterNullCheckStrategy pncs = new ParameterNullCheckStrategy(rm);
private ParameterLegalCheckStrategy plcs = new ParameterLegalCheckStrategy(rm);
public void checkMethod() throws IllegalAccessException, ParameterLegalException, ParameterNullValueException {
Field[] declaredFields = this.getClass().getDeclaredFields();
Class<AbstractCheck> clazz = AbstractCheck.class;
for (Field f : declaredFields){
Class<?> superclass = f.getType().getSuperclass();
if ( superclass == clazz){
AbstractCheck apc = (AbstractCheck) f.get(this);
apc.checkMethod();
}
}
}
public CheckFacade(RequestMessage _rm){
this.rm = _rm;
}
}
4.5 调用层
public static void main (String[] args){
new CheckFacade(this.rm);
}