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();
}