SpringMVC请求处理

一、请求处理

1、请求参数处理

在之前的servlet中我们可以通过request.getParameter()来获取请求中的参数,但是在我们编写的SpringMVC的应用程序中,在具体请求的方法中并不包含request参数,那么我们应该如何获取请求中的参数呢?

1-1、在方法中添加参数

如下,页面请求通过?name=xxx即可向Controller传值 image.png

在Controller中,在方法中直接用Sring name接收即可 image.png

1-1-1、自动转换类型错误

如果我们传入的参数是字符串,但是方法中的参数类型是Integer,就会发生报错提示,注意400这个错误是springmvc自定义的错误,就是参数异常。 image.png

下图我们把传入的参数改为数字,即可顺利接收参数了。 image.png

因此我们在方法中使用String的时候,传入值为String Integer float double 等都可以进行自动转换。

1-1-2、参数名称必须保持一致

如下图,传入参数为age,但是方法内的参数是name,这样就无法获取到传入的参数值了 image.png

2、使用注解获得相关参数

需要使用以下几个注解:

@RequestParam:获取请求的参数

@RequestHeader:获取请求头信息

@CookieValue:获取cookie中的值

2-1、@RequestParam

2-2-1、通过value 重命名参数名称(重命名之后,之前的参数名则失效)

如下可以通过@RequestParam 可以修改方法参数名的名称,@RequestParam(value="username"),其中value可以省略 image.png

2-2-2、通过defaultValue设置参数默认值(默认是必传)

如下可以通过defaultValue="" 设置参数的默认值,只要外部不传入参数,就可以使用默认值

注意,如果value 和defaultValue 同时使用,value就不能省略了 image.png

2-2-3、通过require设置必传/非必传

如下通过设置require=true,就可以设置参数必传了

切记这个时候不能使用defaultValue,否则require=true就不起作用了。 image.png

2-2、javaBean--复杂数据类型传参

2-2-1、创建javaBean

User.java

