第一节 涉及知识
1.经典三层和MVC模式回顾
软件的整体架构有B/S(浏览器/服务器模式)和C/S(客户端/服务器模式),ee开发主要就是B/S模式,从代码开发的角度,代码有层的概念.
经典三层: web表现层(view+controller) +service业务层+dao(数据接入访问层)
2.经典三层
-
表现层(Web层)
整个表现层负责接收客户端浏览器的请求并响应结果给客户端浏览器显示。(Http请求)具体说来,表现层=View视图层+Controller控制层。Controller层负责接收请求、转发请求给Service层、跳转视图页面,servlet-->Struts(过滤器)-->SpringMVC
-
业务层(Service层)
负责业务逻辑处理,和项目需求息息相关(比如转账业务)。 -
Spring-->SpringBoot(全注解)
-
主要涉及逻辑:异常处理参数处理声明式事务AOP
-
持久层(Dao层)
和数据库交互,对数据表进行增删改查
JDBC-->JdbcTemplate --> DButils -->MyBatis->Spring Data JPA -->MyBatis Plus
主流:SSM-->潮流: Spring全家桶
第二节 SpringMVC快速入门
3.SpringMVC框架概述
SpringMVC是一个轻量级的eb表现层框架,用来写Controller接收请求跳转页面的,它是Spring框架的一部分。SpringMVC是对Servlet的封装和增强,简化了servlet的操作。它已经超越了Struts,成为目前最优秀的表现层框架。
- 学习SpringMVC,要把握它的本质
○接收请求,转发请求
○跳转页面 - 什么时候使用SpringMVC?
- 当你觉得servlet繁琐的时候
- 在哪儿使用SpringMVC?
○在web表现层使用SpringMVC - SpringMVC的优势
- 操作特简单,性能特别高,灵活性特别强
- 与Struts框架相比
- 解决了struts的安全性低,操作难,执行性能低的问题
- 拓展认识
- Spring + Spring jdbctemplate + SpringMVC --> Spring全家桶1.0主流
- Spring cloud +Spring Boot +Spring DatajPA+SpringMVC -->Spring全家桶2.0潮流
4.SpringMVC的处理流程
之前: request请求到servlet,一个项目中有很多servlet,不同serlvet处理不同的事情,好比很多年前装修,业主需要直接抱需求告知水工、电工、木工等。现在我们直接把需求告知包工头,包工头具体分发任务给下面的小弟(水工、电工、木工),我们不需要直接和其他人交涉。
前端控制器就类似于上面的包工头,不干具体的活,只负责接收请求,分发请求,反馈结果。
SpringMVC全局只需要一个servlet。
5.SpringMVC快速入门
需求:
浏览器输入url发起请求,该url请求被SpringMVC框架拦截处理,把后台服务器的当前时间输出到jsp页面显示。
实现步骤:
- 创建Maven工程,引入spring框架jar包,springMVC框架jar包,Servlet与jsp jar包
- 定义类DefaultController
- 方法gotoResult(),参数和返回值类型为ModelAndView
- 类添加@Controller注解
- 方法添加@RequestMapping注解,注解属性为客户端访问虚拟路径
- spring配置文件中,配置注解扫描
- web.xml配置mvc框架前端控制器
目录
maven jar包
<dependencies>
<!--spring核心包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!--springMVC的jar包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!--Servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<!--
provided的作用是:当项目打成war包时,当前的jar包不会压缩在当前的war包里
只在当前代码的编写和编译过程中产生依赖的作用,
当程序部署在Tomcat中的工程在war包压缩包中,通过加上provided不然jar包压缩在war包中
运行的时候,用Tomcat自身带的jar包
-->
<scope>provided</scope>
</dependency>
</dependencies>
<!--
运行方式有两种,一种是tomcat插件,然后在maven中找到对应的文件
打开tomcatjar包,右键run
另一种tomcat运行
配置Tomcat插件 -->
<!--
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>9090</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
-->
首页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
SpringMVC框架的helloWorld
</body>
</html>
controller层也就是servelt
/**
* 控制器(理解为 相当于WEB阶段的Servlet)
* @author Lucky
*/
@Controller
public class DefaultController {
/**
* 定义方法,相当于以前 Servlet 中 用于处理请求的方法
*/
@RequestMapping("gotoResult")
public ModelAndView gotoResult(ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date());
// 指定页面
modelAndView.setViewName("WEB-INF/jsp/result.jsp");
return modelAndView;
}
}
配置spring.xml 开启注解扫描controller层的注解
<!-- 开启SpringIOC注解扫描 -->
<context:component-scan base-package="com.zhuxu.controller"></context:component-scan>
配置SpringMvc框架的前端控制器
<!-- 配置SpringMvc框架的前端控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载SpringMVC的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 让dispatcherServlet对象随着Tomcat的启动而创建 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
结果页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>结果页面</title>
</head>
<body>
${nowDate}
</body>
</html>
第三节 SpringMVC架构
为什么我们写了 @RequestMapping
就可以找到相应的类或者方法呢?
为什么传了参数就可以自动进行封装呢?
其实都依赖于 SpringMVC 的处理器映射器、处理器适配器、视图解析器这三大组件来完成
整体流程描述:
- 用户发起请求到前端控制器 DispatcherServlet,该控制器根据
url-pattern
会过滤出哪些请求可以访问、哪些不能访问。并且会加载 springmvc.xml 配置文件。 - DispatcherServlet 会找到处理器映射器 HandlerMapping,通过 HandlerMapping 完成 url 到 controller 映射的组件,简单来说,就是将在 springmvc.xml 或注解中配置的 url 与对应的处理类找到并进行存储,用
map<url,handler>
这样的方式来存储。 - HandlerMapping 有了映射关系,并且找到 url 对应的处理器,HandlerMapping 就会将其处理器 Handler 返回,在返回前,会加上很多拦截器。
- DispatcherServlet 拿到 Handler 后,找到处理器适配器 HandlerAdapter,通过它来访问处理器,并执行处理器。
- 执行处理器
- 处理器会返回一个 ModelAndView 对象给 HandlerAdapter
- 通过 HandlerAdapter 将 ModelAndView 对象返回给 DispatcherServlet
- DispatcherServlet 请求视图解析器 ViewResolver 去进行视图解析,根据逻辑视图名解析成真正的视图 jsp,其实就是将 ModelAndView 对象中存放视图的名称进行查找,找到对应的页面形成视图对象
- 返回视图对象到前端控制器。
- 视图渲染,就是将 ModelAndView 对象中的数据放到 request 域中,用来让页面加载数据的。
- 通过第 8 步,通过名称找到了对应的页面,通过第 10 步,request 域中有了所需要的数据,那么就能够进行视图渲染了。最后将其返回即可。
1:六个组件
1.1:DispatcherServlet - 前端控制器
dispatcherServlet 是整个流程的控制中心,由它调用其它组件处理用户的请求。
dispatcherServlet 的存在降低了组件之间的耦合性。
1.2:HandlerMapping - 处理器映射器
HandlerMapping 负责根据用户请求找到 Handler 即处理器
dispatcherServlet 接收到请求路径之后,找 HandlerMapping ,根据请求路径映射找到相应的方法或者类
SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
1.3:Handler - 处理器
它就是我们开发中要编写的具体业务控制器。
由 DispatcherServlet 把用户请求转发到 Handler。由 Handler 对具体的用户请求进行处理。
1.4:HandlAdapter - 处理器适配器
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
1.5:ViewResolver - 视图解析器
ViewResolver 负责将处理结果生成 View 视图。
ViewResolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
1.6:View - 视图
SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView 等。
我们最常用的视图就是 jsp,一般情况下需要通过页面标签或页面模版技术,将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
2:定制组件
其实 springmvc 中的各个组件都是内置的,不用配置就可以
2.1:定制视图解析器
ModelAndView 中设置视图时,每次都要写前缀和后缀,可以不写吗?可以,定制视图解析器即可
在 springmvc.xml 中定制
<bean id="internalResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/"/>
<!-- 后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
2.2:定制处理器映射器
在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
使用 <mvc:annotation-driven>
会自动加载
- RequestMappingHandlerMapping (处理映射器)
- RequestMappingHandlerAdapter (处理适配器)
可用在 SpringMVC.xml 配置文件中使用 <mvc:annotation-driven>
替代注解处理器映射器和适配器的配置。
它就相当于在 xml 中配置了:
<!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <!-- HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- HadnlerExceptionResolvers -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver"></bean>
<bean class="org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver"></bean>
注意: 一般开发中,我们都需要写上此标签(虽然从入门案例中看,我们不写也行,随着课程的深入,该标签还有具体的使用场景)
明确: 我们只需要编写处理具体业务的控制器以及视图。
<mvc:annotation-driven />注解意义:提供 Controller请求转发,json自动转换等功能
<mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。配置一些 messageconverter。即解决了 @Controller 注解的使用前提配置 <context:annotation-config /> 是对包进行扫描,实现注释驱动 Bean 定义,同时将 bean 自动注入容器中使用。即解决了 @Controller 标识的类的 bean 的注入和使用。
<mvc:annotation-driven /> 会自动注册 RequestMappingHandlerMapping 与 RequestMappingHandlerAdapter 两个 Bean,这是 Spring MVC 为 @Controller 分发请求所必需的,并且提供了数据绑定支持,@NumberFormatannotation 支持,@DateTimeFormat 支持,@Valid 支持读写 XML 的支持(JAXB)和读写 JSON 的支持(默认Jackson)等功能。
我们处理响应 ajax 请求时,就使用到了对 json 的支持。
对 action 写 JUnit 单元测试时,要从 spring IOC 容器中取 DefaultAnnotationHandlerMapping 与 AnnotationMethodHandlerAdapter 两个 bean,来完成测试,取的时候要知道是 <mvc:annotation-driven /> 这一句注册的这两个 bean。
第四节 @RequestMapping 注解
用法一:
多个URL路径映射到同一个Handler(同一个方法)
Handler处理器
@RequestMapping注解用于映射请求与处理器
注解属性value,可以配置多个url
// 用法1:多个url路径映射到同一个Handler(同一个方法)
@RequestMapping(value = {"gotoResultURL","gotoResultURL2"})
public ModelAndView gotoResultURL(ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date()+"========gotoResultURL");
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
用法二:
@RequestMapping 注解作用在类上,实现对请求路径的分类管理,限定类中方法访问的前缀
@RequestMapping("default")
public class DefaultController{}
<fieldset>
<p>01_MVC入门测试用例</p>
<a href = "${pageContext.request.contextPath}/default/gotoResultURL2.do">测试</a>
</fieldset>
用法三:
method属性限定请求方法,请求的handler相同,请求方式不同进入不同方法处理
method属性限定请求方法,请求的handler相同,请求方式不同进入不同方法处理,访问的url是一样的(handler名字是一样的),但是根据不同的请求方式(get/post)进入不同的方法处理,请求的url一样,但是请求方式不一样(get/post)
/**
* url相同,但是请求方式为GET
* @RequestMapping注解属性method
*/
@RequestMapping(value = "gotoResultMethod",method = RequestMethod.GET)
public ModelAndView gotoResultMethodGet(ModelAndView modelAndView){
modelAndView.addObject( "nowDate",new Date()+"Method=GET");
modelAndView.setViewName( "index" );
return modelAndView;
/**
* url相同,但是请求方式为POST
* @RequestMapping注解属性method
*/
@RequestMapping(value = "gotoResultMethod" ,method = RequestMethod.POST)
public ModelAndView gotoResultMethodPost(ModelAndView modelAndView){
modelAndView.addobject( "nowDate",new Date()+"Method=POST");
modelAndView.setViewName( "index" );
return modelAndView;
}
用法四:
params属性限定请求参数:支持简单的表达式语法,url一样,根据携带参数的不同进入不同的方法处理
params属性限定请求参数,支持简单的表达式语法,url一样,根据携带参数的不同进入不同的方法处理,url相同,请求方式相同,请求参数不同进入不同hanIder方法处理
<fieldset>
<h4>用法4 params属性限定请求参数︰支持简单的表达式语法,url一样,根据携带参数的不同进入不同的方法处理</h4>
<a href="http://1ocalhost:8080/user/login. do?type=user">普通用户</a>
<a href="http://localhost:8080/user/login. do?type=admin">管理员</a>
<a href="http://localhost:8080/user/login. do?type=vip">VIP</a>
</fieldset>
url相同,请求方式相同,请求参数不同
@RequestMapping注解属性params
id:表示请求必须包含名为id的请求参数
演示:http://localhost:9090/user/gotoResultMethod.action?id=123
!id:表示请求不能包含名为id的请求参数
演示: http://localhost:9090/user/gotoResultMethod.action?id=123
idl=100:
表示请求包含名为param1的请求参数,但其值不能为100
演示: http://localhost:9090/user/gotoResultMethod.action?id=1123213
id!=100”,"name”}:请求必须包含名为id和name的两个请求参数,
演示: http://localhost:9090/user/gotoResultMethod.action?id=112&name=zhang3
第五节 请求参数绑定
功能一:默认支持ServletAPI
SpringMVC在方法中直接声明HttpServletRequest,HttpServletResponse,HttpSession即可使用
控制器
@Controller
@RequestMapping("params")
public class DefaultController {
// 功能一:默认支持ServletAPI
@RequestMapping("gotoParams")
public ModelAndView gotoResultURL(HttpServletRequest request, HttpServletResponse response, HttpSession session,ModelAndView modelAndView){
// 获取请求参数
String id = request.getParameter("id");
String name = request.getParameter("name");
// 封装数据
modelAndView.addObject("nowDate",new Date()+"==="+id+"===="+name);
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
}
}
请求参数
<body>
<h3>请求参数绑定</h3>
<fieldset>
<h4>功能一:默认支持ServletAPI</h4>
<a href="${pageContext.request.contextPath}/params/gotoParams.do?id=123&name=list">测试路径2</a>
</fieldset>
</body>
功能二:绑定简单的数据类型
- 基本数据类型推荐使用包装类,包装类可以为null
- 说明:对于布尔类型的参数,请求参数值为true或false。或者1或0
/**
* 绑定基本数据类型参数
* 参数的名字,和请求参数的键相同
*/
//功能2:绑定简单数据类型
//http://localhost:9090/param/sendParamsBase.action?isVip=1
@RequestMapping(i"sendParamsBase"])
public ModelAndView sendParamsBase(Boolean isVip,ModelAndView modelAndView){
modelAndView.addobject("nowDate",new Date()+"===="+ isVip);
modelAndView.setViewName("Result");
return mode1AndView;
}
// 功能二:绑定简单数据类型
@RequestMapping("gotoParamsBase")
public ModelAndView gotoParamsBase( Integer id,ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date()+"==="+id);
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
}
jsp页面
<fieldset>
<h4>功能二:绑定简单数据类型</h4>
<a href="${pageContext.request.contextPath}/params/gotoParamsBase.do?id=123&name=list">测试路径2</a>
</fieldset>
功能三:@RequestParam注解使用
当形参和传递的参数名称不一致时使用RequestParam进行手动映射,类似于MyBatis中requestMap的作用
// 功能三:RequestParam
@RequestMapping("gotoParamsParam")
public ModelAndView gotoParamsParam(@RequestParam("id") Integer ids, ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date()+"==="+ids);
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
}
<fieldset>
<h4>功能三RequestParam</h4>
<a href="${pageContext.request.contextPath}/params/gotoParamsBase.do?id=123">测试路径2</a>
</fieldset>
功能四:绑定pojo对象
- 直接形参生命pojo即可接收
- 要求:传递的参数名必须和pojo属性名对应
public class User {
private Integer id;
private String name;
private String sex;
}
// get set tonstring 省略
// 功能四:绑定pojo
@RequestMapping("gotoParamsPojo")
public ModelAndView gotoParamsPojo(User user, ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date()+"==="+user);
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
}
<fieldset>
<h4>功能四:绑定pojo对象</h4>
<a href="${pageContext.request.contextPath}/params/gotoParamsPojo.do?id=123&name=lisi">测试路径2</a>
</fieldset>
功能五:绑定pojo对象的包装类对象
- 重点在于船舱参数的命名
- pojo包装对象首先就是一个普通的pojo,就应该按照上面绑定的pojo的要求来,然后进一步处理,传参时参数名,首先应该定位到包装对象的属性名,如果不能确定数据,通过属性的方式进一步锁定即可。
/**
* 用于对 页面提交的表单所对应的实体对象
*
* entity---> 网页中表单提交的数据,所对应的JavaBean对象
* pojo ---> 对应数据库表的实体类 JavaBean对象
* @author Lucky
*/
public class QueryVo {
private User user;
@Override
public String toString() {
return "QueryVo{}";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
<fieldset>
<h4>功能五:绑定pojo对象的包装类对象</h4>
<a href="${pageContext.request.contextPath}/params/gotoParamsQueryVo.do?user.id=123&user.name=wangyi">测试路径2</a>
</fieldset>
// 功能五:绑定pojo对象的包装类对象
@RequestMapping("gotoParamsQueryVo")
public ModelAndView gotoParamsQueryVo(QueryVo queryVo, ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date()+"==="+queryVo);
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
}
功能六:绑定List集合包装pjo对象
传递绑定集合类型(List/Map),作为pojo的一个属性来传递
<fieldset>
<h4>功能六:绑定集合包装pojo对象</h4>
<form action="${pageContext.request.contextPath}/params/gotoParamsList.do" method="get">
<table>
<tr>
<th>id</th>
<th>name</th>
<th>sex</th>
</tr>
<tr>
<td><input type="text" name="userList[0].id" placeholder="请输入ID"></td>
<td><input type="text" name="userList[0].name" placeholder="请输入姓名"></td>
<td><input type="text" name="userList[0].sex" placeholder="请输入性别"></td>
</tr>
</table>
<input type="submit" value="提交">
</form>
</fieldset>
private List<User> userList;
// 功能六:绑定集合包装pojo对象
@RequestMapping("gotoParamsList")
public ModelAndView gotoParamsList(QueryVo queryVo, ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date()+"==="+queryVo);
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
}
功能七:绑定Map集合包装pojo对象
index.jsp
<fieldset>
<h4>功能七:绑定Map集合包装pojo对象</h4>
<form action="${pageContext.request.contextPath}/params/gotoParamsList.do" method="get">
<table>
<tr>
<th>id</th>
<th>name</th>
<th>sex</th>
</tr>
<tr>
<td><input type="text" name="userMap[user001].id" placeholder="请输入ID"></td>
<td><input type="text" name="userMap[user001].name" placeholder="请输入姓名"></td>
<td><input type="text" name="userMap[user001].sex" placeholder="请输入性别"></td>
</tr>
</table>
<input type="submit" value="提交">
</form>
</fieldset>
ParamsController控制器中的方法
// 功能七:绑定Map集合包装pojo对象
@RequestMapping("gotoParamsMap")
public ModelAndView gotoParamsMap(QueryVo queryVo, ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date()+"==="+queryVo);
// 指定页面
modelAndView.setViewName("result");
return modelAndView;
}
第六节 SpringMVC编码过滤器
前边的案例中你在输入框,输入一下中文试试,会发现控制台是几个 ????
随便写一个表单
<form action="encodingFilter" method="post">
<input type="text" name="name" />
<input type="submit" value="提交">
</form>
控制器
@RequestMapping(value = "encodingFilter",method = RequestMethod.POST)
public String testEncodingFilter(String name){
System.out.println(name);
return "success";
}
输入中文,查看控制台
在前端控制器 web.xml中写
<!-- 配置编码过滤器:过滤post请求 -->
<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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
但是此种方式只能拦截 POST 请求,拦截 GET 请求需要到 Tomcat 中配置
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
改为:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>
如果遇到 ajax 请求仍然乱码,把: useBodyEncodingForURI="true"
改为 URIEncoding="UTF-8"
即可。
第七节 消息头相关的两个注解 -- 了解
1:RequestHeader
作用: 用于获取请求消息头。
属性:
- value:提供消息头名称
- required:是否必须有此消息头
注: 在实际开发中一般不怎么用。
使用示例 jsp中代码:
<!-- RequestHeader注解 -->
<a href="springmvc/useRequestHeader">获取请求消息头</a>
控制器中代码:
/**
* RequestHeader注解
* @param user
* @return
*/
@RequestMapping("/useRequestHeader")
public String useRequestHeader(
@RequestHeader(value="Accept-Language", required=false)
String requestHeader){
System.out.println(requestHeader);
return "success";
}
2:CookieValue
作用: 用于把指定 cookie 名称的值传入控制器方法参数。
属性:
- value:指定 cookie 的名称。
- required:是否必须有此 cookie。
<!-- CookieValue注解 -->
<a href="springmvc/useCookieValue">绑定cookie的值</a>
控制器中的代码:
/**
* Cookie注解注解
* @param user
* @return
*/
@RequestMapping("/useCookieValue")
public String useCookieValue(
@CookieValue(value="JSESSIONID",required=false)
String cookieValue){
System.out.println(cookieValue);
return "success";
}