dispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
dispatcherServlet
/
注意:
(1)、上述标签中的contextConfigLocation,是为DispatcherServlet配置一个初始化参数,指定SpringMVC配置文件的加载位置;
(2)、实际上也可以不通过 contextConfigLocation 来指定 SpringMVC 的配置文件位置, 而使用默认的。 默认的配置文件的位置为: /WEB-INF/-servlet.xml(可以在源码中看到该路径)
SpringMVC配置文件的具体介绍可以看下面这篇文章: https://blog.csdn.net/zxd1435513775/article/details/78843299
二、注解剖析 1、@RequestMapping @Controller
public class HelloWorld {
@RequestMapping("/helloworld")
public String hello(){
System.out.println("hello world");
return "success";
}
}
使用介绍:
(1)、 使用 @RequestMapping 注解来映射请求的URL; (2)、返回值会通过视图解析器,解析为实际的物理视图, 对于InternalResourceViewResolver视图解析器, 会做如下的解析:通过 prefix + returnVal + 后缀,这样的方式得到实际的物理视图, 然会做转发操作 :/WEB-INF/views/success.jsp (3)、@RequestMapping 除了修饰方法,还可来修饰类,具体用法如下:
1). 类定义处:提供初步的请求映射信息,相对于WEB应用的根目录;
2). 方法处:提供进一步的细分映射信息,相对于类定义处的UR,若类定义处未标注@RequestMapping,
则方法处标记的URL相对于WEB应用的根目录
2、@PathVariable
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("testPathVariable: " + id);
}
使用介绍:
(1)、带占位符的URL是Spring3.0新增的功能; (2)、通过 @PathVariable 注解可以将URL中占位符参数绑定到控制器处理方法的入参中: URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx”) 绑定到操作方法的入参中;
3、REST风格的URL 操作访问URL请求方式原来的请求方式查询/order/1HTTP GETget?id=1删除/order/1HTTP DELETEdelete?id=1更新/order/1HTTP PUTupdate?id=1新增/order/1HTTP POST(1)、客户端如何发送 PUT 请求和 DELETE 请求呢 ?
1)、需要配置 HiddenHttpMethodFilter 过滤器
2)、需要发送POST请求
3)、需要在发送 POST 请求时携带一个 name="_method" 的隐藏域, 值为DELETE或PUT
(2)、在SpringMVC的目标方法中如何得到 id 呢?
1)、使用@PathVariable注解
注意:
浏览器 form 表单只支持GET与POST请求,而DELETE、PUT等method并不支持,Spring3.0 添加了一个HiddenHttpMethodFilter过滤
器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求。
4、@RequestParam
@RequestMapping(value = "/testRequestParam")
public String testRequestParam(
@RequestParam(value = "username") String un,
@RequestParam(value = "age", required = false, defaultValue = "0") int age){
System.out.println("testRequestParam, username: " + un + ", age: "+ age);
return "success";
}
(1)、使用@RequestParam绑定请求参数值,在处理方法入参处使用 @RequestParam 可以把请求参数传递给请求方法; (2)、参数用法:
value:参数名
required:是否必须。默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
(3)、@RequestParam 来映射请求参数,value值即请求参数的参数名,required该参数是否必须,默认为true defaultValue 请求参数的默认值。
5、@RequestHeader 6、@CookieValue 7、使用POJO对象绑定请求参数值 @RequestMapping("/testPojo")
public String testPojo(User user) {
System.out.println("testPojo: " + user);
return “success”;
}
(1)、Spring MVC 会按请求参数名和POJO属性名进行自动匹配, 自动为该对象填充属性值,支持级联属性。 如:dept.deptId、dept.address.tel 等。
8、使用Servlet API作为入参 @RequestMapping("/testServletAPI")
public void testServletAPI(HttpServletRequest request,
HttpServletResponse response,
Writer out)
throws IOException {
System.out.println("testServletAPI, " + request + ", " + response);
out.write("hello springmvc");
}
(1)、可以使用 Serlvet 原生的 API 作为目标方法的参数,具体支持以下类型:
HttpServletRequestHttpServletResponseHttpSessionPrincipalInputStreamOutputStreamReaderWriterLocale 9、处理模型数据(1)、Spring MVC 提供了以下几种途径输出模型数据:
1)、ModelAndView:处理方法返回值类型为 ModelAndView 时,则其既包含视图信息,也包含模型数据信息。
添加模型数据:
MoelAndView addObject(String attributeName, Object attributeValue)
ModelAndView addAllObject(Map modelMap )
设置视图:
void setView(View view )
void setViewName(String viewName)
2)、Map 、Model、ModelMap:
入参为:org.springframework.ui.Model、org.springframework.ui.ModelMap 、java.uti.Map 时,
处理方法返回时,Map中的数据会自动添加到模型中;
3)、@SessionAttributes: 将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性;
4)、@ModelAttribute: 方法入参标注该注解后, 入参的对象就会放到数据模型中
(2)、ModelAndView示例代码
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
String viewName = SUCCESS;
ModelAndView modelAndView = new ModelAndView(viewName);
//添加模型数据到 ModelAndView 中.
modelAndView.addObject("time", new Date());
return modelAndView;
}
(3)、Map示例代码
@RequestMapping("/testMap")
public String testMap(Map map){
map.put("names", Arrays.asList("Tom", "Jerry", "Mike"));
return “success”;
}
说明:
目标方法可以添加 Map 类型(实际上也可以是 Model 类型或 ModelMap 类型)的参数.。
(4)、@SessionAttributes 示例代码
@RequestMapping("/testSessionAttributes")
public String testSessionAttributes(Map map){
User user = new User("Tom", "123456", "tom@qq.com", 15);
map.put("user", user);
map.put("school", "hupan");
return "success";
}
说明:
1)、@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外(实际上使用的是 value 属性值),
还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是 types 属性值)
2)、若希望在多个请求之间共用某个模型属性数据,则可以在控制器类上标注一个 @SessionAttributes,
Spring MVC 将在模型中对应的属性暂存到 HttpSession 中;
3)、@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型
指定哪些模型属性需要放到会话中;
4)、@SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加
到会话中。
注意: 该注解只能放在类的上面. 而不能修饰放方法。
10、@ModelAttribute(1)、在方法定义上标注 @ModelAttribute 注解
Spring MVC在调用目标处理方法前,会先逐个调用在方法上标注了@ModelAttribute 的方法。
(2)、在方法的入参前使用@ModelAttribute 注解
可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参,将方法
入参对象添加到模型中。
(3)、示例代码
//该方法会往隐含模型中添加一个名为user的模型属性
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
Map map){
if(id != null){
//模拟从数据库中获取对象
User user = new User(1, "Tom", "123456", "tom@qq.com", 12);
System.out.println("从数据库中获取一个对象: " + user);
map.put("user", user);
}
}
//表单请求数据的Controller(略)
...
(4)、上述代码运行流程:
1)、执行 @ModelAttribute 注解修饰的方法:从数据库中取出对象, 把对象放入到了 Map 中,键为: user;
2)、SpringMVC 从 Map 中取出 User 对象,并把表单的请求参数赋给该 User 对象的对应属性;
3)、SpringMVC 把上述对象传入目标方法的参数;
注意: 在 @ModelAttribute 修饰的方法中, 放入到 Map 时的键需要和目标方法入参类型的第一个字母小写的字符串一致!
11、视图和视图解析器(1)、无论目标方法返回的是一个String型、ModelAndView型还是View,SpringMVC都会把它转化为一个ModelAndView对象;
(2)、请求处理方法执行完成后,最终返回一个 ModelAndView对象。对于那些返回String,View或 ModeMap等类型的处理方法,Spring MVC也会在内部将它们装配成一个ModelAndView对象,它包含了逻辑名和模型对象的视图;(可以阅读源码)
(3)、Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是JSP 、Excel、JFreeChart 等各种表现形式的视图,对于最终究竟采取何种视图对象对模型数据进行渲染, 处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦;
(4)、视图解析器
SpringMVC为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,
并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。视图解析器的作用比较单一:
将逻辑视图解析为一个具体的视图对象。
所有的视图解析器都必须实现 ViewResolver 接口:
12、请求页面不经过Controller,直接跳到页面
13、处理静态资源
(1)、优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀,若将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕获WEB 容器的所有请求,包括静态资源的请求, SpringMVC 会将它们当成一个普通请求处理,因找不到对应处理器将导致错误;
(2)、可以在 SpringMVC 的配置文件中加入如下配置,来解决静态资源的问题:
(3)、该注解将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由DispatcherServlet 继续处理,一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的WEB 服务器的默认 Servlet 名称不是 default,则需要通过 defaultservlet-name 属性显式指定;
14、关于重定向(1)、一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
(2)、如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对它们进行特殊处理,将 forward: 和 redirect: 当成指示符,其后的字符串作为 URL 来处理。
redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作;
forward:success.jsp:会完成一个到 success.jsp 的转发操作;
15、QA
(1)、需要进行 Spring 整合 SpringMVC 吗 ?还是否需要再加入 Spring 的 IOC 容器 ?是否需要再 web.xml 文件中配置启动 Spring IOC 容器的 ContextLoaderListener ?
回答:
(1)、需要的观点:通常情况下, 类似于数据源, 事务, 整合其他框架都是放在 Spring 的配置文件中
(而不是放在 SpringMVC 的配置文件中),实际上放入 Spring 配置文件对应的 IOC 容器中的还有
Service 和 Dao;
(2)、不需要的观点:都放在 SpringMVC 的配置文件中. 也可以分多个 Spring 的配置文件,
然后使用 import 节点导入其他的配置文件
(2)、问题:若 Spring 的 IOC 容器和 SpringMVC 的 IOC 容器扫描的包有重合的部分, 就会导致有的 bean 会被创建 2 次.
解决:
1. 使 Spring 的 IOC 容器扫描的包和 SpringMVC 的 IOC 容器扫描的包没有重合的部分.
2. 使用 exclude-filter 和 include-filter 子节点来规定只能扫描的注解
(3)、SpringMVC 的 IOC 容器中的 bean 可以来引用 Spring IOC 容器中的 bean, 返回来呢 ? 反之则不行. Spring IOC 容器中的 bean 却不能来引用 SpringMVC IOC 容器中的 bean!
补充:SpringMVC运行流程图