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方法

    1. /*
    2. 按照请求映射关系要调用的那个目标方法,获得目标方法的参数列表
    3. 根据参数列表获得所需要的参数,并将参数组装到Object[]中
    4. */
    5. private Object[] handleParam(Map<String, Object> paramMap, MappingInfo info, HttpServletRequest req, HttpServletResponse resp) throws IllegalAccessException, InstantiationException, InvocationTargetException {
    6. Method method = info.getMethod();
    7. Parameter[] parameters = method.getParameters();
    8. Object[] paramValues = new Object[parameters.length];
    9. int i = 0;
    10. for (Parameter parameter : parameters) {
    11. RequestParam rp = parameter.getAnnotation(RequestParam.class);
    12. Class paramType = parameter.getType();
    13. if (rp != null) {
    14. //注解的value就是key,可以用来获取实参
    15. String key = rp.value();
    16. Object value = paramMap.get(key);
    17. if (value == null) {
    18. //当前所需参数为空
    19. i++;
    20. continue;
    21. }
    22. //如果参数值存在,起初只有2种表现形成 String[] , MulitpartFile[]
    23. //将此次需要的参数value,转换成方法中定义的需要参数类型
    24. paramValues[i++] = castType(value, paramType);
    25. } else {
    26. //没有@RequestParam注解,可能是request、response、session、domain(组装参数)
    27. if (paramType == HttpServletRequest.class) {
    28. paramValues[i++] = req;
    29. } else if (paramType == HttpServletResponse.class) {
    30. paramValues[i++] = resp;
    31. } else if (paramType == HttpSession.class) {
    32. paramValues[i++] = req.getSession();
    33. } else {
    34. Object paramObject = paramType.newInstance();
    35. Method[] methods = paramType.getMethods();
    36. //通过反射获得对象中的属性名,根据属性名找到与之同名的参数,为属性赋值
    37. //为了更好的符合Java封装的特性,不建议通过反射找属性,建议找set方法
    38. for (Method m : methods) {
    39. String mname=m.getName();
    40. if(mname.startsWith("set")){
    41. String key=mname.substring(3);
    42. key=key.substring(0,1).toLowerCase()+key.substring(1);
    43. Object value=paramMap.get(key);
    44. if(value==null){
    45. continue;
    46. }
    47. Class domainParamType=m.getParameterTypes()[0];
    48. Object obj= castType(value,domainParamType);
    49. m.invoke(paramObject,obj);
    50. }
    51. }
    52. //循环结束找到了所有set方法,赋值结束,将对象保存
    53. paramValues[i++]=paramObject;
    54. }
    55. }
    56. }
    57. return paramValues;
    58. }
    1. /*
    2. 将原始类型的参数数据,转换成目标方法所需要的类型
    3. 原始类型:String[],MultipartFile[]
    4. 目标类型:int、long、double、String、Integer、MultipartFile以及这些类型的数组形式
    5. */
    6. private Object castType(Object value, Class paramType) {
    7. if (paramType == String.class) {
    8. String str = ((String[]) value)[0];
    9. return str;
    10. }
    11. if (paramType == int.class || paramType == Integer.class) {
    12. String str = ((String[]) value)[0];
    13. int num = Integer.parseInt(str);
    14. return num;
    15. }
    16. if (paramType == long.class || paramType == Long.class) {
    17. String str = ((String[]) value)[0];
    18. long num = Long.parseLong(str);
    19. return num;
    20. }
    21. if (paramType == double.class || paramType == Double.class) {
    22. String str = ((String[]) value)[0];
    23. double num = Double.parseDouble(str);
    24. return num;
    25. }
    26. if (paramType == String[].class) {
    27. return value;
    28. }
    29. if (paramType == int[].class) {
    30. String[] str = (String[]) value;
    31. int[] n = new int[str.length];
    32. for (int j = 0; j < str.length; j++) {
    33. n[j] = Integer.parseInt(str[j]);
    34. }
    35. return n;
    36. }
    37. if (paramType == Integer[].class) {
    38. String[] str = (String[]) value;
    39. Integer[] nums = new Integer[str.length];
    40. for (int j = 0; j < str.length; j++) {
    41. nums[j] = Integer.valueOf(str[j]);
    42. }
    43. return nums;
    44. }
    45. if (paramType == MultipartFile.class) {
    46. return ((MultipartFile[]) value)[0];
    47. }
    48. if (paramType == MultipartFile[].class) {
    49. return value;
    50. }
    51. return null;
    52. }
    1. package web.annotation;
    2. import java.lang.annotation.ElementType;
    3. import java.lang.annotation.Retention;
    4. import java.lang.annotation.RetentionPolicy;
    5. import java.lang.annotation.Target;
    6. @Target(ElementType.PARAMETER)
    7. @Retention(RetentionPolicy.RUNTIME)
    8. public @interface RequestParam {
    9. public String value();
    10. }

    image.png