1、SpringMVC的概述:
• Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一
• Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架
• Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口。
• 支持 REST 风格的 URL 请求
• 采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性
2、第一个Hellow
1、步骤:
– 加入 jar 包 – 在 web.xml 中配置 DispatcherServlet
– 加入 Spring MVC 的配置文件
– 编写处理请求的处理器,并标识为处理器
– 编写视图
1.1、jar包:
1.2、配置 web.xml,spring-mvc.xml:
1.2.1、配置 DispatcherServlet(web.xml) :
DispatcherServlet 默认加载 /WEB-INF/
.xml 的 Spring 配置文件, 启动 WEB 层 的 Spring 容器。可以通过 contextConfigLocation 初始化参数自定义配置文件的位置和名称
springmvc
org.springframework.web.servlet.DispatcherServlet
springmvc
*.action
配置详解:
1.2.2、配置自动扫描的包(spring-mvc.xml):
名称空间补充:
1.2.3、配置视图解析器:
视图名称解析器:将视图逻辑名解析为: /WEB-INF/pages/
.jsp
1.3、创建请求处理器类:
@Controller//此注解将类标记为控制层
public class HelloWorld {
@RequestMapping("/hello")//此注解可映射方法或者类为url
public String hello() {
System.out.println ("helloworld...");
return "success";
}
}
对应的view:
1.4、手绘流程图:
3、@RequestMapping 映射请求
1.1、概述:
1、 Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求
2、 在控制器的类定义及方法定义处都可标注 :
@RequestMapping
– 类定义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
– 方法处:提供进一步的细分映射信息。相对于类定义处的 URL。
若类定义处未标注 @RequestMapping,则方法处标记的 URL 相对于WEB 应用的根目录
3、 DispatcherServlet 截获请求后,就通过控制器上
@RequestMapping 提供的映射信息确定请求所对应的处理方法。
2、使用@RequestMappiing示例:
@Controller//此注解将类标记为控制层
@RequestMapping("/hello")//限定所有请求,部署的根路径
public class HelloWorld {
@RequestMapping("/SpringMVC")//可定义多个方法,加上注解来处理
public String hello() {
System.out.println ("helloworld...");
return "success";
}
}
3、映射请求参数、请求方法或请求头:
3.1、标准的请求头:
3.2、@RequestMapping 除了可以使用请求 URL 映射请求外,还可以使用请求方法、请求参数及请求头映射请求
3.3、@RequestMapping 的 value、method、params 及 heads 分别表示请求 URL、请求方法、请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可让请求映射更加精确化。
3.4、params 和 headers支持简单的表达式:
能进入的访问地址:http://localhost:8081/mvc/testParamsAndHeaders?username&age=1 (请求头Accept-Language=en-US,zh;q=0.8)
@RequestMapping(value = "testParamsAndHeaders", params = { "username",
"age!=10" }, headers = { "Accept-Language=en-US,zh;q=0.8" })
public String testParamsAndHeaders() {
System.out.println("testParamsAndHeaders");
return SUCCESS;
}
4、@RequestMapping 映射请求支持的风格:
案例:
访问地址:http://localhost:8081/mvc/testAntPath/xxxxxsa/abc
@RequestMapping(value = "testAntPath/*/abc")
public String testAntPath()
{
System.out.println ("testAntPath " );
return SUCCESS;
}
5、@PathVariable 映射 URL 绑定的占位符
概述:
1、 带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义
2、 通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过 @PathVariable("xxx") 绑定到操作方法的入参中。
访问地址:http://localhost:8081/mvc/testPathVariable/16
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("testPathVariable: " + id);
return SUCCESS;
}
6、Rest风格:
案例:
@RequestMapping(value = "testParamsAndHeaders", params = { "username",
"age!=10" }, headers = { "Accept-Language=en-US,zh;q=0.8" })
public String testParamsAndHeaders() {
System.out.println("testParamsAndHeaders");
return SUCCESS;
}
正确访问地址:
RestTest.java
@Controller
@RequestMapping("springmvc")
public class RestTest {
@RequestMapping(value = "testRest", method = RequestMethod.POST)
public String hello1() {
System.out.println ("当前是添加操作");
return "success";
}
@RequestMapping(value = "testRest/{id}", method = RequestMethod.DELETE)
public String hello2(@PathVariable Integer id) {
System.out.println ("当前是删除操作,得到的id:"+id);
return "success";
}
@RequestMapping(value = "testRest/{id}", method = RequestMethod.PUT)
public String hello3(@PathVariable Integer id) {
System.out.println ("当前是更新操作,得到的id:"+id);
return "success";
}
@RequestMapping(value = "testRest/{id}", method = RequestMethod.GET)
public String hello4(@PathVariable Integer id) {
System.out.println ("当前是查询操作,得到的id:"+id);
return "success";
}
}
index.jsp
<%--注: .action 是配置了后缀拦截--%>
查询操作
前提:在web.xml上配置Rest请求转换:
HiddenHttpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter
HiddenHttpMethodFilter
/*
注意:此处可能出现jsp不支持post,请求头加上isErrorPage="true",默认为false
4、映射请求参数 & 请求头
1、概述:
2、@RequestParam 绑定请求参数值
• 在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法
– value:参数名
– required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
测试地址:http://localhost:8081/mvc/testRequestParam?username=大根
@RequestMapping("testRequestParam")
public String testRequestParam(@RequestParam(value = "username") String name,
@RequestParam(value = "age",required = false,defaultValue = "0") int age){
System.out.println ("第一个参数值:"+name+",第二个无传入,默认值:"+age );
return SUCCESS;
}
3、@RequestHeader 绑定请求报头的属性值
请求头包含了若干个属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将请求头中的属性值绑定到处理方法的入参中
测试地址:http://localhost:8081/mvc/testRequestHeader
@RequestMapping("testRequestHeader")
public String testRequestHeader(
@RequestHeader("Accept-Language") String al )
{
System.out.println ("请求头中Accept-Language值为:"+al );
return SUCCESS;
}
4、@CookieValue 绑定请求中的 Cookie 值
@CookieValue 可让处理方法入参绑定某个 Cookie 值
测试地址:http://localhost:8081/mvc/testCookieValue
@RequestMapping("testCookieValue")
public String testCookieValue(
@CookieValue("JSESSIONID") String sessionId )
{
System.out.println ("Cookie中Session的 ID:"+sessionId );
return SUCCESS;
}
5、POJO 对象绑定请求参数值
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配,自动为该对象填充属性值。支持级联属性。
如:dept.deptId、dept.address.tel 等
测试地址:http://localhost:8081/mvc/testPojo?uid=2&uname=%E5%A4%A7%E6%A0%B9&age=11
@RequestMapping("testPojo")
public String testPojo(User user)
{
System.out.println ("用户的对象的属性值:"+user );
return SUCCESS;
}
6、Servlet API 作为入参
测试地址:http://localhost:8081/mvc/testServletApi
/**
* HttpServletRequest
* HttpServletResponse
* HttpSession
* java.security.Principal
* Locale InputStream
* OutputStream
* Reader
* Writer
*
* @return
*/
@RequestMapping("testServletApi")
public void testServletApi(HttpServletRequest req, HttpServletResponse resp, Writer out)
throws IOException {
System.out.println ("testServletApi:"+req+resp);
out.write ("hello kk");
//return SUCCESS;
}
5、处理模型数据
概:
Spring MVC 提供了以下几种途径输出模型数据:
– ModelAndView: 处理方法返回值类型为 ModelAndView时, 方法体即可通过该对象添加模型数据
– Map 及 Model: 入参为:org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
– @SessionAttributes: 将模型中的某个属性暂存到HttpSession 中,以便多个请求之间可以共享这个属性
– @ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中
1、ModelAndView:
1.1、 控制器处理方法的返回值如果为 ModelAndView, 则其既包含视图信息,也包含模型数据信息。
1.2、 添加模型数据:
– MoelAndView addObject(String attributeName, Object attributeValue)
– ModelAndView addAllObject(MapmodelMap)
1.3、 设置视图: – void setView(View view) – void setViewName(String viewName)j
@RequestMapping("testModelAndView")
public ModelAndView testModelAndView() {
String viewName = SUCCESS;
ModelAndView modelAndView = new ModelAndView (viewName);
modelAndView.addObject ("time",new Date ());
return modelAndView;
}
----------------------------------------------------------------------------------------------------------------------
jsp页面:
Time: ${requestScope.time}
map: ${requestScope.names}
2、Map及Model
概:
@RequestMapping("testMap")
public String testMap(Map map) {
//实际上也可以是Model类型或者ModelMap
//org.springframework.validation.support.BindingAwareModelMap
System.out.println (map.getClass ().getName () );
map.put ("names", Arrays.asList ("Tom","kk","mike"));
System.out.println (map );
return SUCCESS;
}
----------------------------------------------------------------------------------------------------------------------
jsp页面:
Time: ${requestScope.time}
map: ${requestScope.names}
BindingAwareModelMap继承图:
因为传入的map 实际上是BindingAwareModelMap(MVC处理的)
3、@SessionAttributes
@Controller
//value内可以指定多个;存入session域中,并且也存入request域一份
//types如果类型是String,map.put(key,value)中的value是字符串的话也会存入Session中,如果不是只会存到request
@SessionAttributes(value = {"user"},types = {String.class})//该注解只能放类上
public class RestTest {
public static final String SUCCESS = "success";
@RequestMapping("testSessionAtt")
public String testSessionAtt(Map map)
{
User user = new User (1, "kk", 27);
map.put ("user",user);
map.put ("sex",1);
map.put ("age","18");
return SUCCESS;
}
-----------------------------------------jsp页面-------------------------------------------------------------------------------------------
user--request: ${requestScope.user}
user--session: ${sessionScope.user}
sex--request: ${requestScope.sex}
sex--session: ${sessionScope.sex}
//这个没有值,其他都有
age--request: ${requestScope.age}
age--session: ${sessionScope.age}
4、@ModelAttribute(重点)
1、概要:
2、案例流程:
3、@ModelAttribute详解,说明
/**
* 1. 有 @ModelAttribute 标记的方法, 会在每个目标方法执行之前被 SpringMVC 调用!
* 2. @ModelAttribute 注解也可以来修饰目标方法 POJO 类型的入参, 其 value 属性值有如下的作用:
* 1). SpringMVC 会使用 value 属性值在 implicitModel 中查找对应的对象, 若存在则会直接传入到目标方法的入参中.
* 2). SpringMVC 会一 value 为 key, POJO 类型的对象为 value, 存入到 request 中.
*/
/**
* 运行流程:
* 1. 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象, 把对象放入到了 Map 中. 键为: user
* 2. SpringMVC 从 Map 中取出 User 对象, 并把表单的请求参数赋给该 User 对象的对应属性.
* 3. SpringMVC 把上述对象传入目标方法的参数.
*
* 注意: 在 @ModelAttribute 修饰的方法中, 放入到 Map 时的键需要和目标方法入参类型的第一个字母小写的字符串一致!
*
* SpringMVC 确定目标方法 POJO 类型入参的过程
* 1. 确定一个 key:
* 1). 若目标方法的 POJO 类型的参数木有使用 @ModelAttribute 作为修饰, 则 key 为 POJO 类名第一个字母的小写
* 2). 若使用了 @ModelAttribute 来修饰, 则 key 为 @ModelAttribute 注解的 value 属性值.
* 2. 在 implicitModel 中查找 key 对应的对象, 若存在, 则作为入参传入
* 1). 若在 @ModelAttribute 标记的方法中在 Map 中保存过, 且 key 和 1 确定的 key 一致, 则会获取到.
* 3. 若 implicitModel 中不存在 key 对应的对象, 则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰,
* 若使用了该注解, 且 @SessionAttributes 注解的 value 属性值中包含了 key, 则会从 HttpSession 中来获取 key 所
* 对应的 value 值, 若存在则直接传入到目标方法的入参中. 若不存在则将抛出异常.
* 4. 若 Handler 没有标识 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 则
* 会通过反射来创建 POJO 类型的参数, 传入为目标方法的参数
* 5. SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中, 进而会保存到 request 中.
*
* 源代码分析的流程
* 1. 调用 @ModelAttribute 注解修饰的方法. 实际上把 @ModelAttribute 方法中 Map 中的数据放在了 implicitModel 中.
* 2. 解析请求处理器的目标参数, 实际上该目标参数来自于 WebDataBinder 对象的 target 属性
* 1). 创建 WebDataBinder 对象:
* ①. 确定 objectName 属性: 若传入的 attrName 属性值为 "", 则 objectName 为类名第一个字母小写.
* *注意: attrName. 若目标方法的 POJO 属性使用了 @ModelAttribute 来修饰, 则 attrName 值即为 @ModelAttribute
* 的 value 属性值
*
* ②. 确定 target 属性:
* > 在 implicitModel 中查找 attrName 对应的属性值. 若存在, ok
* > *若不存在: 则验证当前 Handler 是否使用了 @SessionAttributes 进行修饰, 若使用了, 则尝试从 Session 中
* 获取 attrName 所对应的属性值. 若 session 中没有对应的属性值, 则抛出了异常.
* > 若 Handler 没有使用 @SessionAttributes 进行修饰, 或 @SessionAttributes 中没有使用 value 值指定的 key
* 和 attrName 相匹配, 则通过反射创建了 POJO 对象
*
* 2). SpringMVC 把表单的请求参数赋给了 WebDataBinder 的 target 对应的属性.
* 3). *SpringMVC 会把 WebDataBinder 的 attrName 和 target 给到 implicitModel.
* 近而传到 request 域对象中.
* 4). 把 WebDataBinder 的 target 作为参数传递给目标方法的入参.
*/
5、@SessionAttributes引发的异常:
讲人话,就是类上面上的@SessionAttributes( value="xxx"),xxx找不到,所有必须有,或者注释掉这个注解
解决方法:
6、视图和视图解析器
概述:
案例:
@RequestMapping("show")
public String test() {
return SUCCESS;
}
@RequestMapping("testRedirect")
public String testRedirect() {
System.out.println ("重定向");
return "redirect:/index.jsp";
}