在CollectionVO对象中定义一个map
// 自定义Vo对象
public class CollectionVO {
private List<String> lists;
private Map<String, String> maps;
public Map<String, String> getMaps() {
return maps;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public List<String> getLists() {
return lists;
}
public void setLists(List<String> lists) {
this.lists = lists;
}
}
测试map类型参数的接收
使用Tomcat8部署项目时,有接口会报400错误,后端提示在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义
tomcat在8.5版本之后对请求的url的数值做了限制,如果url中有其他特殊符号需要进行配置,否则tomcat无法处理该请求。
当我们在插入map的时候例如:
http://localhost:9999/springmvc_day1/param/test3?maps['aaa']=111&maps['bbb']=222&maps['ccc']=333
在地址栏会将’单引号解析为%
tomcat高版本严格按照RFC 3986规范解析地址。该规范只允许包含 a-zA-Z 0-9 - _ . ~ 以及所有保留字符 ! * ’ ( ) ; : @ & = + $ , / ? # [ ]
,没有%
所以我们要在配置文件中进行修改
relaxedPathChars="|{}[],%" relaxedQueryChars="|{}[],%"
学习于:在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义
这样之后我们地址栏输入:
http://localhost:9999/springmvc_day1/param/test3?maps['aaa']=111&maps['bbb']=222&maps['ccc']=333
就会打印出:
k = aaa v = 111
k = bbb V = 222
k = ccc v = 333
打印出了正确的结果
接收表单
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
测试参数接收
测试对象和零散对象接收
# springmvc在接收post请求参数时中文乱码问题解决方案
1. 出现乱码的两种请求方式的解决方案
a. GET方式的请求出现乱码
tomcat8.x版本以前 默认使用server.xml 中URIEncoding="iso-8559-1" 编码不是utf-8 出现中文乱码
tomcat8.x版本以后 默认使用server.xml 中URIEncoding="UTF-8"
2. 在springmvc中post方式中文乱码解决方案
说明:在springmvc中默认没有对post方式请求进行任何编码处理,所以直接接收post方式请求会出现中文乱码
a. 解决方案
自定义filter request,response对象编码
b. 使用springmvc提供好的编码filter CharacterEncodingFilter
表单:
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
测试参数接收
测试对象和零散对象接收
如果使用的是旧版的idea,并且使用了tomcat8.x版本甚至更新,默认使用server.xml 中URIEncoding="UTF-8"所以不用解决。
如果是新版本的idea,2021.x的,新版本idea,不再认可直接从文件中编辑参数
因此我们这样修改编码格式:
测试:
/**
* 用来测试参数接收的Controller
*/
@Controller
@RequestMapping("param")
public class ParamController {
/**
* 用来测试对象类型的参数接收
* 接收对象类型:也是直接将要接受的对象作为控制器方法参数声明
* 注意:springmvc封装对象时直接根据传递参数key与对象中属性名一致自动封装对象
* url: http://localhost:9999/springmvc_day1/param/test1?id=21&name=zhangsan&age=23&bir=2012/12/12
* form:
* input name="id"
* input name="name"
* input name="age"
* input name="bir"
*/
@RequestMapping("test1")
public String test1(User user, String name){
System.out.println("name = " + name);
System.out.println("user = " + user);
return "index";
}
}
其实上面这个方法就已经解决了下面的post请求出现的中文乱码问题,但是我们还是要学一学另外的处理方式。
测试类:
/**
* 用来测试参数接收的Controller
*/
@Controller
@RequestMapping("param")
public class ParamController {
/**
* 用来测试对象类型的参数接收
* 接收对象类型:也是直接将要接受的对象作为控制器方法参数声明
* 注意:springmvc封装对象时直接根据传递参数key与对象中属性名一致自动封装对象
* url: http://localhost:9999/springmvc_day1/param/test1?id=21&name=zhangsan&age=23&bir=2012/12/12
* form:
* input name="id"
* input name="name"
* input name="age"
* input name="bir"
*/
@RequestMapping("test1")
public String test1(User user, String name){
System.out.println("name = " + name);
System.out.println("user = " + user);
return "index";
}
}
表单:
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
测试参数接收
测试对象和零散对象接收
定义一个过滤类,专门用来解决中文乱码问题:
// 自定义编码filter
public class CharacterEncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding = filterConfig.getInitParameter("encoding");// 读取局部初始化参数
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding(encoding); // 设置请求的编码为UTF-8
servletResponse.setCharacterEncoding(encoding); // 设置响应的编码为UTF-8
filterChain.doFilter(servletRequest, servletResponse); // 放行请求
}
@Override
public void destroy() {
}
}
在web.xml文件中配置filter
<filter>
<filter-name>charsetfilter-name>
<filter-class>com.baizhi.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>charsetfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
其实这个过滤类谁来写都一样的,所以官方写好了一个过滤类,我们只需要在web.xml文件中配置即可
<filter>
<filter-name>charsetfilter-name>
<filter-class>org.springframework.web.filterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>charsetfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
测试:
在地址栏输入:
http://localhost:9999/springmvc_day1/param/test1
springmvc其实是一个控制器,对于一个控制器而言,我们就关注三件事,收集数据、调用业务对象、流程跳转,其实在调用业务对象和跳转流程这两个环节里其实还隐藏了一步,就是数据的传递过程。
# springmvc中数据传递机制
1. 数据传递机制
页面如何获取数据 页面如何展示数据
数据怎么存储? 数据在页面如何获取? 在页面中获取的数据该如何展示?
Servlet request, EL表达式 EL+JSTL标签 展示
session,
application
Struts2 request, EL表达式 EL+JSTL标签 展示
session,
application
SpringMVC request, EL表达式 EL+JSTL标签
session,
application
2. 存数据具体使用哪种作用域
跳转方式:
forward: 一次请求 request作用域|Model(springmvc提供,Model内部封装的就是request,且Model只能用于forward)
redirect:多次请求 session作用域 application作用域[不推荐] ?"问号"地址栏传递(但是"问号"传递的数据是有限的)
3. 如何在springmvc控制器方法中获取request对象,response对象
// 声明一个HttpServletRequest、HttpServletResponse,会在请求访问控制器这个方法时会自动把当前的请求对象
// 和响应对象赋值给这两个声明的参数
public String findAll(HttpServletRequest request, HttpServletResponse response){
request.getSession(); // 拿到session对象
request.getServletContext(); // 拿到application对象
}
注意:直接将request response对象作为控制器方法参数声明即可获取
- Servlet中数据传递机制:
springmvc是一个控制器,这个控制器可以说是基于最早期原始的servlet技术而来的,所以我们先来回顾一下servlet中的
数据处理机制,在servlet中存数据我们得找作用域,所以在整个servlet中我们在做数据传递的过程中,我们其实用的是
request、session、application这样的对象,日后在存储数据时,我们就用这些作用域,那时候我们的页面该如何获取呢,
在servlet我们是通过EL表达式去获取存在作用域中的数据。如果取的是单个数据,EL表达式取出来之后直接展示;如果是一个
集合类型的数据,取出来之后我们要通过EL去获取配合JSTL标签才能展示数据。
- Struts2中数据传递机制
Struts2中存数据的时候其实我们用的也是作用域,request、session、application,只不过struts2有一个特有的机制,
成员变量替换了request作用域,虽然它替换request作用,但它底层操作的也是request对象,所以我们也可以认为,它就是
直接request,Struts2是如何在页面中取数据呢,同样是EL表达式,那在页面中如何去展示数据呢,EL+JSTL标签展示数据。
获取request对象,response对象:
Struts2:ServletActionContext.getRequest(); ServletActionContext.getResponse(); 工具类
- springmvc中数据传递机制
其实对于springmvc而言,它作为一个控制器框架,这个控制器框架如果在开发的时候想要被更多的人接受,那它就尽可能做到轻量,
不要让更多的开发人员去花费大量的精力去学它,所以springmvc也沿用了原始的servlet或struts2中的数据处理机制,也就是在
springmvc中数据处理机制没变,存数据还是request、session、application,存数据还是找作用域,取数据还是用EL表达式,
取出来的数据如果是多个,同样用EL+JSTL标签去展示。如果是单个数据,EL取出来直接就展示了,如果是多个数据,就要配合JSTL
标签进行遍历
需要的jsp文件attr.jsp
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
测试数据传递
用来测试数据的传递
获取request作用域数据:${requestScope.username}
获取request作用域数据:${username}
/**
* 用来测试springmvc中数据传递机制
*/
@Controller
@RequestMapping("attr")
public class AttrController {
/**
* 使用forward跳转页面的数据传递
* 1. 传递零散类型数据 2. 传递对象类型数据 3. 传递集合类型数据
*/
@RequestMapping("test")
public String test(HttpServletRequest request, HttpServletResponse response){
// 1. 收集参数
// 2. 调用业务方法 String name = "小陈";
String name = "小陈";
request.setAttribute("username", name); // 存储数据
// 3. 流程跳转
return "attr";
}
}
补充:如果想要格式化日期,我们可以按照下面的步骤做
在pom.xml文件中引入jstl依赖
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
修改原来attr.jsp文件中日期那一行:
<h3>bir: <fmt:formatDate value="${requestScope.user.bir}" pattern="yyyy-MM-dd"/>h3>
因为在jsp页面中遍历时需要用到c标签,所以我们在jsp文件最上面加入这句话
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
补充
只有一个数据时用?拼接(或少量数据)
传英文:
public class AttrController {
/**
* 使用redirect跳转传递数据
* // 传递数据两种方式 一种:地址栏?拼接数据(仅限于数据比较少) 二种:session对象 (传递集合和forward一样,不再赘述)
*/
@RequestMapping("test1")
public String test1() throws UnsupportedEncodingException {
// 1. 收集数据
// 2. 调用业务
String name = "xiaochen";
// 3. 流程跳转
return "redirect:/attr.jsp?name="+name;
}
}
传中文:
当传递多个数据时用session
/**
* 用来测试springmvc中数据传递机制
*/
@Controller
@RequestMapping("attr")
public class AttrController {
/**
* 使用redirect跳转传递数据
* // 传递数据两种方式 一种:地址栏?拼接数据(仅限于数据比较少) 二种:session对象 (传递集合和forward一样,不再赘述)
*/
@RequestMapping("test1")
public String test1(HttpServletRequest request) throws UnsupportedEncodingException {
// 1. 收集数据
// 2. 调用业务
String name = "xiaochen";
User user = new User("21", "百知教育", 23, new Date());
request.getSession().setAttribute("user", user);
// 3. 流程跳转
return "redirect:/attr.jsp?name="+name;
}
}
总结: