SpringMVC

1、SpringMVC简介

  大部分java应用都是web应用,展现层是web应用最为重要的部分。Spring为展现层提供了一个优秀的web框架——Spring MVC。和众多其他web框架一样,它基于MVC的设计理念,此外,它采用了松散耦合可插拔组件结构,比其他MVC框架更具扩展性和灵活性。

  SpringMVC通过一套MVC注解,让POJO成为处理请求的控制器,无需实现任何接口,同时,SpringMVC还支持REST风格的URL请求。此外,SpringMVC在数据绑定、视图解析、本地化处理及静态资源处理上都有许多不俗的表现。它在框架设计、扩展性、灵活性等方面全面超越了Struts、WebWork等MVC框架,从原来的追赶者一跃成为MVC的领跑者。

  SpringMVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet是SpringMVC框架的总导演、总策划,它负责截获请求并将其分派给相应的处理器处理。

 1.1、Spring体系简介

  

 1.2、回顾MVC设计模式

  

  1. 用户将请求发送到控制器,控制器本身没有处理业务逻辑的能力;
  2. 将请求委托给模型做处理,模型将处理结果返回到控制器;
  3. 控制器将模型对视图做渲染;
  4. 将最终的视图(html)返回给用户;

  注意:MVC不是java独有的,其他语言也有,它是一种模式!它也不是B/S独有的,C/S也有!

 1.3、SpringMVC整体架构

  

  1. 用户发起请求到前端控制器(DispatcherServlet),前端控制器没有能力处理业务逻辑;
  2. 通过HandlerMapping查找模型(Controller、Handler);
  3. 返回执行链,执行链包含了2部分内容,Handler对象以及拦截器(组):n个HandlerInterceptor;
  4. 根据处理器Handler找到适配器HandlerAdapter,再通过HandlerAdapter去适配、执行模型(Handler)
  5. 适配器调用Handler对象处理业务逻辑;
  6. 模型处理完业务逻辑,返回ModelAndView对象,view不是真正的视图对象,而是视图名称;
  7. 将ModelAndView对象返回给前端控制器;
  8. 前端控制器通过视图名称经过视图解析器(ViewResolver)查找视图对象;
  9. 返回视图对象;
  10. 前端控制器渲染视图;
  11. 返回给前端控制器;
  12. 前端控制器将视图(html、json、xml、Excel)返回给用户;

 1.4、我的第一个SpringMVC程序

  1. 配置SpringMVC框架入口-web.xml
     1 <!-- SpringMVC框架的入口 -->
     2 <servlet>
     3 <servlet-name>springmvc</servlet-name>
     4 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     5     <load-on-startup>1</load-on-startup>
     6     <!-- 默认查找配置文件规则  /WEB-INF/servletName-servlet.xml -->
     7 </servlet>
     8 <servlet-mapping>
     9     <servlet-name>springmvc</servlet-name>
    10     <!-- 所有请求以*.do会进入MVC框架(.do是struts1的后缀) -->
    11     <url-pattern>*.do</url-pattern>
    12 </servlet-mapping>

    默认查找配置文件规则  /WEB-INF/servletName-servlet.xml

  2. 配置核心组件_springmvc-servlet.xml
    1. 配置HandlerMapping
      1 <!-- 注册HandlerMapping -->
      2 <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

      通过beanName查找,/hello.do è  cn.itcast.springmvc.controller.HelloController

    2. 配置适配器
      1 <!-- 注册简单适配器 -->
      2 <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    3. 定义Controller
      1 <!-- 自定义Handler -->
      2 <bean name="/hello.do" class="cn.itcast.springmvc.controller.HelloController"/>

      要指定名称:/hello.do

    4. 定义视图解析器
      1 <!-- prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp"  -->
      2 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      3     <!-- 前缀 -->
      4     <property name="prefix" value="/WEB-INF/views/"/>
      5     <!-- 后缀 -->
      6     <property name="suffix" value=".jsp"/>
      7 </bean>

      设置前缀和后缀,得到具体视图路径;

      prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp"

  3. 测试

    http://127.0.0.1/hello.do

  4. 执行过程

  5. SpringMVC的默认装载组件

    在org.springframework.web.servlet/DispatcherServlet.properties 默认配置

    # Default implementation classes for DispatcherServlet's strategy interfaces.
    # Used as fallback when no matching beans are found in the DispatcherServlet context.
    # Not meant to be customized by application developers.
    
    org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
    
    org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
    
    org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
        org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
    
    org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
        org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
    
    org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
        org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
        org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
    
    org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
    
    org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
    
    org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

 1.5、我的第一个SpringMVC注解程序

  1. 创建Controller
     1 @RequestMapping("/demo") //标识请求进入Controller的url path
     2 @Controller //用来标识这个一个Controller(Handler)
     3 public class Demo1Controller {
     4 
     5     @RequestMapping("/show1") //标识请求进入Controller的url path
     6     public ModelAndView show1() {
     7         ModelAndView mv = new ModelAndView();
     8         mv.setViewName("demo1");
     9         mv.addObject("msg", "我的第一个注解程序!");
    10         return mv;
    11     }
    12 }
  2. 配置扫描器
    1 <!-- 扫描包,使@Controller生效 -->
    2 <context:component-scan base-package="cn.itcast.springmvc.controller"/>
  3. 配置视图解析器
    1 <!-- prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp"  -->
    2 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    3     <!-- 前缀 -->
    4     <property name="prefix" value="/WEB-INF/views/"/>
    5     <!-- 后缀 -->
    6     <property name="suffix" value=".jsp"/>
    7 </bean>
  4. 创建jsp页面

    创建页面:/WEB-INF/views/demo1.jsp

     1 <%@ page language="java" contentType="text/html; charset=UTF-8"
     2     pageEncoding="UTF-8"%>
     3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
     4 <html>
     5 <head>
     6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     7 <title>Insert title here</title>
     8 </head>
     9 <body>
    10 <h1>${msg}</h1>
    11 </body>
    12 </html>
  5. 测试

    http://127.0.0.1/demo/show1.do

 1.6、推荐使用的注解的HandlerMapping和HandlerAdapter

