`

SpringSide搜索功能的扩展

阅读更多

 

    SpringSide 很好很强大,整合了各式主流的、实用的、好玩的开源项目,非常值的学习。springSide3中有一个功能很实用、很方便、就是页面条件过滤(搜索)功能。由于springSide该功能目前只支持String类型的搜索,但在项目中仅仅只有String类型是远远不够的,所以自己就将其功能做了一些扩展。
     
   在扩展中需考滤以下几个问题:
     1、需将PropertyFilter类中的枚举MatchType扩展更多的属性比较类型。
     2、在构建Criterion对象时,由于由于PropertyFilte中的过滤的属性值都是通过request.getParameter(name)方式所获取,所以需将String类型的值转换成与过滤属性类型一致。
     3、要将String类型进行转换,首先需获得过滤属性的类型,属性单一时很好处理,如果为链方式时(如A.B.C.id),怎样处理?怎样来获取最后一个属性类型(id的类型),又假如属性是继承父类而来的又将怎样处理。

 

   围绕以上3点,我主要做了以下扩展:
    
     一、扩展PropertyFilter类中的枚举MatchType

public enum MatchType {
		EQ, LIKE, LT, LE, GT, GE;
	}

 

        添加了小于、小于等于、大于、大于等于.

     二、在ReflectionUtils类中添加获取过滤属性的类型方法

public static Class<?> getFieldType(Class<?> entityClass, String propertyName) {
		Assert.hasText(propertyName, "propertyName不能为空");
		Class<?> propertyType = null;
		try {
			if (StringUtils.contains(propertyName, ".")) {
				for (String str : propertyName.split("\\.")) {
					Field declaredField = getDeclaredField(entityClass, str);
					entityClass = declaredField.getType();
				}
				propertyType = entityClass;
			} else {
				propertyType = getDeclaredField(entityClass, propertyName).getType();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		return propertyType;

	}
 

   
     三、在HibernateWebUtils类中添加值类型转换方法

public static Object convertValue(Object value, Class<?> toType) {
		Assert.notNull(value, "value不能为空");
		Object result = null;
		try {
			if (toType == Date.class) {
				result = DateUtils.parseDate((String) value, new String[] { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss" });
			} else {
				result = OgnlOps.convertValue(value, toType);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return result;
	} 
	 
	public static Object convertValue(Object value, Class<?> entityClass, String propertyName) {
		return convertValue(value, ReflectionUtils.getFieldType(entityClass, propertyName));
	}
 

     四、重构HibernateDao类中的buildPropertyFilterCriterion方法

 

protected Criterion buildPropertyFilterCriterion(final String propertyName, final Object value,
			final MatchType matchType) {
		Assert.hasText(propertyName, "propertyName不能为空");
		Criterion criterion = null;
		Object pValue = null;
		try { 
			pValue = HibernateWebUtils.convertValue(value, entityClass, propertyName); 
			if (MatchType.EQ.equals(matchType)) {
				criterion = Restrictions.eq(propertyName, pValue);
			}
			if (MatchType.LIKE.equals(matchType)) {
				criterion = Restrictions.like(propertyName, (String) value, MatchMode.ANYWHERE);
			}
			if (MatchType.LT.equals(matchType)) {
				criterion = Restrictions.lt(propertyName, pValue);
			}
			if (MatchType.LE.equals(matchType)) {
				criterion = Restrictions.le(propertyName, pValue);
			}
			if (MatchType.GT.equals(matchType)) {
				criterion = Restrictions.gt(propertyName, pValue);
			}
			if (MatchType.GE.equals(matchType)) {
				criterion = Restrictions.ge(propertyName, pValue);
			} 
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return criterion;
	}

 

 

分享到:
评论
6 楼 flyliying 2009-12-04  
3.2.1已经看到完善了
/**
	 * 属性比较类型.
	 */
	public enum MatchType {
		EQ, LIKE, LT, GT, LE, GE;
	}

	/**
	 * 属性数据类型.
	 */
	public enum PropertyType {
		S(String.class), I(Integer.class), L(Long.class), N(Double.class), D(Date.class), B(Boolean.class);

		private Class<?> clazz;

		PropertyType(Class<?> clazz) {
			this.clazz = clazz;
		}

		public Class<?> getValue() {
			return clazz;
		}
	}

	private String[] propertyNames = null;
	private Class<?> propertyType = null;
	private Object propertyValue = null;
	private MatchType matchType = MatchType.EQ;

	public PropertyFilter() {
	}

	/**
	 * @param filterName 比较属性字符串,含待比较的比较类型、属性值类型及属性列表. 
	 *                   eg. LIKES_NAME_OR_LOGIN_NAME
	 * @param value 待比较的值.
	 */
	public PropertyFilter(final String filterName, final Object value) {

		String matchTypeStr = StringUtils.substringBefore(filterName, "_");
		String matchTypeCode = StringUtils.substring(matchTypeStr, 0, matchTypeStr.length() - 1);
		String propertyTypeCode = StringUtils.substring(matchTypeStr, matchTypeStr.length() - 1, matchTypeStr.length());
		try {
			matchType = Enum.valueOf(MatchType.class, matchTypeCode);
		} catch (RuntimeException e) {
			throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性比较类型.", e);
		}

		try {
			propertyType = Enum.valueOf(PropertyType.class, propertyTypeCode).getValue();
		} catch (RuntimeException e) {
			throw new IllegalArgumentException("filter名称" + filterName + "没有按规则编写,无法得到属性值类型.", e);
		}

		String propertyNameStr = StringUtils.substringAfter(filterName, "_");
		propertyNames = StringUtils.split(propertyNameStr, PropertyFilter.OR_SEPARATOR);

		Assert.isTrue(propertyNames.length > 0, "filter名称" + filterName + "没有按规则编写,无法得到属性名称.");
		//按entity property中的类型将字符串转化为实际类型.
		this.propertyValue = ReflectionUtils.convertValue(value, propertyType);
	}
5 楼 nbaertuo 2009-09-18  
测试是否可以灌水!
4 楼 zhxing 2009-09-18  
感觉既然用了enum ,这么多if 语句不如用swtich 来的自然。。
3 楼 kaki 2009-09-18  
大家多发一些经典代码,让我们好好学习啊。
2 楼 h521999 2009-07-28  
嗯,应该会在3.15版中完善吧.
1 楼 godson_2003 2009-07-28  
白衣应该会完善这个扩展的

相关推荐

Global site tag (gtag.js) - Google Analytics