1.SpringMVC 概述
Spring 为 展 现层提供的基于 提供的基于 MVC 设计 理念的优秀的
Web 框架,是 目前 最主流的 的 MVC 框架 之一
Spring3.0 后全面超越 Struts2,成为最 优秀的的 MVC 框架
Spring MVC 通 通 过套 MVC 注解,让 POJO 成为处理请 求的控制器,而无须实现任何接口。
支持 REST 风 格的 的 URL 请 求
采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性
2.HelloWorld
步骤:
-加入 jar 包
commons-logging-1.1.3.jar –
spring-aop-4.0.0.RELEASE.jar –
spring-beans-4.0.0.RELEASE.jar –
spring-context-4.0.0.RELEASE.jar –
spring-core-4.0.0.RELEASE.jar –
spring-expression-4.0.0.RELEASE.jar –
spring-web-4.0.0.RELEASE.jar –
spring-webmvc-4.0.0.RELEASE.jar
-在 web.xml 中配置 DispatcherServlet
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <!-- html中form表单只支持GET与POST请求,而DELETE、PUT等method并不支持, spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求。
--> <!-- 配置 org.springframework.web.filter.HiddenHttpMethodFilter --> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置 DispatcherServlet --> <!-- The front controller of this Spring Web application, responsible for handling all application requests --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置DispatcherServlet 的初始化参数 --> <!-- <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> --> <!-- 实际上也可以不通过 contextConfigLocation 来配置SpringMVC 的配置文件 而使用默认的配置文件:/WEB-INF/<servlet-name>-servlet.xml --> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-加入 Spring MVC 的配置文件
-编写处理请求的处理器,并标识为处理器
-编写视图
springDispatcherServlet-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!--配置自动扫描的包 --> <context:component-scan base-package="com.aff.springmvc"></context:component-scan> <!--配置视图 BeanNameViewResolver" 解析器, 使用视图的名字来解析视图 通过 order属性来定义视图解析器优先级, order 值越小, 优先级越高 --> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="100"></property> </bean> <!-- 配置视图解析器:如何把 handler 方法返回值解析为实际的物理视图 这个视图解析器优先级最低默认为MAXInteger order越大优先级越 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--配置国际化资源文件 --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"></property> </bean> <!--配置直接转发的页面 --> <mvc:view-controller path="/success" view-name="success"/> <!-- 在实际开发中通常都配置 mvc:annotation-driven 标签--> <mvc:annotation-driven></mvc:annotation-driven> </beans>
HelloWorld.java
package com.aff.springmvc.handlers; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorld { /** * 1. 使用 @RequestMapping 注解来映射请求的URL * 2.返回值会通过视图解析器解析为实际到位物理视图,对于 InternalResourceViewResolver 视图解析器 * 通过 prefix + returnVal + 后缀(suffix) 这样的方式得到实际的物理视图, 然后转发操作 * * /WEB-INF/views/succcess.jsp * @return */ @RequestMapping("/helloworld") public String hello() { System.out.println("hello world"); return "success"; } }
3.内容概要
-使用 @RequestMapping 映射 映射 请 求
Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求
在控制器的 类 定 义 及方法定义处都可标注 •
@RequestMapping
类 定 义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
方法处 处:提供进一步的细分映射信息。相对于类定义处的 URL。若
类定义处未标注 @RequestMapping,则方法处标记的 URL 相对于WEB 应用的根目录
DispatcherServlet 截获请求后,就通过控制器上
@RequestMapping 提供的映射信息确定请求所对应的处理方法。
-映射请求参数 & 请求头
①RequestMapping 除了可以使用请 请求 求 URL 映射请求外,还 可以使用 请 求方法、请 求参数及 请求头映射 请 求
②@RequestMapping 的 value、method、params 及 heads 分别表示 请求 求 URL请 求方法、 请 求参数及 请 求 头的映射条件,
他们之间是 与的关系, 联 合使用多个条件可 让请 求映射更加精 确化。
③params 和 headers 支持 简单 的表 达 式:
param1: 表示请求必须包含名为 param1 的请求参数
!param1: 表示请求不能包含名为 param1 的请求参数
param1 != value1: 表示请求包含名为 param1 的请求参数,但其值 不能为 value1
{“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1
④使用 @RequestMapping 映射请求
Ant 风 风 格 资源地址支持 源地址支持 3 种 种 匹配符:
?:匹配文件名中的一个字符
*:匹配文件名中的任意字符
**:** 匹配多层路径
@RequestMapping 还 支持 Ant 风格的 URL:
/user/*/createUser: 匹配
/user/aaa/createUser、/user/bbb/createUser 等 URL
/user/**/createUser: 匹配
/user/createUser、/user/aaa/bbb/createUser 等 URL
/user/createUser??: 匹配
/user/createUseraa、/user/createUserbb 等 URL
⑤@PathVariable 映射 URL 绑定的占位符
带占位符的 占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
通过 过 @PathVariable 可以将 URL 中占位符参数 中占位符参数 绑 定到控 •制器 处 理方法的入参中 中:URL 中的 {xxx} 占位符可以通过
@PathVariable("xxx") 绑定到操作方法的入参中。
⑥REST
REST:即 Representational State Transfer。( ( 资 源)表 现层 状 态转 化。 是目前 •
最流行的一 种 互 联 网 软 件架 构。它结构清晰、符合标准、易于理解、扩展方便,
所以正得到越来越多网站的采用
资源( 源(Resources) ): 网 络 上的一个 实 体,或者 说 是网 络 上的一个具体信息。它 •
可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。
可以用一个URI(统一资源定位符)指向它,每 每 种资 源 对应 一个特定的 的 URI 。要
获取这个资源,访问它的URI就可以,因此 URI 即 即 为 每 一个 资 源 的独一无二 的 识
别 符。
表 现层( (Representation) ): 把 资 源具体 呈 现 出来的形式 ,叫做它 的表 现层 •
( (Representation )。比如,文本可以用 txt 格式表现,也可以用 HTML 格
式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
状 态转化( 化(State Transfer) ):每发出一个请求,就代表了客户端和服务器的一 •
次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器
端。因此, 如果客 户 端想要操作服 务 器,必 须 通 过 某 种 手段, 让 服 务 器端 发生 生“
状 态转化 化” (State Transfer)。而 )。而 这种转 化是建立在表 现层 之上的,所以就是 就是 “
表 现 层 状 态 转化 化” 。具体说,就是 HTTP 协议 协议 里面,四个表示操作方式的 动
词: :GET 、POST 、PUT 、DELETE。它 。它 们 分 别对应 四 种基本操作: 基本操作:GET 用来 用来 获
取 资源, 源,POST 用来 用来 新建 资源, 源,PUT 用来 用来 更新 资源, 源,DELETE 用来 用来 删 除 资 源。
示例:
/order/1 HTTP GET :得到 id = 1 的 order
/order/1 HTTP DELETE :删除 id = 1的 order
/order/1 HTTP PUT:更新id = 1的 order
/order HTTP POST:新增 order –
HiddenHttpMethodFilter:浏览器 form 表单只支持 GET 与 POST 请求,而DELETE、PUT 等 method 并不支持,
Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与DELETE 请求。
⑦使用 @RequestParam 绑定请求参数值
在处理方法入参处使用 @RequestParam 可以把 请求参数 传递给请 求方法
value:参数名
required:是否必须。默认为 true, 表示请求参数中必须包含对应 的参数,若不存在,将抛出异常
⑧使用 @RequestHeader 绑定请求报头的属性值
请求头包含了若干个属性,服务器可据此获知客户端的信息,
通过 过 @RequestHeader 即可将 即可将 请 求 头 中的属性 值绑定到 处
⑨使用 @CookieValue 绑定请求中的 Cookie 值
@CookieValue 可让处理方法入参绑定某个 Cookie 值
⑩使用 POJO 对象绑定请求参数值
Spring MVC 会按 请求参数名和 求参数名和 POJO 属性名 属性名 进 行自 动 匹 配,自 动为该对 象填充属性 值。
支持 级联 属性。如:dept.deptId、dept.address.tel 等
⑪ 使用 Servlet API 作 为入参
MVC 的 Handler 方法可以接受哪些 ServletAPI 类型的参数
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
-处理模型数据
Spring MVC 提供了以下几种途径输出模型数据:
ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据
Map 及 Model: 入参为 org.springframework.ui.Model 、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,
Map中的数据会自动添加到模型中。
@SessionAttributes: 将模型中的某个属性暂存到 HttpSession 中,以便多个请求之间可以共享这个属性
@ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中
Map 及 Model
Spring MVC 在内部使用了一个 •org.springframework.ui.Model 接口存储模型数据
具体步骤 •
Spring MVC 在 在 调 用方法前会 创 建一个 隐 含的模型 对 象作 为 模型数据的存 储 容器
如果方法的入参为 为 Map 或 Model 类 型,Spring MVC 会将隐含模型的引用传递给这些入参。
在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据
@SessionAttributes
若希望在多个 请 求之 间 共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes, Spring MVC将在模型中对应的属性暂存到 HttpSession 中。
@SessionAttributes 除了可以通过 属性名指定需要放到会 话中的属性外,还可以通过模型属性的 对 象 类 型指定哪些模型属性需要放到会话中
@SessionAttributes(types=User.class) 会将隐含模型中所有类型 为 User.class 的属性添加到会话中。
@SessionAttributes(value={“user1”, “user2”})
@SessionAttributes(types={User.class, Dept.class})
@SessionAttributes(value={“user1”, “user2”}, types={Dept.class})
@ModelAttribute
在方法定 义上使用 @ModelAttribute注解: Spring MVC 在调用目标处理方法前,会先逐个调用在方法 级上标注了注 了 @ModelAttribute 的方法。
在方法的 入参前使用 @ModelAttribute 注解 :
可以从 隐 含 对 象中 获 取 隐 含的模型数据中 获 取 对 象,再将 请 求参数 绑 定 到 对 象中,再 传 入入参
将 方法入参 对 象添加到模型中
由@SessionAttributes引发的异常
org.springframework.web.HttpSessionRequiredException:Session attribute 'user' required - not found in session
如果在处理类定义处标注了@SessionAttributes(“xxx”),则 尝试从会话中获取该属性,并将其赋给该入参,然后再用
请求消息填充该入参对象。 如果在会 话 中找不到 对应 的属性, 则 抛出 出 HttpSessionRequiredException 异 常
如何避免@SessionAttributes引发的异常
该 方法会往 隐 含模型中添加一个名为 为user的模型属性
-视图和视图解析器
Spring MVC如何解析视图
请求处理方法执行完成后,最终返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的
处理方法,Spring MVC 也会在内部将它 也会在内部将它 们装配成一个 装配成一个ModelAndView 对 象,它包含了逻辑名和模型对象的视图
Spring MVC 借助 视图解析器 解析器(ViewResolver)得到最终 的视图对象(View),最终的视图可以是 JSP ,也可能是Excel、JFreeChart 等各种表现形式的视图
对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦
视图对象由 视图 解析器 负责实例化。由于视图是 无状 态的,所以他们不会有 线 程安全的问题
常用的视图实现类
视图解析器
SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中 配置一 种 或多 种 解析策略, 并指定他 们 之 间 的先后 顺 序。
每一种映射策略对应一个具体的视图解析器实现类。
视图解析器的作用比较单一:将逻辑视图解析为一个具体 的视图对象。所有的视图解析器都必须实现 ViewResolver 接口:
常用的视图解析器实现类
程序员可以选择一种视图解析器或混用多种视图解析器 •每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,
可以通过 过 order 属性指定解析器的 属性指定解析器的 优 先 顺 序,order 小 越小 优 先 级 越高。
SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解 析,直到解析成功并返回视图对象,否则将抛出 ServletException 异常
InternalResourceViewResolver
JSP 是最常见的视图技术,可以使用 InternalResourceViewResolver 作为视图解析器
若项目中使用了 JSTL,则 SpringMVC 会自动把视图由 •InternalResourceView 转为 JstlView
若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中 配置国 际 化 资源文件
若希望直接响应通过 SpringMVC 渲染的页面,可以使用 mvc:view-controller 标签实现
Excel 视图
若希望使用 Excel 展示数据列表,仅需要扩展 SpringMVC 提供的 AbstractExcelView 或AbstractJExcel View 即可。实现 buildExcelDocument ()方法,
在方法中使用模型数据对象构建 Excel 文档就可以了。
AbstractExcelView 基于 POI API,而 AbstractJExcelView 是基于 JExcelAPI 的。
视图对象需要配置 象需要配置 IOC 容器中的一个 Bean ,使用 BeanNameViewResolver 作 作 为视图 解析器即可
若希望直接在浏览器中直接下载 Excel 文档,则可以设置 响应头 Content-Disposition 的值为attachment;filename=xxx.xls
关于重定向
一般情况下,控制器方法返回字符串类型的值会被当成逻 辑视图名处理
如果返回的字符串中带 forward: 或 redirect: 前缀 时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理
redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
forward:success.jsp:会完成一个到 success.jsp 的转发操作
测试代码
SpringMVCTest.java
package com.aff.springmvc.handlers; import java.io.IOException; import java.io.Writer; import java.util.Arrays; import java.util.Date; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.servlet.ModelAndView; import com.aff.springmvc.entities.User; @SessionAttributes(value={"user"},types={String.class}) @RequestMapping("/springmvc") @Controller public class SpringMVCTest { private static final String SUCCESS = "success"; //重定向到index.jsp @RequestMapping("/testRedirect") public String testRedirect(){ System.out.println("testRedirect"); return "redirect:/index.jsp"; } //自定义视图 @RequestMapping("/testView") public String testView(){ System.out.println("testView"); return "helloView"; } @RequestMapping("/testViewAndViewResolver") public String testViewAndViewResolver(){ System.out.println("testViewAndViewResolver:"); return SUCCESS; } /** * 1.有 @ModelAttribute 标记的方法,会在每个目标方法执行之前被SpringMVC调用 * * 2. @ModelAttribute 注解 也可以修饰 目标方法POJO 类型的入参, 其value 属性值有如下的作用 * ① SpringMVC 会使用value 属性值 在implicitModel 中查找对应对象,
若存在则会直接存入到目标方法的入参中 * ② SpringMVC 会以value 为key pojo 类型的对象为value , 存入到request 中 */ @ModelAttribute public void getUser(@RequestParam(value="id",required=false) Integer id ,Map<String, Object> map){ System.out.println("modelAttribute method"); if (id !=null) { //模拟从数据库中获取对象 User us = new User(1, "Tom", "123456", "tom@qq.com", 12); System.out.println("从数据库中获取一个对象:"+us); //把获取的-对象放到map中 //map.put("user", us); map.put("abc", us); } } /** * 运行流程: * 1. 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象, 把对象放掉map中,键为user * 2. SpringMVC 从Map中取出User对象 , 并把表单的请求参数赋给User 对象的对应属性 * 3. SpringMVC 把上述对象传入目标方法的参数中 * * 注意:在@ModelAttribute 修饰的方法中, * 放入到Map时的键需要和目标方法入参类型的参数的第一个字母小写的字符串一致 * * * 源代码分析流程 * 1.调用 @ModelAttribute 修饰的方法, 实际上把@ModelAttribute 方法中的Map 中的数据放到了
implicitModel 中 * 2.解析请求处理器的目标参数, 实际该目标参数来自于 WebDataBinder对象的 target 属性 * 1)创建 WebDataBinder 对象: * ① 确定 objectName 属性: 若传入的attrName 属性值为 "" ,
则 objectName 为类名第一个字母的小写 * 注意: attrName , 若目标方法的POJO属性使用了 @ModelAttribute
来修饰吗则attrName 值为@ModelAttribute 的 value 属性值 * * ② 确定 target 属性 * >在implicitModel查找 attrName 对应的属性值,若存在,ok * >不存在, 则验证当前handler是否使用了 @SssionAttributes 进行修饰
若使用了,则尝试从Session中获取attrName 所对应的属性值 * 若session 中没有对应的属性值, 则抛出异常 * >若handler没有 使用@SessionAttributes 进行修饰,
或@SessionAttributes 中没有使用value值指定的key * 和attrName 相匹配, 则通过哦反射创建POJO对象 * 2)SpringMVC 把表单的请求参数 赋值给了 WebDataBinder 的target 对应的属性 * 3)SpringMVC 会把WebDataBinder 的attrName 和target 给implicitModel,进而传到request域对象中 * 4)把 WebDataBinder 的target 作为 参数传递给你目标方法的入参 * */ //先找到数据库中的值,表单中没有password的值使用原先查到的值, //达到password没有被修改 其他的属性的值被修改的目的 @RequestMapping("/testModelAttribute") public String testModelAttribute(@ModelAttribute("abc") User user){ System.out.println("修改:"+user); return SUCCESS; } /** * 在控制器上面添加@SessionAttributes(value="user") 就会把user放到session中 *SessionAttributes 除了可以通过 属性名指定需要放到会话中的属性外(实际上使用的是value 属性值), * 还可以通过模型属性的 对 象 类 型指定哪些模型属性需要放到会话中(实际上使用的是types 属性值) * * 注意: 该注解只能放到类的上面, 而不能修饰方法 */ @RequestMapping("/testSessionAttributes") public String testSessionAttributes(Map<String, Object> map){ User us = new User("Tyom", "12345", "hxn!com", 13); map.put("user", us); map.put("fi", "hxl"); return SUCCESS; } /** * 目标方法 可以添加 Map(实际上可以是Model类型或者M odelMap类型)类型的参数 * */ @RequestMapping("/testMap") public String testMap(Map<String, Object> map){ System.out.println(map.getClass().getName()); //org.springframework.validation.support.BindingAwareModelMap map.put("name", Arrays.asList("Tomn","jack","hxl")); return SUCCESS; } /** * 目标方法的返回值 可以是ModelAndView 类型 * 其中 可以包含 视图和模型信息 * SpringMVC 会把ModelAndView 中数据放到reuqest域对象中 */ @RequestMapping("/testModelAndView") public ModelAndView testModleAndView(){ String viewName= SUCCESS; ModelAndView modelAndView = new ModelAndView(viewName); //添加模型数据到ModelAndView 中 modelAndView.addObject("time", new Date()); return modelAndView; } /** * 可以使用 Servlet 原生的API 作为目标方法的参数,具体支持一下类型 HttpServletRequest HttpServletResponse HttpSession java.security.Principal Locale InputStream OutputStream Reader Writer * @throws IOException * */ @RequestMapping("/testServletApi") public void testServletApi( HttpServletRequest request,HttpServletResponse response,Writer out) throws IOException { System.out.println("testServletApi,"+request+","+response); out.write("this is hxl"); //return SUCCESS; } /** * Spring MVC 会按 请求参数名和 求参数名和 POJO 属性名 属性名 进 行自 动 匹 配, * 自 动为该对 象填充属性 值。 支持 级联 属性。 */ @RequestMapping("/testPoJo") public String testPoJo(User user){ System.out.println("testPoJo:"+user); return SUCCESS; //testPoJo:User [username=mhxl, password=123456, email=@hxl.com, age=12, address=Address [province=anhui, city=hei]] } /** * 了解: * @CookieValue:映射一个Cookie 值,属性同 @RequestParam * */ @RequestMapping("/testCookieValue") public String testCookieValue(@CookieValue(value="JSESSIONID") String sessionId){ System.out.println("@CookieValue :sessionId::"+sessionId); return SUCCESS; //@CookieValue :sessionId::792148022E90573E6223FB326E70584A } /** * 了解 * 映射请求头信息 * @RequestHeader */ @RequestMapping("/testRequestHeader") public String testRequestHeader(@RequestHeader(value="Accept-Language") String al){ System.out.println("testRequestHeader,Accept-Language: "+al ); return SUCCESS; } /** * * @RequestParam 来映射请求参数 * value 值 即请求参数的参数名 * required 该值是否必须 * defaultValue 请求参数的默认值 */ @RequestMapping(value="/testRequestParam") public String testRestParam( @RequestParam(value="username") String un,@RequestParam(value="age",required=false,defaultValue="0") Integer age){ System.out.println("testRestParam, username:"+un+", age:"+age); return SUCCESS; } /** * Rest 风格的URL * 以CRUD 为例 * 新增:/order POST * 修改:/order/1 PUT update?id=1 * 获取:/order/1 GET get?id=1 * 删除:/order/1 DELETE delete?id=1 * *如何发送PUT 请求 和DELETE请求? *1.需要 配置 HiddenHttpMethodFilter *2.需要发送POST 请求 *3.需要发送POST 请求时携带一个name="_method" 的隐藏域,值为DELETE 或PUT * * 在SpringMVC的目录方法中如何 得到id? * 使用 @PathVariable 注解 * */ //put 和delete需要 在success页面中 设置 isErrorPage="true" //PUT请求 更新id = 1的 order @RequestMapping(value="/testRest/{id}",method = RequestMethod.PUT) public String testRestPut(@PathVariable Integer id){ System.out.println("testRest PUT:"+id); return SUCCESS; } //DELETE请求 :删除 id = 1的 order @RequestMapping(value="/testRest/{id}",method = RequestMethod.DELETE) public String testRestDelete(@PathVariable Integer id){ System.out.println("testRest Delete:"+id); return SUCCESS; } //POST请求 新增 order @RequestMapping(value="/testRest",method = RequestMethod.POST) public String testRestPost(){ System.out.println("testRest POST"); return SUCCESS; } //GET请求 得到 id = 1 的 order @RequestMapping(value="/testRest/{id}",method = RequestMethod.GET) public String testRestGet(@PathVariable Integer id){ System.out.println("testRest GET:"+id); return SUCCESS; } /** * 可以映射URL 中的占位符到目标方法的参数中 * @param id * @return */ @RequestMapping("/testPathVariable/{id}") public String testPathVariable(@PathVariable("id") Integer id){ System.out.println("testPathVariable:"+ id); return SUCCESS; } /** Ant 风 格 资源地址支持 源地址支持 3 种匹配符: ?:匹配文件名中的一个字符 – *:匹配文件名中的任意字符 – **:** 匹配多层路径 */ @RequestMapping("/testAntPath/*/abc") public String testAntPath(){ System.out.println("testAntPath"); return SUCCESS; } /** * 了解:可以使用 param 换个headers 来更加精确的映射请求, params 和headers 支持简单表达式 * * @return */ @RequestMapping(value ="testParamAndHeaders" ,params={"username","age!=10"},headers = {"Accept-Language=zh-CN,zh;q=0.9"}) public String testParamAndHeaders(){ System.out.println("testParamAndHeaders"); return SUCCESS; } /** * 常用: method属性来指定请求方式 */ @RequestMapping(value ="/testMethod",method=RequestMethod.POST) public String testMethod(){ System.out.println("testMethod"); return SUCCESS; } /** * 1.@RequestMapping 除了修饰方法, 还可以修饰类 * 2. * ①类定义 处:提供初步的请求映射信息。相对于 WEB 应用的根目录 * ②方法处 处:提供进一步的细分映射信息。相对于类定义处的 URL。若类定义处未标注 @RequestMapping,
则方法处标记的 URL 相对于WEB 应用的根目录 *@return */ @RequestMapping("/testReuestMapping") public String testRequestMapping() { System.out.println("test RequestMapping "); return SUCCESS; } }
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <br><br> <a href="springmvc/testRedirect">testRedirect</a> <br><br> <a href="springmvc/testView">TestView</a> <br><br> <a href="springmvc/testViewAndViewResolver">Test ViewAndViewResolver</a> <!--模拟修改操作 1. 原始数据为: 1,Tom,123456,tom@qq.com,12 2.密码不能被修改 3.表单回显, 模拟操作直接在表单填写对象的属性值 --> <br><br> <form action="springmvc/testModelAttribute" method="post"> <input type="hidden" name="id" value="1"/> <br> username:<input type="text" name="username" value="Tom"/> <br> <!--还有个password 没赋值 使用数据库中查出的值 --> email:<input type="text" name="email" value="tom@qq.com"/> <br> age:<input type="text" name="age" value="13"/> <br> <input type="submit" value="Submit"> </form> <br><br> <a href="springmvc/testSessionAttributes">Test SessionAttributes</a> <br><br> <a href="springmvc/testMap">test Map</a> <br><br> <a href="springmvc/testModelAndView">testModelAndView</a> <br><br> <a href="springmvc/testServletApi">test ServletApi</a> <br><br> <form action="springmvc/testPoJo" method="post"> username:<input type="text" name="username"/> <br> password:<input type="password" name="password"/> <br> email<input type="text" name="email"> <br> age:<input type="text" name="age"/> <br> City:<input type="text" name="address.city"/> <br> Province:<input type="text" name="address.province"/> <br> <input type="submit" value="Sumit"/> </form> <br><br> <a href="springmvc/testCookieValue"> test CookieValue</a> <br><br> <a href="springmvc/testRequestHeader"> test RequestHeader</a> <br><br> <a href="springmvc/testRequestParam?username=hxl&age=13">test RequestParam</a> <br><br> <!--PUT --> <!--Put 和delete需要 在success页面中 设置 isErrorPage="true" --> <form action="springmvc/testRest/1" method="post"> <input type="hidden" name="_method" value="PUT"/> <input type="submit" value="TestRest PUT"/> </form> <br><br> <!-- DELETE --> <form action="springmvc/testRest/1" method="post"> <input type="hidden" name="_method" value="DELETE"/> <input type="submit" value="TestRest DELETE"/> </form> <br><br> <!-- POST --> <form action="springmvc/testRest" method="post"> <input type="submit" value="TestRest POST"/> </form> <br><br> <!-- GET --> <a href="springmvc/testRest/1">Test Rest Get</a> <br><br> <!-- 可以映射URL 中的占位符到目标方法的参数中 --> <a href="springmvc/testPathVariable/1">Test PathVariable</a> <!-- Ant 风 格 资源地址支持 源地址支持 3 种匹配符: --> <br><br> <a href="springmvc/testAntPath/asdfadffasfdsfas/abc">TestAntPath</a> <br><br> <!-- 为啥在谷歌浏览器可以跑起来,在ie跑不起来 警告: No matching handler method found for servlet request: path '/springmvc/testParamAndHeaders', method 'POST', parameters map['username' -> array<String>['hxl'], 'age' -> array<String>['19']] --> <form action="springmvc/testParamAndHeaders?username=hxl&age=19" method="post"> <input type="submit" value="TestParamAndHeaders"/> </form> <br><br> <a href="springmvc/testParamAndHeaders?username=hxl&age=19">TestParamAndHeaders </a> <br><br> <form action="springmvc/testMethod" method="post"> <input type="submit" value="Method"/> </form> <!-- a 标签为get 请求 ,控制层为post请求 ,运行不了 ,应该为表单的post请求--> <br><br> <a href="springmvc/testMethod">Test Method</a> <br><br> <a href="springmvc/testReuestMapping">Test RequestMapping</a> <br><br> <a href="helloworld">Hello World</a> </body> </html>
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isErrorPage="true"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h2>Success Page</h2> time:${ requestScope.time} <br> names: ${ requestScope.name } <br> request user: ${requestScope.user } <br><br> session user: ${sessionScope.user } <br><br> request fi: ${requestScope.fi } <br><br> session fi: ${sessionScope.fi } <br><br> <fmt:message key="i18n.username"></fmt:message> <br><br> <fmt:message key="i18n.password"></fmt:message> </body> </html>
HelloView.java
package com.aff.springmvc.views; import java.util.Date; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.View; @Component public class HelloView implements View { @Override public String getContentType() { return "text/html"; } @Override public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { response.getWriter().print("hello view ,time:" + new Date()); } }
i18n_en_US.properties
i18n.username=Username
i18n.password=Password
i18n_zh_CN.properties
i18n.username=u7528u6237u540D
i18n.password=u5BC6u7801
Address.java
package com.aff.springmvc.entities; public class Address { private String province; private String city; public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "Address [province=" + province + ", city=" + city + "]"; } }
User.java
package com.aff.springmvc.entities; public class User { private Integer id; private String username; private String password; private String email; private int age; private Address address; public User(String username, String password, String email, int age) { super(); this.username = username; this.password = password; this.email = email; this.age = age; } public User(Integer id, String username, String password, String email, int age) { super(); this.id = id; this.username = username; this.password = password; this.email = email; this.age = age; } public User() { super(); } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + ", age=" + age + "]"; } }
目录