• 通过Pojo对象 field 属性加注解实现格式校验,极大的降低代码量


    近期做一个接口。接受外系统的报文,通过XStream转换成java对象以后。须要对当中的字段做格式校验。

    要求例如以下:

    传统的方式是硬编码校验。可是对于field非常多的情况。代码量暴增。easy出错。

    String storeCode = uHeader.getStoreCode();
            if (StringUtils.isNotBlank(storeCode)) {
                ParamsUtil.getInstance().checkStrParam(result, storeCode, "抬头-參考订单门店号[storeCode]", LSPConstants.NUM_TEN);
                if (!result.isSuccess()) {
                    return result;
                }
            }
            String routing = uHeader.getRouting();
            if (StringUtils.isNotBlank(routing)) {
                ParamsUtil.getInstance().checkStrParam(result, routing, "抬头-路线[routing]", LSPConstants.NUM_SIX);
                if (!result.isSuccess()) {
                    return result;
                }
            }
            String areaDeliBusSysId = uHeader.getAreaDeliBusSysId();
            if (StringUtils.isNotBlank(areaDeliBusSysId)) {
                ParamsUtil.getInstance().checkStrParam(result, areaDeliBusSysId, "抬头-辖区内配送班车系统编号 [areaDeliBusSysId]",
                        LSPConstants.NUM_TEN);
                if (!result.isSuccess()) {
                    return result;
                }
            }
            String transBusSysId = uHeader.getTransBusSysId();
            if (StringUtils.isNotBlank(transBusSysId)) {
                ParamsUtil.getInstance().checkStrParam(result, transBusSysId, "抬头-联运班车系统编号[transBusSysId]",
                        LSPConstants.NUM_TEN);
                if (!result.isSuccess()) {
                    return result;
                }
            }
            String nostopBusSysId = uHeader.getNostopBusSysId();
            if (StringUtils.isNotBlank(nostopBusSysId)) {
                ParamsUtil.getInstance().checkStrParam(result, nostopBusSysId, "抬头-直达班车班车编号[nostopBusSysId]",
                        LSPConstants.NUM_TEN);
                if (!result.isSuccess()) {
                    return result;
                }
            }
            String speBusSysId = uHeader.getSpeBusSysId();
            if (StringUtils.isNotBlank(speBusSysId)) {
                ParamsUtil.getInstance().checkStrParam(result, speBusSysId, "抬头-穿梭班车系统编号1[speBusSysId]",
                        LSPConstants.NUM_TEN);
                if (!result.isSuccess()) {
                    return result;
                }
            }

    而我更希望的方式是通过对字段添加注解,由系统自己主动校验,如:

    Pojo OmsTaskHead.java:

    public class OmsTaskHead {
    	
    	@FieldNote(name = "參考订单门店号", type = FvEnum.STRING, regex = Regexs.letterAndDigit, isNullAble = true, length = 10)
    	private String storeCode; // 參考订单门店号
    
    	@FieldNote(name = "路线", type = FvEnum.STRING, regex = Regexs.letterAndDigit, length = 6)
    	private String routing; // 路线
    
    	@FieldNote(name = "辖区内配送班车系统编号", type = FvEnum.STRING, regex = Regexs.letterAndDigit, length = 10)
    	private String areaDeliBusSysId; // 辖区内配送班车系统编号
    
    	@FieldNote(name = "联运班车系统编号", type = FvEnum.STRING, regex = Regexs.letterAndDigit, length = 10)
    	private String transBusSysId; // 联运班车系统编号
    
    	@FieldNote(name = "直达班车班车编号", type = FvEnum.STRING, regex = Regexs.letterAndDigit, length = 10)
    	private String nostopBusSysId; // 直达班车班车编号
    
    	@FieldNote(name = "穿梭班车系统编号1", type = FvEnum.STRING, regex = Regexs.letterAndDigit, length = 10)
    	private String speBusSysId; // 穿梭班车系统编号1
    
    	@FieldNote(name = "联运班车发车日期", type = FvEnum.DATE_STR, regex = Regexs.yyyyMMdd, length = 8)
    	private String transBusDate; // 联运班车发车日期
    
    	@FieldNote(name = "辖区班车发车日期", type = FvEnum.DATE_STR, regex = Regexs.yyyyMMdd, length = 8)
    	private String areaDeliBusDate; // 辖区班车发车日期
    
    	@FieldNote(name = "直达班车发车日期", type = FvEnum.DATE_STR, regex = Regexs.yyyyMMdd, length = 8)
    	private String nonstopBusDate; // 直达班车发车日期
    
    	//getter and setter methods
    	
    }
    

    自己定义注解 FieldNote.java:

    package com.validate.intf;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import com.validate.holder.FvEnum;
    
    @Target({ ElementType.FIELD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface FieldNote {
    	/**
    	 * 名称
    	 * @return
    	 */
    	String name();
    	/**
    	 * 类型
    	 * @return
    	 */
    	FvEnum type();
    	/**
    	 * 能否够为空
    	 * @return
    	 */
    	boolean isNullAble() default true;
    	/**
    	 * 格式,能够是正则,默觉得空字符串
    	 * @return
    	 */
    	String regex() default "";
    	/**
    	 * 长度(String)
    	 * @return
    	 */
    	int length() default -1;
    }
    

    FvEnum.java(field validator enum) 字段校验方法集合。定义了不同类型field的校验方式:

    package com.validate.holder;
    
    import com.validate.ResultVO;
    import com.validate.intf.FieldNote;
    import com.validate.intf.IValidator;
    
    /**
     * @author 15041965 2015-06-09
     *
     */
    public enum FvEnum {
    	/*
    	 * CHAR, BOOL, INT, LONG, DOUBLE, FLOAT,
    	 */
    	DATE_STR(FieldValidatorHolder.DATE_STR), 
    	STRING(FieldValidatorHolder.STRING);
    
    	@SuppressWarnings("rawtypes")
    	private FvEnum(IValidator validator) {
    		this.validator = validator;
    	}
    
    	@SuppressWarnings("rawtypes")
    	private IValidator validator;
    
    	@SuppressWarnings("unchecked")
    	public <T> ResultVO validate(FieldNote fn,String fieldName, T fieldVal, ResultVO resultVO) {
    		return validator.validate(fn,fieldName,fieldVal, resultVO);
    	}
    
    }
    
    IValidator.java:

    package com.validate.intf;
    
    import com.validate.ResultVO;
    
    /**
     * @author 15041965 2015-06-09
     *
     */
    public interface IValidator<T> {
    	ResultVO validate(FieldNote fv,String fieldName,T fieldVal,ResultVO resultVO);
    }
    

    ResultVO.java 校验结果载体:

    package com.validate;
    
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 方法运行 结果 封装对象
     * 
     */
    public class ResultVO {
    
    	private boolean success = true;// 返回标识
    	private Set<String> errorCodes; // 错误消息代码
    
    	public ResultVO() {
    	}
    
    	public boolean isSuccess() {
    		return success;
    	}
    
    	public void setSuccess(boolean success) {
    		this.success = success;
    	}
    
    	public Set<String> getErrorCodes() {
    		if (null == errorCodes) {
    			errorCodes = new HashSet<String>();
    		}
    		return errorCodes;
    	}
    
    	public void addError(String errorCode) {
    		if (errorCode == null || "".equals(errorCode.trim())) {
    			return;
    		}
    		if (!getErrorCodes().contains(errorCode)) {
    			getErrorCodes().add(errorCode);
    		}
    		success = false;
    	}
    	
    	public void addErrors(Collection<String> errors) {
    		getErrorCodes().addAll(errors);
    		success = false;
    	}
    
    	public String getErrorStr() {
    		String str = errorCodes.toString();
    		return str.substring(1, str.length() - 1);
    	}
    }
    

    FieldValidatorHolder.java 和 FvEnum.java相应。是FvEnum.java里面各校验方式的详细实现持有类:

    package com.validate.holder;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.springframework.util.StringUtils;
    
    import com.validate.ResultVO;
    import com.validate.intf.FieldNote;
    import com.validate.intf.IValidator;
    
    /**
     * @author 15041965 2015-06-09
     *
     */
    public class FieldValidatorHolder {
    	public static final IValidator<String> STRING = newStringVal();
    
    	public static final IValidator<String> DATE_STR = new IValidator<String>() {
    		public ResultVO validate(FieldNote fv, String fieldName,
    				String fieldVal, ResultVO resultVO) {
    			resultVO = checkNullAndLen(fv, fieldName, fieldVal, resultVO);
    			if (!resultVO.isSuccess()) {
    				return resultVO;
    			}
    			if (!StringUtils.isEmpty(fieldVal)
    					&& !StringUtils.isEmpty(fv.regex())) {
    				if (!validateDate(fieldVal, fv.regex())) {
    					resultVO.addError(fv.name() + "[" + fieldName + "]值["
    							+ fieldVal + "]日期不合法或不能匹配格式 " + fv.regex());
    					return resultVO;
    				}
    			}
    			return resultVO;
    		}
    	};
    
    	private static IValidator<String> newStringVal() {
    		IValidator<String> validator = new IValidator<String>() {
    			public ResultVO validate(FieldNote fv, String fieldName,
    					String fieldVal, ResultVO resultVO) {
    				resultVO = checkNullAndLen(fv, fieldName, fieldVal, resultVO);
    				if (!resultVO.isSuccess()) {
    					return resultVO;
    				}
    				if (!StringUtils.isEmpty(fieldVal)
    						&& !StringUtils.isEmpty(fv.regex())
    						&& !fieldVal.matches(fv.regex())) {
    					resultVO.addError(fv.name() + "[" + fieldName + "]值["
    							+ fieldVal + "]不能匹配格式 " + fv.regex() + " ");
    					return resultVO;
    				}
    				return resultVO;
    			}
    		};
    		return validator;
    	}
    
    	protected static ResultVO checkNullAndLen(FieldNote fv, String fieldName,
    			String fieldVal, ResultVO resultVO) {
    		if (StringUtils.isEmpty(fieldVal)) {
    			if (!fv.isNullAble()) {
    				resultVO.addError(fv.name() + "[" + fieldName + "]为空!");
    			}
    			return resultVO;
    		}
    		if (fv.length() > 0 && (fieldVal.length() > fv.length())) {
    			resultVO.addError(fv.name() + "[" + fieldName + "]长度("
    					+ fieldVal.length() + ")超过限制(" + fv.length() + ")");
    			return resultVO;
    		}
    		return resultVO;
    	}
    
    	public static boolean validateDate(String dateStr, String pattern) {
    		try {
    			SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
    			Date date = dateFormat.parse(dateStr);
    			String pStr = dateFormat.format(date);
    			return pStr.equals(dateStr);
    		} catch (ParseException e) {
    			return false;
    		}
    	}
    
    }
    


    測试Main方法:

    	public static void main(String[] args) {
    		OmsTaskHead head = new OmsTaskHead();
    		head.setRouting("555555");
    		head.setAreaDeliBusSysId("busiId1234");
    		head.setNostopBusSysId("not010101");
    		head.setSpeBusSysId("busId0101");
    		head.setTransBusSysId("trans0909");
    		head.setAreaDeliBusDate("20150640");
    		head.setNonstopBusDate("20150610");
    		head.setStoreCode("20150610");
    		head.setTransBusDate("20150610");
    		
    		ResultVO resultVO = ObjFieldValUtil.validate(head);
    		if(resultVO.isSuccess()){
    			System.out.println("校验成功!");
    		} else {
    			System.out.println(resultVO.getErrorStr());
    		}
    	}

    执行结果:


    这样是不是非常方便,qq:1773240270 欢迎交流




    
  • 相关阅读:
    元组-琢磨已久的购物车程序
    学习使我充实自己-列表具备的功能
    很高兴今天用PYTHON3写了三级菜单程序!
    python内建模块shlex将普通字符串编码成符合linux shell的字符串
    HTTPS能登陆,HTTP不行
    linux shell判断输入的是哪个不可见字符,例如^X(Ctrl-X)
    TI CC3200做ETSI EN 300 328 认证
    使用systemd-resolved的系统中DNS来源优先级
    systmed-timesyncd中NTP服务器地址来源优先级
    markdown的简单应用实例
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7259086.html
Copyright © 2020-2023  润新知