spring自定义ArgumentResolver

阅读更多
参考:http://www.cnblogs.com/HD/p/4118829.html  介绍了几种传参数方式。

对于传多个对象或者List<对象>,spring mvc并没有提供默认实现。不过我们可以自定义。

参考:http://stackoverflow.com/questions/30715579/custom-spring-annotation-for-request-parameters/30716094

例子:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Documented
public @interface WebParameter {

	String value() default "";
	
	boolean required() default true;
	
	String defaultValue() default ValueConstants.DEFAULT_NONE;
}



/**
 * This class is suitable for when you pass more than one object or List<object>,or both of them.
* This class does not support Array, even the property.
* @author gche * */ public class WebParameterAnnotationArgumentResolver implements HandlerMethodArgumentResolver{ private Map> fieldMap = new WeakHashMap>(100); @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(WebParameter.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { WebParameter anno = parameter.getParameterAnnotation(WebParameter.class); String name = anno.value(); Object arg = null; Class parameterType = parameter.getParameterType(); Map parameterMap = webRequest.getParameterMap(); if(parameterMap == null || parameterMap.isEmpty()){ String defaultValue = anno.defaultValue(); if(StringUtils.isBlank(defaultValue) && anno.required()){ throw new Exception("no value is given for " + name + ", and it is required"); } return this.convert(defaultValue, parameterType); } //student[0].name, student[1].name "student" List if(List.class.isAssignableFrom(parameterType)){//List(Object) int size = this.getListSize(parameterMap, name); if(size <= 0){ return Collections.emptyList(); } arg = new ArrayList(size); ParameterizedType type = (ParameterizedType)parameter.getGenericParameterType(); for(int i=0;i parameterMap, String name){ int size = -1; Iterator> it = parameterMap.entrySet().iterator(); while(it.hasNext()){ Map.Entry entry = it.next(); String key = entry.getKey(); int index = key.indexOf(name + "["); int index2 = key.indexOf("]"); if(index != -1){ size = Math.max(size, Integer.valueOf(key.substring(index+(name+"[").length(), index2))); } } return size + 1; } private void setValue(Object instance, Map parameterMap, String name) throws Exception{ List fieldList = this.getFields(instance.getClass()); for(Field field : fieldList){ PropertyDescriptor property = BeanUtils.getPropertyDescriptor(instance.getClass(), field.getName()); Class propertyType = property.getPropertyType(); if(ClassUtils.isPrimitiveOrWrapper(propertyType)|| propertyType == String.class || propertyType == Date.class){ String[] value = parameterMap.get(name + "." + property.getName()); if(value == null || (value.length == 1 && StringUtils.isBlank(value[0]))){ continue; } Method writeMethod = property.getWriteMethod(); writeMethod.invoke(instance, this.convert(value[0], propertyType)); }else if(propertyType.isArray()){ throw new Exception("array is not supported, please use List instead"); }else if(List.class.isAssignableFrom(propertyType)){ //student.books int size = this.getListSize(parameterMap, name + "." + field.getName()); List nestedList = size <=0 ? Collections.emptyList() : new ArrayList(size); Method writeMethod = property.getWriteMethod(); writeMethod.invoke(instance, nestedList); for(int i=0;i 10){ return DateUtils.parseDate(data, "yyyy"+delimiter+"MM"+delimiter+"dd HH:mm"); }else{ return DateUtils.parseDate(data, "yyyy"+delimiter+"MM"+delimiter+"dd"); } } throw new TypeMismatchException(data, expectedType); // return data; } private List getFields(Class parameterType) { if(this.fieldMap.get(parameterType) != null){ return this.fieldMap.get(parameterType); } Field[] fields = parameterType.getDeclaredFields(); this.fieldMap.put(parameterType, Arrays.asList(fields)); return this.fieldMap.get(parameterType); } }



		
			
		
	


@RequestMapping("xxx")
public void save(@WebParameter("activity")Activity activity, @WebParameter("strategy")List strategy, HttpServletResponse response)

Activity和ActivityStrategy都是POJO。

在前端数据格式是这样:
{"activity.id":111,"activity.name":'test',"strategy[0].id":222,"strategy[0].name":"aaaa","strategy[1].id":333,"strategy[1].name":"bbbb"}

目前只实现了POJO和List,支持嵌套。
由于我喜欢用List,因此没有实现数组。
PS:spring版本是4.2.4,4.1.4是不行的。

你可能感兴趣的:(spring自定义ArgumentResolver)