目录
1. 原生Servlet获取请求参数
2. 通过控制器方法的取请求参形参获取请求参数
3. @RequestParam
4. @ReuqestHeader
5. @CookieValue
6. 通过POJO获取请求参数
7. 解决获取请求参数的乱码问题
1. 原生Servlet获取请求参数
这里我们创建一个控制器,以及一个用于跳转成功的取请求参页面
@RequestMapping("/param")public String param(){ return "test_param";}
测试请求参数 测试请求参数
测试使用servletAPI获取请求参数
@Controllerpublic class ParamController { @RequestMapping("/testServletAPI") // 形参位置的request表示当前请求 public String testServletAPI(HttpServletRequest request){ String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("username:"+username+",password:"+password); return "success"; }}
一开始去访问http://localhost:8080/springMVC/param这个地址,然后跳转到test_param页面,取请求参点击里面的取请求参超链接,携带参数跳转到success页面,取请求参这是取请求参用ServletAPI做到的,但是取请求参我们在SpringMVC中基本是不用这种方式来实现。
注:
我们在使用SpringMVC的取请求参时候,能不用原生API就不用,取请求参因为我们当前操作的取请求参数据,SpringMVC就已经帮助我们获取过了,取请求参而且它还会给我们提供更简单的取请求参方式让我们获取,没有必要使用原生的取请求参ServletAPI
2. 通过控制器方法的形参获取请求参数
既然我们不适用原生ServletAPI进行获取参数,当然,取请求参SpringMVC也有自己获取请求参数的取请求参方式
前端代码还是这样:
测试获取请求参数-->/testParam
@RequestMapping("/testParam")public String testParam(String username, String password){ System.out.println("username:"+username+",password:"+password); return "success";}
那么我们还有一种情况,当前传过来有多个同名的请求参数,这个时候又要如何处理?
用户名:
密码:
爱好: a b c
@RequestMapping("/testParam")public String testParam(String username,String password,String[] hobby){ System.out.println("username:"+username+",password:"+password+",hobby:"+ Arrays.toString(hobby)); return "success";}
这时候我们是用一个表单里面有爱好来测试多个同名的请求参数,这个是字符串数组形式的输出结果
现在我们来测试用字符串输出结果
@RequestMapping("/testParam")public String testParam(String username,String password,String hobby){ System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby); return "success";}
3. @RequestParam
我们之前是在方法里面的设置形参,然后让形参跟前端的请求参数名进行匹配,最终获得参数,但是如果前端的参数值和形参名不匹配会发生什么?
这时候我们把username改成user_name
用户名:
密码:
爱好: a b c
方法这边的形参名还是用username来接收
@RequestMapping("/testParam")public String testParam(String username,String password,String hobby){ System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby); return "success";}
可以看到username并没有获取到,也就是说只要是请求参数名和形参名不一致,那就没办法获取值,那么此时就要用到一个注解——@RequestParam。
@RequestMapping("/testParam")public String testParam( @RequestParam("user_name") String username, String password, String hobby){ System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby); return "success";}
这个注解的用处就是将请求参数和形参建立映射关系,那么这里就是将请求参数user_name和形参username对应,此时就可以获取到值了
4. @ReuqestHeader
这里要注意:@RequestParam、@ReuqestHeader、@CookieValue这三个注解所拥有的属性基本都是一模一样的,这三个注解都拥有value、required、defaultValue这三个属性,作用是一样的,只不过这三个属性所操作的内容不一样,比如说@RequestParam是将请求参数和形参进行建立映射关系,而@ReuqestHeader是将请求头信息与形参建立映射关系,@CookieValue是将Cookie与形参进行建立映射关系。
请求头信息也是键值对,所以这里可以通过@RequestHeader然后指定一个请求头的键,然后就可以将指定的请求头信息和形参进行绑定
@RequestMapping("/testParam")public String testParam( @RequestParam(value = "user_name",required = false,defaultValue = "hehe") String username, String password, String hobby, @RequestHeader("Host") String host ){ System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby); System.out.println("host:"+host); return "success";}
那么此时会把请求头信息打印出来。
当然,里面还有required和defaultValue属性,当required为false时,如果没有请求头信息,则不处理,赋null值,如果为true则进行报错。
defaultValue属性,当没有请求头信息时,自动设置为我们自己设置的默认值。
@RequestMapping("/testParam")public String testParam( @RequestParam(value = "user_name",required = false,defaultValue = "hehe") String username, String password, String hobby, @RequestHeader(value = "sayHaha",required = true,defaultValue = "Haha") String host ){ System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby); System.out.println("host:"+host); return "success";}
5. @CookieValue
当去调用getSession方法的时候,就会创建一个键JSESSIONID的cookie。
@RequestMapping("/testServletAPI")// 形参位置的request表示当前请求public String testServletAPI(HttpServletRequest request){ HttpSession session = request.getSession(); String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("username:"+username+",password:"+password); return "success";}
由于是会话技术,生命周期是浏览器开启到浏览器关闭,所以只要是浏览器不关闭,cookie将一直存在。
由于我们是第一次访问getSession方法,Cookie是存在于当前的响应报文中
第一次执行getSession方法的时候,会去检测请求报文中是否携带JSESSIONID的Cookie,如果没有就说明在这一次的会话中,是第一次创建Session对象,所以就会去创建一个Session对象,然后将Session放在服务器所维护的Map集合中,并且去创建一个Cookie,这个Cookie的键是固定的,是JSESSIONID,值则是一个随机序列,然后还会将这个HttpSession对象存储到当前的服务器所维护的Map集合中,以JSESSIONID的Cookie的值,也就是这个随机序列,作为Map集合的键,把Session对象作为Map的值进行存储,存储在服务器内部,这时候再把Cookie响应到浏览器。所以说第一次去访问浏览器getSession方法的时候,JSESSIONID是会存在于响应报文中,从此之后将存在于请求报文中,因为Cookie就是这个工作原理。
第一次JESSIONID存在于响应报文中
我们对页面进行刷新,这时候响应报文中已经没有了,存在于请求报文中。
此时的请求报文中也有携带Cookie
@RequestMapping("/testParam")public String testParam( @RequestParam(value = "user_name",required = false,defaultValue = "hehe") String username, String password, String hobby, @RequestHeader(value = "sayHaha",required = true,defaultValue = "Haha") String host, @CookieValue("JSESSIONID") String JSESSIONID ){ System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby); System.out.println("host:"+host); System.out.println("JSESSIONID:"+JSESSIONID); return "success";}
6. 通过POJO获取请求参数
有时候请求参数很多,比如说添加和修改功能等,将数据添加到数据库,那我们这些添加的数据就要对应数据库字段,而数据库同样对应实体类对象,所以说在页面中添加的数据,跟实体类对象属性也是一一对应。
这个时候SpringMVC又为我们提供了一种很简单的方式,也就是当表单里面的name跟实体类里面的属性对应,那么我们可以在形参位置去写实体类的形参,这个时候只要保证请求参数的名字,跟实体类中的属性名保持一致,就可以自动通过实体类对象收集这些请求参数。
用户名:
密码:
性别:男女
年龄:
邮箱:
public class User { private Integer id; private String username; private String password; private Integer age; private String sex; private String email; public User(Integer id, String username, String password, Integer age, String sex, String email) { this.id = id; this.username = username; this.password = password; this.age = age; this.sex = sex; this.email = email; } public User() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "User{ " + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", email='" + email + '\'' + '}'; }}
@RequestMapping("/testbean")public String testBean(User user){ System.out.println(user); return "success";}
可以看到我们确实是接受到了,但是sex是乱码,出现乱码原因就是因为字符编码不一致而造成的
7. 解决获取请求参数的乱码问题
在我们设置编码之前,已经获取了请求参数,再设置编码,这样是没有任何作用的,那么处理这种请求参数乱码的问题有2种,一种是GET请求,一种是POST请求
我们先尝试一下将表单的method设置为get
可以看到,用GET请求并不会出现乱码的问题,这个问题是Tomcat造成的,也就是说GET请求造成的乱码是由Tomcat来处理的,我们需要去找Tomcat那边去找个配置文件server.xml
这里要注意,Tomcat8以上是不需要改的,没有URIEncoding="UTF-8"也会解析为这个编码。
那么我们前面也说了,如果是已经获取完请求参数,再设置编码,是没有用的,DispatcherServlet里面已经获取了请求参数,所以我们应该在DispatcherServlet获取请求参数之前设置编码
那么是什么组件比Servlet执行更早的呢?
服务器中三大组件:监听器,过滤器,Servlet
监听器执行最早,然后是过滤器,最后是Servlet。
但是监听器是监听作用,监听ServletContext创建和销毁,所以这两个方法都是只执行一次。
过滤器,只要我们设置了过滤路径,访问的请求地址满足过滤路径,都会被过滤器进行过滤。
通过过滤器设置编码,每一次请求都要经过过滤器进行处理,再交给DispatcherServlet处理,当然,这个过滤器我们也不用写,因为SpringMVC已经为我们提供好了。
CharacterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceResponseEncoding true CharacterEncodingFilter /*
那么过滤器配置完了,我们再来试一下POST请求参数还会不会出现乱码问题
这时候不会出现了。