6.映射请求-映射动态资源-参数处理
在读取映射关系时,调用的方法对象会存入MappingInfo,我们根据请求获得info对象,从而获得要调用的method对象,再根据method对象获得参数列表:①参数个数 ②参数类型
但无法获取参数名,而框架需要通过名字key获得对应参数。
可以由框架提供一个@RequestParam注解,作用在controller方法的参数上,指定其对应请求参数名字
例如:
public void t2(@RequestParam(“username”)String username,@RequestParam(“password”)String password){}
有时业务程序要让框架将传递的多个参数组成对象(public void t3(Car car){})
不需要使用@RequestParam注解
告诉框架,将传递的参数组成Car对象
框架会根据Car的属性名找到与之匹配的参数,组装成对象
还有一种特殊情况,不需要请求传递参数,但需要request、response、session的对象
框架也会以方法传参的形式将上述对象传给controller方法
/*按照请求映射关系要调用的那个目标方法,获得目标方法的参数列表根据参数列表获得所需要的参数,并将参数组装到Object[]中*/private Object[] handleParam(Map<String, Object> paramMap, MappingInfo info, HttpServletRequest req, HttpServletResponse resp) throws IllegalAccessException, InstantiationException, InvocationTargetException {Method method = info.getMethod();Parameter[] parameters = method.getParameters();Object[] paramValues = new Object[parameters.length];int i = 0;for (Parameter parameter : parameters) {RequestParam rp = parameter.getAnnotation(RequestParam.class);Class paramType = parameter.getType();if (rp != null) {//注解的value就是key,可以用来获取实参String key = rp.value();Object value = paramMap.get(key);if (value == null) {//当前所需参数为空i++;continue;}//如果参数值存在,起初只有2种表现形成 String[] , MulitpartFile[]//将此次需要的参数value,转换成方法中定义的需要参数类型paramValues[i++] = castType(value, paramType);} else {//没有@RequestParam注解,可能是request、response、session、domain(组装参数)if (paramType == HttpServletRequest.class) {paramValues[i++] = req;} else if (paramType == HttpServletResponse.class) {paramValues[i++] = resp;} else if (paramType == HttpSession.class) {paramValues[i++] = req.getSession();} else {Object paramObject = paramType.newInstance();Method[] methods = paramType.getMethods();//通过反射获得对象中的属性名,根据属性名找到与之同名的参数,为属性赋值//为了更好的符合Java封装的特性,不建议通过反射找属性,建议找set方法for (Method m : methods) {String mname=m.getName();if(mname.startsWith("set")){String key=mname.substring(3);key=key.substring(0,1).toLowerCase()+key.substring(1);Object value=paramMap.get(key);if(value==null){continue;}Class domainParamType=m.getParameterTypes()[0];Object obj= castType(value,domainParamType);m.invoke(paramObject,obj);}}//循环结束找到了所有set方法,赋值结束,将对象保存paramValues[i++]=paramObject;}}}return paramValues;}
/*将原始类型的参数数据,转换成目标方法所需要的类型原始类型:String[],MultipartFile[]目标类型:int、long、double、String、Integer、MultipartFile以及这些类型的数组形式*/private Object castType(Object value, Class paramType) {if (paramType == String.class) {String str = ((String[]) value)[0];return str;}if (paramType == int.class || paramType == Integer.class) {String str = ((String[]) value)[0];int num = Integer.parseInt(str);return num;}if (paramType == long.class || paramType == Long.class) {String str = ((String[]) value)[0];long num = Long.parseLong(str);return num;}if (paramType == double.class || paramType == Double.class) {String str = ((String[]) value)[0];double num = Double.parseDouble(str);return num;}if (paramType == String[].class) {return value;}if (paramType == int[].class) {String[] str = (String[]) value;int[] n = new int[str.length];for (int j = 0; j < str.length; j++) {n[j] = Integer.parseInt(str[j]);}return n;}if (paramType == Integer[].class) {String[] str = (String[]) value;Integer[] nums = new Integer[str.length];for (int j = 0; j < str.length; j++) {nums[j] = Integer.valueOf(str[j]);}return nums;}if (paramType == MultipartFile.class) {return ((MultipartFile[]) value)[0];}if (paramType == MultipartFile[].class) {return value;}return null;}
package web.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.PARAMETER)@Retention(RetentionPolicy.RUNTIME)public @interface RequestParam {public String value();}

