一、请求处理
1、请求参数处理
在之前的servlet中我们可以通过request.getParameter()来获取请求中的参数,但是在我们编写的SpringMVC的应用程序中,在具体请求的方法中并不包含request参数,那么我们应该如何获取请求中的参数呢?
1-1、在方法中添加参数
如下,页面请求通过?name=xxx即可向Controller传值
在Controller中,在方法中直接用Sring name接收即可
1-1-1、自动转换类型错误
如果我们传入的参数是字符串,但是方法中的参数类型是Integer,就会发生报错提示,注意400这个错误是springmvc自定义的错误,就是参数异常。
下图我们把传入的参数改为数字,即可顺利接收参数了。
因此我们在方法中使用String的时候,传入值为String Integer float double 等都可以进行自动转换。
1-1-2、参数名称必须保持一致
如下图,传入参数为age,但是方法内的参数是name,这样就无法获取到传入的参数值了
2、使用注解获得相关参数
需要使用以下几个注解:
@RequestParam:获取请求的参数
@RequestHeader:获取请求头信息
@CookieValue:获取cookie中的值
2-1、@RequestParam
2-2-1、通过value 重命名参数名称(重命名之后,之前的参数名则失效)
如下可以通过@RequestParam 可以修改方法参数名的名称,@RequestParam(value="username"),其中value可以省略
2-2-2、通过defaultValue设置参数默认值(默认是必传)
如下可以通过defaultValue="" 设置参数的默认值,只要外部不传入参数,就可以使用默认值
注意,如果value 和defaultValue 同时使用,value就不能省略了
2-2-3、通过require设置必传/非必传
如下通过设置require=true,就可以设置参数必传了
切记这个时候不能使用defaultValue,否则require=true就不起作用了。
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值
需要注意的是,传入参数的名称需要和javaBean的属性名称一致,如下(这样才可以成功接收数据):
2-2-5、使用get或者post传参过程中乱码解决方案
2-2-5-1、 get传参乱码
可以在tomcat/conf/server.xml中修改如下地方,添加URIEncoding="utf-8"
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这个类
上图就相当于我们在web.xml里面配置的
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
复制代码
设置响应和请求都以encodeing编码 上图在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、测试
未设置之前
设置之后
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、测试
页面填入数据如下
提交后台接收输入如下:
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对象,我们看一下
如上图,因为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进行修改,如下
2-4-3、Controller的方法改为如下
//传入复杂数据类型
@RequestMapping("/saveUser")
public String saveUser(UserDTO userDTO){
System.out.println(userDTO.toString());
return "index.jsp";
}
复制代码
2-4-4、测试如下
小结
如果Controller需要传多个对象,并且对象中有相同的属性,就可以创建一个大类,然后将对象最为大类的属性,传值的时候根据 对应的对象及属性传递就可以了。
2-5、@RequestHeader
通过RequestHeader 就可以获取 header中的数据了
2-5-1、获得固定某个参数
2-5-2、获得所有header参数
如果想一次性获取所有Header信息可以使用Map来接收header数据,如下: