参考: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,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 Object nestedArg = BeanUtils.instantiateClass((Class)type.getActualTypeArguments()[0]); ((List)arg).add(nestedArg); this.setValue(nestedArg, parameterMap, name + "[" + i +"]"); } }else if(parameterType.isArray()){//Object[] throw new Exception("array is not supported, please use List instead"); }else{ arg = BeanUtils.instantiateClass(parameterType); this.setValue(arg, parameterMap, name); } return arg; } private int getListSize(Map 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 Object nestedInstance = BeanUtils.instantiateClass((Class)((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]); nestedList.add(nestedInstance); this.setValue(nestedInstance, parameterMap, name + "." + field.getName() + "[" + i + "]"); } }else{ //nested object Object nestedInstance = BeanUtils.instantiateClass(propertyType); Method writeMethod = property.getWriteMethod(); writeMethod.invoke(instance, nestedInstance); this.setValue(nestedInstance, parameterMap, name + "." + field.getName()); } } } private Object convert(String data, Class expectedType) throws ParseException{ data = data.trim(); if(expectedType == byte.class || expectedType == Byte.class){ return Byte.valueOf(data); } if(expectedType == char.class || expectedType == Character.class){ return data.charAt(0); } if(expectedType == int.class || expectedType == Integer.class){ return Integer.valueOf(data); } if(expectedType == float.class || expectedType == Float.class){ return Float.valueOf(data); } if(expectedType == double.class || expectedType == Double.class){ return Double.valueOf(data); } if(expectedType == long.class || expectedType == Long.class){ return Long.valueOf(data); } if(expectedType == short.class || expectedType == Short.class){ return Short.valueOf(data); } if(expectedType == boolean.class || expectedType == Boolean.class){ return Boolean.valueOf(data); } if(expectedType == Date.class){ //2016-05-09 10位 //2016-05-09 22:23 16位 char delimiter = data.trim().charAt(4); if(data.length() > 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是不行的。