码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-06-10 19:31:26      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:属性校验   注解   自动校验   

最近做一个接口,接受外系统的报文,通过XStream转换成java对象以后,需要对其中的字段做格式校验。要求如下


技术分享

传统的方式是硬编码校验,但是对于field很多的情况,代码量暴增。容易出错。

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 欢迎交流




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

标签:属性校验   注解   自动校验   

原文地址:http://blog.csdn.net/lxy2520/article/details/46443551

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!