package com.jony.entity;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class User {
    private  Integer id;
    private  String name;
    private String[] alias;  //外号
    private List<String> hobbies; //兴趣爱好
    private Map<String,String> relatives;  //亲属
    private Role role;
    private List<User> friends;  //朋友

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String[] getAlias() {
        return alias;
    }

    public void setAlias(String[] alias) {
        this.alias = alias;
    }

    public List<String> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    public Map<String, String> getRelatives() {
        return relatives;
    }

    public void setRelatives(Map<String, String> relatives) {
        this.relatives = relatives;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    public List<User> getFriends() {
        return friends;
    }

    public void setFriends(List<User> friends) {
        this.friends = friends;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", alias=" + Arrays.toString(alias) +
                ", hobbies=" + hobbies +
                ", relatives=" + relatives +
                ", role=" + role +
                ", friends=" + friends +
                '}';
    }
}
复制代码

Role.java

package com.jony.entity;

public class Role {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", name='" + name + ''' +
                '}';
    }
}
复制代码

UserDTO.jsp

package com.jony.entity;

public class UserDTO {
    private User user;
    private Role role;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    @Override
    public String toString() {
        return "UserDTO{" +
                "user=" + user +
                ", role=" + role +
                '}';
    }
}
复制代码

2-2-2、创建Controller方法

//传入复杂数据类型
@RequestMapping("/saveUser")
public String saveUser(User user){
    System.out.println(user.toString());
    return "index.jsp";
}
复制代码

2-2-3、修改index.jsp作为提交复杂数据类型的功能

需要注意的是form中action路径建议为绝对路径,相对路径后面各页面功能直接跳转就会错乱

在jsp中使用 ${pageContext.request.contextPath}即可获得项目名称

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2022-03-21
  Time: 21:15
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>index</title>
  </head>
  <body>
  <form action="${pageContext.request.contextPath}/saveUser">
    <input type="text" name="name">
    <input type="submit" value="提交">
  </form>
  </body>
</html>
复制代码

2-2-4、使用jsp提交数据

可以看到虽然jsp中只提交了一个名称,但是在Controller方法中的User 参数可以获得到jsp中提交过来的name值 image.png

需要注意的是,传入参数的名称需要和javaBean的属性名称一致,如下(这样才可以成功接收数据):

image.png

2-2-5、使用get或者post传参过程中乱码解决方案

2-2-5-1、 get传参乱码

可以在tomcat/conf/server.xml中修改如下地方,添加URIEncoding="utf-8"

image.png

2-2-5-2、post传参乱码

可以使用springmvc自定的过滤器CharacterEncodingFilter,需要在web.xml里面进行配置,如下

<!--配置过滤器编码 使用CharacterEncodingFilter-->
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--设置编码-->
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <!--将 请求和响应都设置以UTF-8编码-->
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<!--设置过滤路径-->
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/</url-pattern>
</filter-mapping>
复制代码

这些参数为啥这么设置呢?我们可以看下CharacterEncodingFilter这个类

image.png 上图就相当于我们在web.xml里面配置的

<init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
</init-param>
复制代码

image.png

设置响应和请求都以encodeing编码 image.png 上图在web.xml中的体现为

<init-param>
    <param-name>forceEncoding</param-name>
    <param-value>true</param-value>
</init-param>
复制代码

最终在通过设置filter-mapping就可以设置过滤的路径,这样过滤器就设置完毕了,最终web.xml内容为

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--关联spring的配置文件,
        也可以不配,会自动到WEB-INF去找名字叫做 springmvc-servlet.xml的文件,springmvc即为上面servlet-name的名字-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <!--设置tomcat启动完成的时候 就会先初始化DispatcherServlet,在这里面再优先加载applicationContext.xml-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--匹配servlet的请求,/标识匹配所有请求-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--
        /                     除了jsp请求都会匹配到
        /*                    所有请求都会匹配到
        *.do *.action *.htm   url结尾匹配(可以自定义)
        -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--配置过滤器编码 使用CharacterEncodingFilter-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--设置编码-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!--将 请求和响应都设置以UTF-8编码-->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <!--设置过滤条件-->
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--设置过滤我们springmvc servlet请求-->
        <servlet-name>springmvc</servlet-name>
    </filter-mapping>
</web-app>
复制代码
2-2-5-3、测试

未设置之前

image.png

设置之后

image.png

2-3、数组、集合、Map复杂数据类型

2-3-1、编辑index.jsp相关标签

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>index</title>
  </head>
  <body>
  <form action="${pageContext.request.contextPath}/saveUser" method="post">
<%--    private  String name;--%>
    姓名:<input type="text" name="name"><p></p>
<%--  private String[] alias;  //外号--%>
  外号:<input type="checkbox" name="alias" value="倔强的小鸟">倔强的小鸟
      <input type="checkbox" name="alias" value="愤怒的小鸡">愤怒的小鸡<p></p>
<%--  private List<String> hobbies; //兴趣爱好--%>
  兴趣爱好:<input type="checkbox" name="hobbies[0]" value="唱歌">唱歌
          <input type="checkbox" name="hobbies[1]" value="看书">看书<p></p>
<%--  private Map<String,String> relatives;  //亲属--%>
  亲属:<input type="checkbox" name="relatives['father']" value="爸爸">爸爸
       <input type="checkbox" name="relatives['mater']" value="妈妈">妈妈<p></p>
<%--  private Role role;--%>
  角色:<input type="text" name="role.name" value=""><p></p>
<%--  private List<User> friends;  //朋友--%>
  朋友:<input type="text" name="friends[0].name" value="">
       <input type="text" name="friends[1].name" value="">
       <input type="text" name="friends[2].name" value=""><p></p>
    <input type="submit" value="提交">
  </form>
  </body>
</html>
复制代码

2-3-2、测试

页面填入数据如下

image.png 提交后台接收输入如下:

User{id=null, name='张三', alias=[倔强的小鸟, 愤怒的小鸡], hobbies=[唱歌, 看书], relatives={father=爸爸, mater=妈妈}, role=Role{id=null, name='超级管理员'}, friends=[User{id=null, name='李四', alias=null, hobbies=null, relatives=null, role=null, friends=null}, User{id=null, name='王五', alias=null, hobbies=null, relatives=null, role=null, friends=null}, User{id=null, name='赵六', alias=null, hobbies=null, relatives=null, role=null, friends=null}]}
复制代码

2-3-3、小结

数组:需要保证表单中元素的name都一致:如name="alias"
List:需要加上索引:
如果是基本数据类型则:name="hobbies[0]" name="hobbies[1]" 如果是对象:name="user[0].name" name="user[1].name"
Map:必须加上key ,如:name="map["key"]"
其他对象:只能给对象属性挨个赋值,如:name="bean.name" name="bean.age"

2-4、如果多个对象同时传参

假如现在我们需要同时提交User 和Role对象,我们看一下

image.png 如上图,因为User 和Role都有name,因此数据就没有办法按照我们的设想进行传递,这个时候就需要创建一个大类来处理了

2-4-1、创建大类

package com.jony.entity;

public class UserDTO {
    private User user;
    private Role role;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    @Override
    public String toString() {
        return "UserDTO{" +
                "user=" + user +
                ", role=" + role +
                '}';
    }
}
复制代码

2-4-2、修改index.jsp

为了测试,仅对user和role的name进行修改,如下 image.png

2-4-3、Controller的方法改为如下

//传入复杂数据类型
@RequestMapping("/saveUser")
public String saveUser(UserDTO userDTO){
    System.out.println(userDTO.toString());
    return "index.jsp";
}
复制代码

2-4-4、测试如下

image.png

小结

如果Controller需要传多个对象,并且对象中有相同的属性,就可以创建一个大类,然后将对象最为大类的属性,传值的时候根据 对应的对象及属性传递就可以了。

2-5、@RequestHeader

通过RequestHeader 就可以获取 header中的数据了

2-5-1、获得固定某个参数

image.png

2-5-2、获得所有header参数

如果想一次性获取所有Header信息可以使用Map来接收header数据,如下: image.png

2-6、@CookieValue获得cookie的值

2-6-1、获得cookie某一个key的值

image.png

猜你喜欢

转载自juejin.im/post/7078316625362944014