1 <!-- 推荐使用的注解的HandlerMapping -->
2 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
3     
4 <!-- 推荐使用的注解适配器 -->
5 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

其实这两个适配器也是不需要配置的,可以只配置下面提到的mvc注解驱动即可!

 1.7、使用MVC注解驱动

   在servlet配置文件中加入注解驱动标签即可:

1 <!-- mvc的注解驱动 -->
2 <mvc:annotation-driven/>
  • 注解驱动背后处理逻辑

    org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser

 2、@RequestMapping映射

  在SpringMVC中的众多Controller以及每个Controller的众多方法,请求是如何映射到具体的处理方法上?这个就是靠@RequestMapping完成的。

  @RequestMapping既可以定义在类上也可以定义在方法上,

  请求映射的规则是:类上的@RequestMapping.value + 方法上的@RequestMapping.value

   @RequestMapping(value = "/hello") 和 @RequestMapping("/hello") 等效;

  

  映射:

  1. 标准URL映射
  2. Ant风格的URL映射
  3. 占位符映射
  4. 限制请求方法映射
  5. 限制参数映射

 2.1、标准URL映射

  标准URL映射是最简单的一种映射,例如:@RequestMapping("/hello")  或 @RequestMapping(value="/hello")

  请求url:http://localhost/hello.action

 2.2、Ant风格的URL映射

  

 1 /**
 2 * Ant风格的通配符映射!
 3 * 
 4 * @return
 5 */
 6 @RequestMapping(value = "/demo/**/show3")
 7 public ModelAndView show3() {
 8     ModelAndView mv = new ModelAndView();
 9     mv.setViewName("hello");
10     mv.addObject("msg", "Ant风格的通配符(**)映射!");
11     return mv;
12 }

 2.3、占位符映射

  Url中可以通过一个或多个{xxxx}占位符映射。通过@PathVariable(“xxx”)绑定到方法的入参中。

  例如:@RequestMapping(“/user/{userId}/query")

  请求URL:http://localhost/user/8/query

 

  RESTFul风格:http://127.0.0.1/demo/123/show4.....

 1 /**
 2 * url占位符
 3 * 这里参数id改为String,也可以传中文,但会有乱码,所以一般传递中文参数会选择post提交
 4 * @return
 5 */
 6 @RequestMapping(value = "/demo/{id}/show4")
 7 public ModelAndView show4(@PathVariable("id") Long id) {
 8     ModelAndView mv = new ModelAndView();
 9     mv.setViewName("hello");
10     mv.addObject("msg", "url占位符测试 id = " + id + "!");
11     return mv;
12 }

 2.4、@PathVariable小误区

  

  

  小结:只有在开发时debug的环境下@PathVariable(xxxx) 可以简写为:@PathVariable!因此不要简写

 2.5、限定请求方式的映射

  在Http请求中最常用的请求方法是GET、POST,还有其他的一些方法,DELET、PUT、HEAD等。

  例如:

  @RequestMapping(value = "/{userId}/query",method=RequestMethod.GET)

  @RequestMapping(value = "/{userId}/query",method={RequestMethod.GET,RequestMethod.POST})

 1 /**
 2      * 限制请求方法GET、POST
 3      * 
 4      * @return
 5      */
 6     @RequestMapping(value = "/demo/test/show5", method = RequestMethod.POST)
 7     public ModelAndView show5() {
 8         ModelAndView mv = new ModelAndView();
 9         mv.setViewName("hello");
10         mv.addObject("msg", "你使用的是POST请求!");
11         return mv;
12     }
13 
14     /**
15      * 限制请求方法GET、PUT
16      * 
17      * @return
18      */
19     @RequestMapping(value = "/demo/test/show6", method = { RequestMethod.GET, RequestMethod.PUT })
20     public ModelAndView show6() {
21         ModelAndView mv = new ModelAndView();
22         mv.setViewName("hello");
23         mv.addObject("msg", "你使用的是GET或PUT请求!");
24         return mv;
25     }

 2.6、限定参数映射

设定请求的参数来映射URL,例如:@RequestMapping(value="/query",params="userId"),要求请求中必须带有userId参数。

参数的限制规则如下:

params=”userId” 请求参数中必须包含userId

params=”!userId” 请求参数中不能包含userId

params=”userId!=1” 请求参数必须包含userId,但其值不能为1

params={“userId”,”name”} 必须包含userId和name参数

 1 /**
 2      * 限制请求参数
 3      * 
 4      * @return
 5      */
 6     @RequestMapping(value = "/demo/test/show7", params = "id")
 7     public ModelAndView show7(@RequestParam("id") String id) {
 8         ModelAndView mv = new ModelAndView();
 9         mv.setViewName("hello");
10         mv.addObject("msg", "现在请求参数  id = " + id + "!");
11         return mv;
12     }
13 
14     /**
15      * 限制多个请求参数
16      * 
17      * @return
18      */
19     @RequestMapping(value = "/demo/test/show8", params = { "id", "name" })
20     public ModelAndView show8(@RequestParam("id") String id, @RequestParam("name") String name) {
21         ModelAndView mv = new ModelAndView();
22         mv.setViewName("hello");
23         mv.addObject("msg", "现在请求参数  id = " + id + "  name = " + name + "!");
24         return mv;
25     }

3、获取参数

 3.1、绑定servlet内置对象

在Controller中获取Servlet的内置对象(Request、Response、Session)是非常简单的,如下:

public void test(HttpServletRequest request){……}

public void test(HttpServletResponse response){……}

public void test(HttpSession session){……}

public void test(Model model){……}//Model:数据模型,主要存储要返回到客户端的数据的,功能类似于Request对象。

 1 /**
 2      * 获取Servlet内置对象
 3      * @param request
 4      * @param response
 5      * @param session
 6      * @return
 7      */
 8     @RequestMapping(value = "/demo/test/show9")
 9     public ModelAndView show9(HttpServletRequest request,HttpServletResponse response,HttpSession session){
10         ModelAndView mv = new ModelAndView();
11         mv.setViewName("servlet");
12         
13         StringBuilder sb = new StringBuilder();
14         sb.append("request = " + request);
15         sb.append("<br/>response = " + response);
16         sb.append("<br/>session = " + session);
17         
18         request.setAttribute("param1", "在Request中参数!");
19         
20         mv.addObject("msg", sb);
21         return mv;
22 }

  结果:

  

 3.2、@PathVariable

通过@PathVariable可以绑定占位符参数到方法参数中,可以认为是url中?前面的参数,例如:@PathVariable("userId") Long userId

参考@RequestMapping映射/占位符映射部分!

 3.3、@RequestParam

@RequestParam有三个参数(url中?后面的参数):

    1. value:参数名;
    2. required:是否必需,默认为true,表示请求参数中必须包含该参数,如果不包含抛出异常。
    3. defaultValue:默认参数值,如果设置了该值自动将required设置为false,如果参数中没有包含该参数则使用默认值。

示例:@RequestParam(value = "userId", required = false, defaultValue = "1")

 1 /**
 2      * 获取?后面传递的参数
 3      * 
 4      * @return
 5      */
 6     @RequestMapping(value = "/demo/test/show10")
 7     public ModelAndView show10(@RequestParam(value = "id", required = false, defaultValue = "000")String id){
 8         ModelAndView mv = new ModelAndView();
 9         mv.setViewName("hello");
10         mv.addObject("msg", "现在请求参数  id = "+id+" !");
11         return mv;
12     }

 3.4、@ CookieValue

在SpringMVC中获取cookie值更加方便了,@CookieValue可以绑定cookie值,和@RequestParam一样有三个参数,使用方法:

public void test(@CookieValue("JSESSIONID") String jsessionid)

 1 /**
 2      * 获取cookie中数据
 3      * 
 4      * @return
 5      */
 6     @RequestMapping(value = "/demo/test/show11")
 7     public ModelAndView show11(@CookieValue("JSESSIONID")String JSESSIONID){
 8         ModelAndView mv = new ModelAndView();
 9         mv.setViewName("hello");
10         mv.addObject("msg", "JSESSIONID  = "+JSESSIONID+" !");
11         return mv;
12 }

  结果:

  

 3.5、POJO对象绑定参数

  SpringMVC会将请求过来的参数名和POJO实体中的属性名进行匹配,如果名称一致,将把值填充到对象中。

 1 /**
 2      * POJO对象绑定
 3      * 
 4      * @return
 5      */
 6     @RequestMapping(value = "/demo/test/show12")
 7     public ModelAndView show12(User user){
 8         ModelAndView mv = new ModelAndView();
 9         mv.setViewName("hello");
10         mv.addObject("msg", "user  = "+user+" !");
11         return mv;
12 }

  http://127.0.0.1/demo/test/show12?id=1&userName=123&password=111&name=abc

  

 3.6、JAVA的基本数据类型绑定

  Spring对Java的基本数据类型的转换支持的非常多,基本能满足日常开发需要,默认支持的数据类型在org.springframework.beans.PropertyEditorRegistrySupport中定义。

  • testForm.html
     1 <!DOCTYPE>
     2 <form action="/demo/test/show13.action" method="post">
     3     <div>姓名:</div>
     4     <div><input name="name" value="张三"/></div>
     5     <div class="clear"></div>
     6     <div>年龄:</div>
     7     <div><input name="age" value="20"/></div>
     8     <div class="clear"></div>
     9     <div>收入:</div>
    10     <div><input name="income" value="100000"/></div>
    11     <div class="clear"></div>
    12     <div>结婚:</div>
    13     <div>
    14     <input type="radio" name="isMarried" value="true" checked="checked"/>15     <input type="radio" name="isMarried" value="false"/></div>
    16     <div class="clear"></div>
    17     <div>兴趣:</div>
    18     <div>
    19     <input type="checkbox" name="interests" value="听歌" checked="checked"/>听歌
    20     <input type="checkbox" name="interests" value="书法" checked="checked"/>书法
    21     <input type="checkbox" name="interests" value="看电影" checked="checked"/>看电影
    22     </div>
    23     <div class="clear"></div>
    24     <div><input type="submit" value="提交表单"/></div>
    25 </form>
  • java测试代码
     1     @RequestMapping("/demo/test/show13")
     2     @ResponseStatus(value = HttpStatus.OK)// 无需跳转页面,直接返回200状态
     3     public void show13(String name, Integer age, Double income, Boolean isMarried, String[] interests) {
     4         System.out.println("简单数据类型绑定=========");
     5         System.out.println("名字:" + name);
     6         System.out.println("年龄:" + age);
     7         System.out.println("收入:" + income);
     8         System.out.println("已结婚:" + isMarried);
     9         System.out.println("兴趣:");
    10         for (String interest : interests) {
    11             System.out.println(interest);
    12         }
    13         System.out.println("====================");
    14     }

 3.7、集合List绑定

  List的绑定需要将List对象包装到一个类中才能绑定。

  

  

4、SpringMVC和Struts2的区别(面试)

  1. SpringMVC的入口是Servlet,Struts2的入口是Filter,两者的实现机制不同;
  2. SpringMVC基于方法设计,传递参数是通过方法形参,其实现是单例模式(也可以改为多例,推荐用单例),Struts2基于类设计,传递参数是通过类的属性,只能是多例实现,性能上SpringMVC更高一些。
  3. 参数传递方面,Struts2是用类的属性接收的,也就是在多个方法间共享,而SpringMVC基于方法,多个方法间不能共享。

5、视图与视图解析器

 5.1、JSP和JSTL视图解析器

  InternalResourceViewResolver默认使用的是JSTL解析器,要想使用JSTL标签需要导入JSTL的依赖。    

1 <dependency>
2 
3        <groupId>jstl</groupId>
4 
5        <artifactId>jstl</artifactId>
6 
7        <version>1.2</version>
8 
9 </dependency>

  具体扩展知识点参考文档:

  

  • user.jsp
     1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
     2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     3 <!DOCTYPE html>
     4 <html>
     5     <head>
     6         <title>JSTL Demo</title>
     7     </head>
     8     
     9     <body>
    10         <table>
    11             <thead>
    12             <tr>
    13                 <th>ID</th>
    14                 <th>UserName</th>
    15                 <th>Name</th>
    16                 <th>Age</th>
    17             </tr>
    18             </thead>
    19             <tbody>
    20                 <c:forEach items="${users}" var="user">
    21                     <tr>
    22                         <td>${user.id}</<td>
    23                         <td>${user.userName}</<td>
    24                         <td>${user.name}</<td>
    25                         <td>${user.age}</<td>
    26                     </tr>
    27                 </c:forEach>
    28             </tbody>
    29         </table>
    30     </body>
    31 </html>
  • 构造List<User>
     1 /**
     2      * 测试JSTL标签
     3      * @return
     4      */
     5     @RequestMapping("/demo/test/show14")
     6     public ModelAndView show14() {
     7         ModelAndView modelAndView = new ModelAndView("users");//通过构造直接赋视图名
     8         List<User> users = new ArrayList<User>();
     9 
    10         for (int i = 0; i < 10; i++) {
    11             User user = new User();
    12             user.setAge(20 + i);
    13             user.setCreated(new Date());
    14             user.setId(Long.valueOf(i));
    15             user.setName("name_" + i);
    16             user.setPassword("123456");
    17             user.setSex(i / 2);
    18             user.setUpdated(user.getCreated());
    19             user.setUserName("userName_" + i);
    20             users.add(user);
    21         }
    22         modelAndView.addObject("users", users);
    23         return modelAndView;
    24     }

 5.2、@ResponseBody

  

  补充:@ResponseBody注解,除了可以返回json,还可以返回xml等其他视图,但是用的最多的是返回json

 1 /**
 2      * 测试@ResponseBody
 3      * 
 4      * @return
 5      */
 6     @RequestMapping(value = "/demo/test/show15")
 7     @ResponseBody
 8     public User show15() {
 9         User user = new User();
10         Integer i = 0;
11         user.setAge(20 + i);
12         user.setCreated(new Date());
13         user.setId(Long.valueOf(i));
14         user.setName("name_" + i);
15         user.setPassword("123456");
16         user.setSex(i / 2);
17         user.setUpdated(user.getCreated());
18         user.setUserName("userName_" + i);
19         return user;
20     }
21 
22     /**
23      * 测试@ResponseBody,返回集合
24      * 
25      * @return
26      */
27     @RequestMapping(value = "/demo/test/show16")
28     @ResponseBody
29     public List<User> show16() {
30         List<User> users = new ArrayList<User>();
31 
32         for (int i = 0; i < 10; i++) {
33             User user = new User();
34             user.setAge(20 + i);
35             user.setCreated(new Date());
36             user.setId(Long.valueOf(i));
37             user.setName("name_" + i);
38             user.setPassword("123456");
39             user.setSex(i / 2);
40             user.setUpdated(user.getCreated());
41             user.setUserName("userName_" + i);
42             users.add(user);
43         }
44         return users;
45     }

 5.3、@RequestBody

  

  java代码:

 1 /**
 2      * 测试@RequestMapping,将json字符转化为java对象
 3      * @param user
 4      * @return
 5      */
 6     @RequestMapping(value = "/demo/test/show17")
 7     public ModelAndView show17(@RequestBody User user) {
 8         ModelAndView mv = new ModelAndView();
 9         mv.setViewName("hello");
10         mv.addObject("msg", "user  = " + user + " !");
11         return mv;
12 }

  测试:

  

  

6、文件上传

  上传原理:首先先保存到一个临时文件中,然后将这个临时文件写到目标文件中,最后将那个临时文件删除!

  • 加入上传组件依赖-pom.xml
    1 <!-- 文件上传组件 -->
    2         <dependency>
    3             <groupId>commons-fileupload</groupId>
    4             <artifactId>commons-fileupload</artifactId>
    5             <version>1.3.1</version>
    6         </dependency>
  • 定义文件上传解析器_ springmvc-servlet.xml
    1 <!-- 定义文件上传解析器 -->
    2     <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    3         <!-- 设定默认编码 -->
    4         <property name="defaultEncoding" value="UTF-8"></property>
    5         <!-- 设定文件上传的最大值5MB,5*1024*1024 -->
    6         <property name="maxUploadSize" value="5242880"></property>
    7     </bean>
  • 定义Controller
     1 @RequestMapping("/file")
     2 @Controller
     3 public class FileUploadController {
     4 
     5     @RequestMapping("/upload")
     6     public String upload(@RequestParam("file") MultipartFile multipartFile) throws Exception {
     7         if (multipartFile != null) {
     8             // multipartFile.getOriginalFilename() 获取文件的原始名称
     9             multipartFile.transferTo(new File("C:\\tmp\\" + multipartFile.getOriginalFilename()));
    10         }
    11         return "redirect:/html/success.html";//重定向跳转
    12     }
    13 }
  • fileUpload.html
    1 <!DOCTYPE>
    2 <form action="/file/upload.action" method="post" enctype="multipart/form-data">
    3     文件: <input name="file" type="file" /><br/>
    4     <input type="submit" value=" 提交 "/>
    5 </form>
  • 测试

7、拦截器

 7.1、理解HandlerExecutionChain

  HandlerExecutionChain是一个执行链,从HandlerMapping返回给DispatcherServlet,其中包含了Handler对象和Interceptor(拦截器)对象,SpringMVC的拦截器接口定义了三个方法:

  1. preHandle 调用handler之前执行;
  2. postHandle 调用handler之后执行;
  3. afterCompletion 视图渲染完之后执行;

  

 7.2、拦截的执行过程

  

  • 前置方法是正序执行:
  • 后置方法是倒序执行:
  • 完成方法是倒序执行:

 7.3、自定义拦截器

  • 实现org.springframework.web.servlet.HandlerInterceptor
     1 public class MyHandlerInterceptor implements HandlerInterceptor{
     2 
     3     /**
     4      * 前置方法,会在handler执行之前执行
     5      */
     6     @Override
     7     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
     8             throws Exception {
     9         System.out.println("前置方法 执行 。。。。。。。。");
    10         return true;
    11     }
    12 
    13     /**
    14      * 后置方法,会在handler执行之后执行
    15      */
    16     @Override
    17     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
    18             ModelAndView modelAndView) throws Exception {
    19         System.out.println("后置方法 执行 。。。。。。。。");
    20     }
    21 
    22     /**
    23      * 完成方法
    24      */
    25     @Override
    26     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
    27             Exception ex) throws Exception {
    28         System.out.println("完成方法 执行 。。。。。。。。");
    29     }
    30 
    31 }
  • 配置拦截器
    1 <!-- 自定义拦截器 -->
    2 <mvc:interceptors>
    3     <mvc:interceptor>
    4         <!-- 2个*代表包含子目录 -->
    5         <mvc:mapping path="/**/*.action"/>
    6         <bean class="cn.itcast.springmvc.interceptor.MyHandlerInterceptor" />
    7     </mvc:interceptor>
    8 </mvc:interceptors>

 7.4、拦截器总结:

  • 拦截器的执行过程和Struts2的拦截器执行过程类似;
  • 拦截器的前置方法是正序执行,如果其中一个返回false则请求返回;
  • 拦截器的后置方法是倒序执行,后置方法只有在前置方法全部执行后才能被执行;
  • 拦截器的完成方法是倒序执行,完成方法不仅是在最后执行,而且如果前置方法返回false也会被执行(已经通过执行的拦截器的完成方法)。
posted @ 2016-03-08 16:08  灰太郎^_^  阅读(339)  评论(0编辑  收藏  举报