1. 映射请求-映射动态资源-获取参数
      按照我们之前所学
      浏览器传递的参数主要包括两类
      1. 普通的请求传参
      只传字符串
      使用req.getParameter()
      2. 文件上传时的传参
      传递2种参数: 普通参数(字符串),文件参数
      fileupload文件上传组件接收参数
      浏览器传递的参数有可能存在同名的情况
      url?hobby=zq&hobby=lq&hobby=pq
      req.getParameter(“hobby”) —> zq 只能获得一个
      req.getParameterValues(“hobby”) -> [zq,lq,pq] 获得所有(数组)
      文件上传时,也可能传递多个同名的参数

      1. /*
      2. * 接收请求传递从参数
      3. * 将参数处理后装入map
      4. * map.key就是请求传递参数key <input type="uname" /> map.key=uname
      5. * map.value 可能是一个 String[] 也可能是一个 文件[] -> Object表示
      6. */
      7. private Map<String,Object> receiveParams(HttpServletRequest req){
      8. Map<String,Object> paramMap = new HashMap<>();
      9. //参数有2种可能 (普通请求,文件上传请求)
      10. //如果普通请求按照文件上传方式处理,会抛出异常
      11. //如果文件上传请求按照普通请求处理会得不到参数
      12. try{
      13. //假设是文件上传方式传递参数
      14. DiskFileItemFactory factory = new DiskFileItemFactory();
      15. ServletFileUpload upload = new ServletFileUpload(factory) ;
      16. //该行会判断是否是文件上传请求,是否配置了enctype="multipart/form-data",如果不是会抛出异常
      17. List<FileItem> fis = upload.parseRequest(req) ;
      18. //确实是一个文件上传的请求,同时因为上一行代码,已经将请求的参数都组成了FileItem对象,装入了List集合
      19. for(FileItem fi : fis){
      20. //拿到了一个参数
      21. if(fi.isFormField()){//一个判断方法
      22. // 是一个普通参数,String
      23. String key = fi.getFieldName() ;// <input name="uname" />
      24. String value = fi.getString("utf-8") ;
      25. String[] values = (String[]) paramMap.get(key);
      26. if(values == null){
      27. //还没有存储过当前这个名字的参数
      28. values = new String[]{value} ;
      29. paramMap.put(key,values) ;
      30. }else{
      31. //当前名字的参数之前存储过,将当前的数据装入数组,数组扩容+1
      32. // 工具方法
      33. values = Arrays.copyOf(values,values.length+1) ;
      34. values[ values.length-1 ] = value ;
      35. paramMap.put(key,values) ;
      36. }
      37. paramMap.put(key,value) ;
      38. }else{
      39. // 是一个文件参数
      40. String key = fi.getFieldName() ; // <input type="file" name="excel" />
      41. String fileName = fi.getName() ; //文件名 1.jpg
      42. long size = fi.getSize() ;//获得文件大小
      43. String contentType = fi.getContentType() ; //文件的类型
      44. InputStream is = fi.getInputStream() ;//文件内容
      45. MulitpartFile file = new MulitpartFile(key,fileName,size,contentType,is);
      46. MulitpartFile[] files = (MulitpartFile[]) paramMap.get(key);
      47. if(files == null){
      48. //当前名字的文件参数之前没有
      49. files = new MulitpartFile[]{file} ;
      50. paramMap.put(key,files);
      51. }else{
      52. //之前存储过这个名字的文件参数
      53. files = Arrays.copyOf(files,files.length+1);
      54. files[ files.length-1 ] = file ;
      55. paramMap.put(key,files) ;
      56. }
      57. }
      58. }
      59. }catch(FileUploadException e){
      60. //出现异常表示不是文件上传方式,再按照普通方式处理
      61. // 得到所有的参数信息
      62. Enumeration<String> names = req.getParameterNames();
      63. while(names.hasMoreElements()){
      64. String name = names.nextElement() ; // name="uname"
      65. String[] values = req.getParameterValues(name);
      66. paramMap.put(name,values) ;
      67. }
      68. } catch (UnsupportedEncodingException e) {
      69. e.printStackTrace();
      70. } catch (IOException e) {
      71. e.printStackTrace();
      72. }
      73. return paramMap ;
      74. }
      75. private String multipartEncoding ;
      76. //读取<multipart-encoding>标签
      77. private void parseMultipartEncodingElement(Document document){
      78. Element mulipartEncodingElement = (Element) document.selectSingleNode("mvc/multipart-encoding");
      79. if(mulipartEncodingElement == null)//做一个判断,不一定写这个标签
      80. return ;
      81. multipartEncoding = mulipartEncodingElement.getText() ;
      82. }
    1. <?xml version="1.0" ?>
    2. <mvc>
    3. <!--
    4. 浏览器发送的/test1请求,由TestController类的t1方法处理
    5. -->
    6. <mapping path="/test1" class="com.controller.TestController" method="t1"></mapping>
    7. <mapping path="/test11" class="com.controller.TestController" method="t1">
    8. <type>int</type>
    9. <type>java.lang.String</type>
    10. </mapping>
    11. <-- mvc.xml 新增 -->
    12. <!-- 文件上传时普通参数的中文编码处理 -->
    13. <-- 这个标签不一定写 -->
    14. <multipart-encoding>utf-8</multipart-encoding>
    15. </mvc>
    1. 映射请求-映射动态资源-参数处理
      框架获得参数后
      需要按照请求映射关系,调用controller方法,同时为其传递参数
      反之,在controller的方法,如果需要用哪些请求的参数
      以前需要使用request方法获得
      现在只需要在controller方法中定义方法参数列表
      告诉看框架,需要哪些参数
      原来需要 uname和upass
      req.getParameter(“uname”);
      req.getParameter(“upass”);
      现在
      public void t2(String uname , String upass){}
      为什么写了t2方法,框架可以为其传递参数了
      首先在读取映射关系时,调用的方法对象会存入MappingInfo
      我们就可以根据请求获得info对象,从而获得要调用的method对象
      获得method对象后,可以通过反射获得参数列表
      参数的个数
      参数类型
      不能获得参数的名字,而框架需要通过名字key获得对应参数
      由框架提供一个@RequestParam,作用在controller方法的参数上,指定其对应请求参数的名字
      通过注解来告诉框架xx名字的参数
      public void t2(@RequestParam(“uname”)String a , @RequestParam(“upass”)String b){}
      告诉框架,需要获得uname和upass两个参数
      注意: 有时,业务程序要让框架,将传递的多个参数组成对象
      public void t3(Car car){}
      //在请求中应用反射
      不需要使用@RequestParam注解
      告诉框架,将传递的参数组成Car对象
      看框架会根据Car的属性名找到与之匹配的参数,组装成对象。
      有注解是一对一,没有是一对多 ```java //Car.java package com.domain;

    public class Car { private Integer cno ; private String cname ; private String color ; private Integer price ;

    1. public Integer getCno() {
    2. return cno;
    3. }
    4. public void setCno(Integer cno) {
    5. this.cno = cno;
    6. }
    7. public String getCname() {
    8. return cname;
    9. }
    10. public void setCname(String cname) {
    11. this.cname = cname;
    12. }
    13. public String getColor() {
    14. return color;
    15. }
    16. public void setColor(String color) {
    17. this.color = color;
    18. }
    19. public Integer getPrice() {
    20. return price;
    21. }
    22. public void setPrice(Integer price) {
    23. this.price = price;
    24. }
    25. public Car(Integer cno, String cname, String color, Integer price) {
    26. this.cno = cno;
    27. this.cname = cname;
    28. this.color = color;
    29. this.price = price;
    30. }
    31. public Car() {
    32. }
    33. @Override
    34. public String toString() {
    35. return "Car{" +
    36. "cno=" + cno +
    37. ", cname='" + cname + '\'' +
    38. ", color='" + color + '\'' +
    39. ", price=" + price +
    40. '}';
    41. }

    }

    1. 注意:<br />还有一种特殊情况,不需要请求传递参数,但需要requestresponsesession的对象<br />框架也会以方法传参的形式将上述对象传给controller方法
    2. ```java
    3. private void handleDynamicResource(MappingInfo info,HttpServletRequest req,HttpServletResponse resp) throws InvocationTargetException, IllegalAccessException {
    4. //获得参数
    5. Map<String,Object> paramMap = receiveParams(req);
    6. //处理参数
    7. //调用mappinginfo中的对象的方法,传递参数
    8. }
    9. /*
    10. 按照请求映射关系要调用的那个目标方法
    11. 获得目标方法的参数列表
    12. 根据参数列表获得所需要的参数
    13. 并将参数组装Object[]中
    14. */
    15. private Object[] handleParam(Map<String,Object> paramMap,MappingInfo info,HttpServletRequest req , HttpServletResponse resp){
    16. Method method = info.getMethod() ;
    17. Parameter[] parameters = method.getParameters() ;
    18. //创建一个与方法参数列表同长度的数组装载参数数据(实参)
    19. Object[] paramValues = new Object[ parameters.length ] ;
    20. int i = 0 ;
    21. for(Parameter parameter : parameters){
    22. RequestParam rp = parameter.getAnnotation(RequestParam.class);
    23. if(rp != null){
    24. //证明有这个注解 @RequestParam("cname") String cname
    25. //表示需要请求传递的一个叫cname名字的参数
    26. //请求传递的参数之前已经处理过了
    27. //处理后将请求传递的参数存入了paramMap集合中,key=cname,value=[]
    28. String key = rp.value() ;// cname
    29. Object value = paramMap.get(key) ;
    30. Class paramType = parameter.getType() ;
    31. if(paramType == String.class){
    32. String str = ((String[])value)[0] ;
    33. paramValues[i++] = str ;
    34. }
    35. if(paramType == int.class || paramType==Integer.class){
    36. String str = ((String[])value)[0] ;
    37. int num = Integer.parseInt(str) ;
    38. paramValues[i++] = num ;
    39. }
    40. if(paramType == long.class || paramType==Long.class){
    41. String str = ((String[])value)[0] ;
    42. long num = Long.parseLong(str) ;
    43. paramValues[i++] = num ;
    44. }
    45. if(paramType == double.class || paramType==Double.class){
    46. String str = ((String[])value)[0] ;
    47. double num = Double.parseDouble(str) ;
    48. paramValues[i++] = num ;
    49. }
    50. if(paramType == String[].class){
    51. paramValues[i++] = value ;
    52. }
    53. //url?cname=1&cname=2&cname3 =》框架会存储成数组[1,2,3]
    54. if(paramType == int[].class){
    55. String[] ss = (String[])value ;
    56. int[] nums = new int[ss.length];
    57. for(int j=0;j< ss.length;j++){
    58. nums[j] = Integer.parseInt(ss[i]);
    59. }
    60. }
    61. if(paramType == Integer[].class){
    62. String[] ss = (String[])value ;
    63. Integer[] nums = new Integer[ss.length];
    64. for(int j=0;j< ss.length;j++){
    65. nums[j] = Integer.valueOf(ss[i]);
    66. }
    67. }
    68. }
    69. }
    70. return paramValues ;
    71. }