映射请求-映射动态资源-获取参数
按照我们之前所学
浏览器传递的参数主要包括两类
1. 普通的请求传参
只传字符串
使用req.getParameter()
2. 文件上传时的传参
传递2种参数: 普通参数(字符串),文件参数
fileupload文件上传组件接收参数
浏览器传递的参数有可能存在同名的情况
url?hobby=zq&hobby=lq&hobby=pq
req.getParameter(“hobby”) —> zq 只能获得一个
req.getParameterValues(“hobby”) -> [zq,lq,pq] 获得所有(数组)
文件上传时,也可能传递多个同名的参数/** 接收请求传递从参数* 将参数处理后装入map* map.key就是请求传递参数key <input type="uname" /> map.key=uname* map.value 可能是一个 String[] 也可能是一个 文件[] -> Object表示*/private Map<String,Object> receiveParams(HttpServletRequest req){Map<String,Object> paramMap = new HashMap<>();//参数有2种可能 (普通请求,文件上传请求)//如果普通请求按照文件上传方式处理,会抛出异常//如果文件上传请求按照普通请求处理会得不到参数try{//假设是文件上传方式传递参数DiskFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(factory) ;//该行会判断是否是文件上传请求,是否配置了enctype="multipart/form-data",如果不是会抛出异常List<FileItem> fis = upload.parseRequest(req) ;//确实是一个文件上传的请求,同时因为上一行代码,已经将请求的参数都组成了FileItem对象,装入了List集合for(FileItem fi : fis){//拿到了一个参数if(fi.isFormField()){//一个判断方法// 是一个普通参数,StringString key = fi.getFieldName() ;// <input name="uname" />String value = fi.getString("utf-8") ;String[] values = (String[]) paramMap.get(key);if(values == null){//还没有存储过当前这个名字的参数values = new String[]{value} ;paramMap.put(key,values) ;}else{//当前名字的参数之前存储过,将当前的数据装入数组,数组扩容+1// 工具方法values = Arrays.copyOf(values,values.length+1) ;values[ values.length-1 ] = value ;paramMap.put(key,values) ;}paramMap.put(key,value) ;}else{// 是一个文件参数String key = fi.getFieldName() ; // <input type="file" name="excel" />String fileName = fi.getName() ; //文件名 1.jpglong size = fi.getSize() ;//获得文件大小String contentType = fi.getContentType() ; //文件的类型InputStream is = fi.getInputStream() ;//文件内容MulitpartFile file = new MulitpartFile(key,fileName,size,contentType,is);MulitpartFile[] files = (MulitpartFile[]) paramMap.get(key);if(files == null){//当前名字的文件参数之前没有files = new MulitpartFile[]{file} ;paramMap.put(key,files);}else{//之前存储过这个名字的文件参数files = Arrays.copyOf(files,files.length+1);files[ files.length-1 ] = file ;paramMap.put(key,files) ;}}}}catch(FileUploadException e){//出现异常表示不是文件上传方式,再按照普通方式处理// 得到所有的参数信息Enumeration<String> names = req.getParameterNames();while(names.hasMoreElements()){String name = names.nextElement() ; // name="uname"String[] values = req.getParameterValues(name);paramMap.put(name,values) ;}} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return paramMap ;}private String multipartEncoding ;//读取<multipart-encoding>标签private void parseMultipartEncodingElement(Document document){Element mulipartEncodingElement = (Element) document.selectSingleNode("mvc/multipart-encoding");if(mulipartEncodingElement == null)//做一个判断,不一定写这个标签return ;multipartEncoding = mulipartEncodingElement.getText() ;}
<?xml version="1.0" ?><mvc><!--浏览器发送的/test1请求,由TestController类的t1方法处理--><mapping path="/test1" class="com.controller.TestController" method="t1"></mapping><mapping path="/test11" class="com.controller.TestController" method="t1"><type>int</type><type>java.lang.String</type></mapping><-- mvc.xml 新增 --><!-- 文件上传时普通参数的中文编码处理 --><-- 这个标签不一定写 --><multipart-encoding>utf-8</multipart-encoding></mvc>
- 映射请求-映射动态资源-参数处理
框架获得参数后
需要按照请求映射关系,调用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 ;
public Integer getCno() {return cno;}public void setCno(Integer cno) {this.cno = cno;}public String getCname() {return cname;}public void setCname(String cname) {this.cname = cname;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price = price;}public Car(Integer cno, String cname, String color, Integer price) {this.cno = cno;this.cname = cname;this.color = color;this.price = price;}public Car() {}@Overridepublic String toString() {return "Car{" +"cno=" + cno +", cname='" + cname + '\'' +", color='" + color + '\'' +", price=" + price +'}';}
}
注意:<br />还有一种特殊情况,不需要请求传递参数,但需要request,response,session的对象<br />框架也会以方法传参的形式将上述对象传给controller方法```javaprivate void handleDynamicResource(MappingInfo info,HttpServletRequest req,HttpServletResponse resp) throws InvocationTargetException, IllegalAccessException {//获得参数Map<String,Object> paramMap = receiveParams(req);//处理参数//调用mappinginfo中的对象的方法,传递参数}/*按照请求映射关系要调用的那个目标方法获得目标方法的参数列表根据参数列表获得所需要的参数并将参数组装Object[]中*/private Object[] handleParam(Map<String,Object> paramMap,MappingInfo info,HttpServletRequest req , HttpServletResponse resp){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);if(rp != null){//证明有这个注解 @RequestParam("cname") String cname//表示需要请求传递的一个叫cname名字的参数//请求传递的参数之前已经处理过了//处理后将请求传递的参数存入了paramMap集合中,key=cname,value=[]String key = rp.value() ;// cnameObject value = paramMap.get(key) ;Class paramType = parameter.getType() ;if(paramType == String.class){String str = ((String[])value)[0] ;paramValues[i++] = str ;}if(paramType == int.class || paramType==Integer.class){String str = ((String[])value)[0] ;int num = Integer.parseInt(str) ;paramValues[i++] = num ;}if(paramType == long.class || paramType==Long.class){String str = ((String[])value)[0] ;long num = Long.parseLong(str) ;paramValues[i++] = num ;}if(paramType == double.class || paramType==Double.class){String str = ((String[])value)[0] ;double num = Double.parseDouble(str) ;paramValues[i++] = num ;}if(paramType == String[].class){paramValues[i++] = value ;}//url?cname=1&cname=2&cname3 =》框架会存储成数组[1,2,3]if(paramType == int[].class){String[] ss = (String[])value ;int[] nums = new int[ss.length];for(int j=0;j< ss.length;j++){nums[j] = Integer.parseInt(ss[i]);}}if(paramType == Integer[].class){String[] ss = (String[])value ;Integer[] nums = new Integer[ss.length];for(int j=0;j< ss.length;j++){nums[j] = Integer.valueOf(ss[i]);}}}}return paramValues ;}
