• SpirngMVC获取请求参数


    目录

    1. 原生Servlet获取请求参数

    2. 通过控制器方法的形参获取请求参数

    3. @RequestParam

    4. @ReuqestHeader

    5. @CookieValue

    6. 通过POJO获取请求参数

    7. 解决获取请求参数的乱码问题


    1. 原生Servlet获取请求参数

    这里我们创建一个控制器,以及一个用于跳转成功的页面

    1. @RequestMapping("/param")
    2. public String param(){
    3. return "test_param";
    4. }
    1. html>
    2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>测试请求参数title>
    6. head>
    7. <body>
    8. <h1>测试请求参数h1>
    9. <a th:href="@{/testServletAPI(username='admin',password=123456)}">测试使用servletAPI获取请求参数a><br>
    10. body>
    11. html>
    1. @Controller
    2. public class ParamController {
    3. @RequestMapping("/testServletAPI")
    4. // 形参位置的request表示当前请求
    5. public String testServletAPI(HttpServletRequest request){
    6. String username = request.getParameter("username");
    7. String password = request.getParameter("password");
    8. System.out.println("username:"+username+",password:"+password);
    9. return "success";
    10. }
    11. }

    一开始去访问http://localhost:8080/springMVC/param这个地址,然后跳转到test_param页面,点击里面的超链接,携带参数跳转到success页面,这是用ServletAPI做到的,但是我们在SpringMVC中基本是不用这种方式来实现。

    注:

    我们在使用SpringMVC的时候,能不用原生API就不用,因为我们当前操作的数据,SpringMVC就已经帮助我们获取过了,而且它还会给我们提供更简单的方式让我们获取,没有必要使用原生的ServletAPI


    2. 通过控制器方法的形参获取请求参数

    既然我们不适用原生ServletAPI进行获取参数,当然,SpringMVC也有自己获取请求参数的方式

    前端代码还是这样:

    <a th:href="@{/testParam(username='admin',password=123456)}">测试获取请求参数-->/testParama><br>
    1. @RequestMapping("/testParam")
    2. public String testParam(String username, String password){
    3. System.out.println("username:"+username+",password:"+password);
    4. return "success";
    5. }

    那么我们还有一种情况,当前传过来有多个同名的请求参数,这个时候又要如何处理?

    1. <form th:action="@{/testParam}" method="get">
    2. 用户名: <input type="text" name="username"><br>
    3. 密码: <input type="password" name="password"><br>
    4. 爱好: <input type="checkbox" name="hobby" value="a">a
    5. <input type="checkbox" name="hobby" value="b">b
    6. <input type="checkbox" name="hobby" value="c">c <br>
    7. <input type="submit" value="测试使用控制器的形参来获取请求参数">
    8. form>
    1. @RequestMapping("/testParam")
    2. public String testParam(String username,String password,String[] hobby){
    3. System.out.println("username:"+username+",password:"+password+",hobby:"+ Arrays.toString(hobby));
    4. return "success";
    5. }

    这时候我们是用一个表单里面有爱好来测试多个同名的请求参数,这个是字符串数组形式的输出结果


    现在我们来测试用字符串输出结果

    1. @RequestMapping("/testParam")
    2. public String testParam(String username,String password,String hobby){
    3. System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby);
    4. return "success";
    5. }

    3. @RequestParam

    我们之前是在方法里面的设置形参,然后让形参跟前端的请求参数名进行匹配,最终获得参数,但是如果前端的参数值和形参名不匹配会发生什么?

    这时候我们把username改成user_name

    1. <form th:action="@{/testParam}" method="get">
    2. 用户名: <input type="text" name="user_name"><br>
    3. 密码: <input type="password" name="password"><br>
    4. 爱好: <input type="checkbox" name="hobby" value="a">a
    5. <input type="checkbox" name="hobby" value="b">b
    6. <input type="checkbox" name="hobby" value="c">c <br>
    7. <input type="submit" value="测试使用控制器的形参来获取请求参数">
    8. form>

    方法这边的形参名还是用username来接收

    1. @RequestMapping("/testParam")
    2. public String testParam(String username,String password,String hobby){
    3. System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby);
    4. return "success";
    5. }

    可以看到username并没有获取到,也就是说只要是请求参数名和形参名不一致,那就没办法获取值,那么此时就要用到一个注解——@RequestParam。

    1. @RequestMapping("/testParam")
    2. public String testParam(
    3. @RequestParam("user_name") String username,
    4. String password,
    5. String hobby){
    6. System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby);
    7. return "success";
    8. }

    这个注解的用处就是将请求参数和形参建立映射关系,那么这里就是将请求参数user_name和形参username对应,此时就可以获取到值了


    4. @ReuqestHeader

    这里要注意:@RequestParam、@ReuqestHeader、@CookieValue这三个注解所拥有的属性基本都是一模一样的,这三个注解都拥有value、required、defaultValue这三个属性,作用是一样的,只不过这三个属性所操作的内容不一样,比如说@RequestParam是将请求参数和形参进行建立映射关系,而@ReuqestHeader是将请求头信息与形参建立映射关系,@CookieValue是将Cookie与形参进行建立映射关系。


    请求头信息也是键值对,所以这里可以通过@RequestHeader然后指定一个请求头的键,然后就可以将指定的请求头信息和形参进行绑定

    1. @RequestMapping("/testParam")
    2. public String testParam(
    3. @RequestParam(value = "user_name",required = false,defaultValue = "hehe") String username,
    4. String password,
    5. String hobby,
    6. @RequestHeader("Host") String host
    7. ){
    8. System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby);
    9. System.out.println("host:"+host);
    10. return "success";
    11. }

    那么此时会把请求头信息打印出来。

    当然,里面还有required和defaultValue属性,当required为false时,如果没有请求头信息,则不处理,赋null值,如果为true则进行报错。

    defaultValue属性,当没有请求头信息时,自动设置为我们自己设置的默认值。  

    1. @RequestMapping("/testParam")
    2. public String testParam(
    3. @RequestParam(value = "user_name",required = false,defaultValue = "hehe") String username,
    4. String password,
    5. String hobby,
    6. @RequestHeader(value = "sayHaha",required = true,defaultValue = "Haha") String host
    7. ){
    8. System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby);
    9. System.out.println("host:"+host);
    10. return "success";
    11. }


    5. @CookieValue

    当去调用getSession方法的时候,就会创建一个键JSESSIONID的cookie。

    1. @RequestMapping("/testServletAPI")
    2. // 形参位置的request表示当前请求
    3. public String testServletAPI(HttpServletRequest request){
    4. HttpSession session = request.getSession();
    5. String username = request.getParameter("username");
    6. String password = request.getParameter("password");
    7. System.out.println("username:"+username+",password:"+password);
    8. return "success";
    9. }

    由于是会话技术,生命周期是浏览器开启到浏览器关闭,所以只要是浏览器不关闭,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

    1. @RequestMapping("/testParam")
    2. public String testParam(
    3. @RequestParam(value = "user_name",required = false,defaultValue = "hehe") String username,
    4. String password,
    5. String hobby,
    6. @RequestHeader(value = "sayHaha",required = true,defaultValue = "Haha") String host,
    7. @CookieValue("JSESSIONID") String JSESSIONID
    8. ){
    9. System.out.println("username:"+username+",password:"+password+",hobby:"+ hobby);
    10. System.out.println("host:"+host);
    11. System.out.println("JSESSIONID:"+JSESSIONID);
    12. return "success";
    13. }

    6. 通过POJO获取请求参数

    有时候请求参数很多,比如说添加和修改功能等,将数据添加到数据库,那我们这些添加的数据就要对应数据库字段,而数据库同样对应实体类对象,所以说在页面中添加的数据,跟实体类对象属性也是一一对应。

    这个时候SpringMVC又为我们提供了一种很简单的方式,也就是当表单里面的name跟实体类里面的属性对应,那么我们可以在形参位置去写实体类的形参,这个时候只要保证请求参数的名字,跟实体类中的属性名保持一致,就可以自动通过实体类对象收集这些请求参数。

    1. <form th:action="@{/testbean}" method="post">
    2. 用户名:<input type="text" name="username"><br>
    3. 密码:<input type="password" name="password"><br>
    4. 性别:<input type="radio" name="sex" value="男"><input type="radio" name="sex" value="女"><br>
    5. 年龄:<input type="text" name="age"><br>
    6. 邮箱:<input type="text" name="email"><br>
    7. <input type="submit" value="使用实体类接收请求参数">
    8. form>
    1. public class User {
    2. private Integer id;
    3. private String username;
    4. private String password;
    5. private Integer age;
    6. private String sex;
    7. private String email;
    8. public User(Integer id, String username, String password, Integer age, String sex, String email) {
    9. this.id = id;
    10. this.username = username;
    11. this.password = password;
    12. this.age = age;
    13. this.sex = sex;
    14. this.email = email;
    15. }
    16. public User() {
    17. }
    18. public Integer getId() {
    19. return id;
    20. }
    21. public void setId(Integer id) {
    22. this.id = id;
    23. }
    24. public String getUsername() {
    25. return username;
    26. }
    27. public void setUsername(String username) {
    28. this.username = username;
    29. }
    30. public String getPassword() {
    31. return password;
    32. }
    33. public void setPassword(String password) {
    34. this.password = password;
    35. }
    36. public Integer getAge() {
    37. return age;
    38. }
    39. public void setAge(Integer age) {
    40. this.age = age;
    41. }
    42. public String getSex() {
    43. return sex;
    44. }
    45. public void setSex(String sex) {
    46. this.sex = sex;
    47. }
    48. public String getEmail() {
    49. return email;
    50. }
    51. public void setEmail(String email) {
    52. this.email = email;
    53. }
    54. @Override
    55. public String toString() {
    56. return "User{" +
    57. "id=" + id +
    58. ", username='" + username + '\'' +
    59. ", password='" + password + '\'' +
    60. ", age=" + age +
    61. ", sex='" + sex + '\'' +
    62. ", email='" + email + '\'' +
    63. '}';
    64. }
    65. }
    1. @RequestMapping("/testbean")
    2. public String testBean(User user){
    3. System.out.println(user);
    4. return "success";
    5. }

    可以看到我们确实是接受到了,但是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已经为我们提供好了。  

    1. <filter>
    2. <filter-name>CharacterEncodingFilterfilter-name>
    3. <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    4. <init-param>
    5. <param-name>encodingparam-name>
    6. <param-value>UTF-8param-value>
    7. init-param>
    8. <init-param>
    9. <param-name>forceResponseEncodingparam-name>
    10. <param-value>trueparam-value>
    11. init-param>
    12. filter>
    13. <filter-mapping>
    14. <filter-name>CharacterEncodingFilterfilter-name>
    15. <url-pattern>/*url-pattern>
    16. filter-mapping>

    那么过滤器配置完了,我们再来试一下POST请求参数还会不会出现乱码问题

    这时候不会出现了。  

  • 相关阅读:
    arm cortex-m架构 SVC指令详解以及SVC异常在freertos的应用
    Vue3使用dataV报错问题解决
    NSSCTF第13页(2)
    Rt-Thread 移植2--线程定义与切换(KF32)
    【面经】如何查看服务器内存和磁盘空间占用
    尤雨溪Vue登榜GitHub之路看似不难
    MapStruct入门及集成springboot
    python将图片合并为视频
    C++中将十六进制数转化为字符串数据
    你真的了解HTML中的JavaScript吗?
  • 原文地址:https://blog.csdn.net/qq_44706176/article/details/126681388