SpringMVC学习

转载:http://blog.csdn.net/superdog007/article/details/25614039

          http://blog.csdn.net/xtu_xiaoxin/article/details/8796499

          http://blog.csdn.net/zxr85/article/details/5548588

 

一.SpringMVC工作流程描述

一旦Http请求到来,DispatcherSevlet将负责将请求分发。DispatcherServlet可以认为是Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。HandlerMapping能够完成客户请求到Controller之间的映射。其中,Spring为Controller接口提供了若干实现,例如Spring默认使用的BeanNameUrlHandlerMapping。还有,SimpleUrlHandlerMapping,CommonsPathMapHandlerMapping。Spring Controller将处理来自DispatcherServlet的请求,能够接受HttpServletRequest和HttpServletResponse。Spring为Controller接口提供了若干实现类,位于org.springframework.web.servlet.mvc包中。由于Controller需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。

一旦Controller处理完客户请求,则返回ModelAndView对象给DispatcherServlet前端控制器。ModelAndView中包含了模型(Model)和视图(View)。从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观角度考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型和视图。前端控制器返回的视图可以是视图的逻辑名,或者实现了View接口的对象。View对象能够渲染客户响应结果。其中,ModelAndView中的模型能够供渲染View时使用。借助于Map对象能够存储模型。

如果ModelAndView返回的视图只是逻辑名,则需要借助Spring提供的视图解析器(ViewResoler)在Web应用中查找View对象,从而将响应结果渲染给客户。DispatcherServlet将View对象渲染出的结果返回个客户。

 

大概流程如下:

1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;

2. DispatcherServlet 对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象 (包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;

3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)

4.  提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:

HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息

数据转换:对请求消息进行数据转换。如String转换成Integer、Double等

数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等

数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中

5.  Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;

6.  根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;

7. ViewResolver 结合Model和View,来渲染视图

8. 将渲染结果返回给客户端。

 

二.WebApplicationContext

Spring会创建一个全局的WebApplicationContext上下文,称为根上下文 (root WebApplicationContext),保存在 ServletContext 中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性的值。可以使用工具类取出上下文:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

DispatcherServlet是一个Servlet,可以同时配置多个,每个DispatcherServlet有一个自己的 WebApplicationContext上下文,这个上下文继承了根上下文中所有东西。 保存在ServletContext中,key是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称。当一个Request对象产生时,会把这个WebApplicationContext上下文保存在Request对象中,key是DispatcherServlet.class.getName() + ".CONTEXT"。可以使用工具类取出上下文:RequestContextUtils.getWebApplicationContext(request);DispatcherServlet的上下文是通过配置servlet的contextConfigLocation来加载的,默认实现是XmlWebApplicationContext。

DispatcherServlet的上下文仅仅是 Spring MVC的上下文,而Spring加载的上下文是通过ContextLoaderListener来加载的。一般spring web项目中同时会使用这两种上下文,前者仅负责MVC相关bean的配置管理(如ViewResolver、Controller、 MultipartResolver等),后者则负责整个spring相关bean的配置管理 (如相关Service、DAO等)。因此在/WEB-INF/[server-name]-servlet.xml中配置的Bean一般只针对Spring MVC有效,而在ContextLoaderListener配置文件下配置的bean则对整个spring有效。

如果通过 WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 来试图获取DispatcherServlet加载的applicationContext时,就会抛出"No WebApplicationContext found: no ContextLoaderListener registered?"的异常。

 

三.SpringMVC的初级使用

1.目录结构

    

2.web.xml

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   3:     xmlns="http://java.sun.com/xml/ns/javaee"
   4:     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
   5:     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   6:  
   7:     id="WebApp_ID" version="3.0">
   8:     <display-name>mvc</display-name>
   9:  
  10:     <context-param>
  11:         <param-name>contextConfigLocation</param-name>
  12:         <param-value>/WEB-INF/applicationContext.xml</param-value>
  13:     </context-param>
  14:  
  15:     <!-- Spring 容器启动监听器 -->
  16:     <listener>
  17:         <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  18:     </listener>
  19:  
  20:     <listener>
  21:         <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  22:     </listener>
  23:  
  24:  
  25:     <!-- SpringMVC的核心控制器(前端控制器) -->
  26:     <servlet>
  27:         <servlet-name>springmvc</servlet-name>
  28:         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  29:         <!-- 指定配置文件的全名,如果不指定,则为这里的servlet-name的属性值+"-servlet.xml" -->
  30:         <init-param>
  31:             <param-name>contextConfigLocation</param-name>
  32:             <param-value>/WEB-INF/springmvc-servlet.xml</param-value>
  33:         </init-param>
  34:         <!-- 启动服务器时创建此serlvet核心对象 -->
  35:         <load-on-startup>1</load-on-startup>
  36:     </servlet>
  37:  
  38:     <servlet-mapping>
  39:         <servlet-name>springmvc</servlet-name>
  40:         <url-pattern>/</url-pattern>
  41:     </servlet-mapping>
  42: </web-app>

3.springmvc-servlet.xml

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <beans xmlns="http://www.springframework.org/schema/beans"
   3:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
   4:     xmlns:context="http://www.springframework.org/schema/context"
   5:     xmlns:mvc="http://www.springframework.org/schema/mvc"
   6:     xsi:schemaLocation="http://www.springframework.org/schema/beans 
   7:     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
   8:     http://www.springframework.org/schema/tx 
   9:     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
  10:     http://www.springframework.org/schema/context
  11:     http://www.springframework.org/schema/context/spring-context-3.0.xsd
  12:     http://www.springframework.org/schema/mvc
  13:     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
  14:  
  15:     <!-- 自动扫描 -->
  16:     <context:component-scan base-package="com.zero.mvc.controller" />
  17:  
  18:     <mvc:annotation-driven />
  19:     <!-- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">  </bean>
  20:     <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  </bean>
  21:     自动注册DefaultAnnotationHandlerMapping与 AnnotationMethodHandlerAdapter 
  22:         两个bean, 是spring MVC为@Controllers分发请求所必须的。 并提供了数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持, 
  23:         读写XML的支持(JAXB),读写JSON的支持(Jackson)
  24:      -->
  25:  
  26:     <!-- 控制器类,name表示访问的URI路径,class表示对应的action类 -->
  27:     <bean name="/welcome.html" class="com.zero.mvc.controller.WelcomeController"></bean>
  28:  
  29:     <!-- ViewResolver ,视图解析器,框架提供了好多解析器,这里举例其中的一种 -->
  30:     <bean
  31:         class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  32:         <property name="prefix" value="/WEB-INF/jsp/"></property>
  33:         <property name="suffix" value=".jsp"></property>
  34:         <!--prefix+ view + suffix -->
  35:     </bean>
  36:  
  37:     <!-- 总拦截器,拦截所有url,用于处理权限 -->
  38:     <mvc:interceptors>
  39:         <bean class="com.zero.mvc.inteceptor.MyInteceptor" />
  40:     </mvc:interceptors>
  41:  
  42:     <!-- 总错误处理 -->
  43:     <bean id="exceptionResolver"
  44:         class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  45:         <property name="defaultErrorView">
  46:             <value>error</value>
  47:         </property>
  48:         <property name="defaultStatusCode">
  49:             <value>500</value>
  50:         </property>
  51:         <property name="warnLogCategory">
  52:             <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
  53:             </value>
  54:         </property>
  55:     </bean>
  56: </beans>

4.applicationContext

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <beans xmlns="http://www.springframework.org/schema/beans"
   3:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   4:     xmlns:mvc="http://www.springframework.org/schema/mvc"
   5:     xsi:schemaLocation="http://www.springframework.org/schema/mvc
   6:         http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
   7:         http://www.springframework.org/schema/beans
   8:         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   9:         http://www.springframework.org/schema/context
  10:         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  11:  
  12:     <!-- 注解扫描包 -->
  13:     <context:component-scan base-package="com.zero.mvc.vo" />
  14:  
  15:     <bean id="client" class="com.zero.mvc.vo.Client">
  16:     </bean>
  17:  
  18: </beans>

5.com.zero.mvc.controller

   1: package com.zero.mvc.controller;
   2:  
   3: import javax.servlet.http.HttpServletRequest;
   4: import javax.servlet.http.HttpServletResponse;
   5:  
   6: import org.springframework.stereotype.Controller;
   7: import org.springframework.ui.Model;
   8: import org.springframework.web.bind.annotation.RequestMapping;
   9: import org.springframework.web.bind.annotation.RequestMethod;
  10: import org.springframework.web.bind.annotation.RequestParam;
  11: import org.springframework.web.bind.annotation.ResponseBody;
  12: import org.springframework.web.context.WebApplicationContext;
  13: import org.springframework.web.context.support.WebApplicationContextUtils;
  14: import org.springframework.web.servlet.support.RequestContextUtils;
  15:  
  16: import com.zero.mvc.vo.Client;
  17:  
  18: @Controller
  19: @RequestMapping(value = "/hello", method = { RequestMethod.GET,
  20:         RequestMethod.POST })
  21: public class MyController {
  22:     @RequestMapping("/hello1")
  23:     // 当url有 ?name=xxx 也没关系
  24:     public String print1(HttpServletRequest request) {
  25:         System.out.println("/hello1");
  26:         // 根上下文
  27:         WebApplicationContext ct1 = WebApplicationContextUtils
  28:                 .getWebApplicationContext(request.getSession()
  29:                         .getServletContext());
  30:  
  31:         // DispatcherServlet的WebApplicationContext上下文springmvc上下文
  32:         // DispatcherServlet的上下文仅仅是 Spring MVC的上下文
  33:         WebApplicationContext ct2 = RequestContextUtils
  34:                 .getWebApplicationContext(request);
  35:         try {
  36:             System.out.println(111);
  37:             System.out.println(ct1);
  38:             System.out.println(ct1 == ct2);
  39:             System.out.println(ct1.containsBean("client"));
  40:             System.out.println(ct2.containsBean("client"));
  41:         } catch (Exception e) {
  42:             e.printStackTrace();
  43:         }
  44:         return "welcome";
  45:     }
  46:  
  47:     @RequestMapping("/hello2")
  48:     // url必须有 ?name=xxx
  49:     public String print2(@RequestParam("name") String name) {
  50:         System.out.println("/hello2");
  51:         System.out.println(name);
  52:         return "welcome";
  53:     }
  54:  
  55:     @RequestMapping("/hello3")
  56:     // url可有 ?name=xxx 也可没有
  57:     // 没有时name=null
  58:     public String print3(String name) {
  59:         System.out.println("/hello3");
  60:         System.out.println(name);
  61:         return "welcome";
  62:     }
  63:  
  64:     // 传值给前端
  65:     @RequestMapping(value = "/hello4")
  66:     public String print4(Model model) {
  67:         System.out.println("/hello3");
  68:         model.addAttribute("name", "zero");
  69:         // model.addAttribute(object);//直接以object的类型作为key
  70:         return "welcome";
  71:     }
  72:  
  73:     @RequestMapping(value = "/update")
  74:     @ResponseBody
  75:     public Client req(HttpServletRequest request, HttpServletResponse response) {
  76:         System.out.println("json");
  77:         Client client = new Client();
  78:         client.setAge(26);
  79:         client.setName("zero");
  80:         return client;
  81:     }
  82: }

 

   1: package com.zero.mvc.controller;
   2:  
   3: import javax.annotation.Resource;
   4:  
   5: import org.springframework.stereotype.Controller;
   6: import org.springframework.web.bind.annotation.RequestMapping;
   7: import org.springframework.web.bind.annotation.RequestMethod;
   8:  
   9: import com.zero.mvc.vo.Client;
  10:  
  11: @Controller
  12: @RequestMapping(value = "/spring", method = { RequestMethod.GET,
  13:         RequestMethod.POST })
  14: public class SController {
  15:  
  16:     @Resource(name = "client")
  17:     private Client client;
  18:  
  19:     @RequestMapping(value = "/hello")
  20:     public String get() {
  21:         System.out.println(11111);
  22:         return "welcome";
  23:     }
  24: }

 

   1: package com.zero.mvc.controller;
   2:  
   3: import javax.servlet.http.HttpServletRequest;
   4: import javax.servlet.http.HttpServletResponse;
   5:  
   6: import org.springframework.web.servlet.ModelAndView;
   7: import org.springframework.web.servlet.mvc.AbstractController;
   8:  
   9: public class WelcomeController extends AbstractController {
  10:  
  11:     @Override
  12:     protected ModelAndView handleRequestInternal(HttpServletRequest request,
  13:             HttpServletResponse response) throws Exception {
  14:         System.out.println("welcome");
  15:         return new ModelAndView("welcome");
  16:     }
  17: }

6.com.zero.mvc.intecepotor

   1: package com.zero.mvc.inteceptor;
   2:  
   3: import javax.servlet.http.HttpServletRequest;
   4: import javax.servlet.http.HttpServletResponse;
   5:  
   6: import org.springframework.web.servlet.HandlerInterceptor;
   7: import org.springframework.web.servlet.ModelAndView;
   8:  
   9: public class MyInteceptor implements HandlerInterceptor {
  10:  
  11:     @Override
  12:     // 最后执行,可用于释放资源,可以根据ex是否为null判断是否发生了异常,进行日志记录。
  13:     public void afterCompletion(HttpServletRequest request,
  14:             HttpServletResponse response, Object handler, Exception arg3)
  15:             throws Exception {
  16:         //配置了<bean id="exceptionResolver" 
  17:         //class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"/>
  18:         //后(全局的异常处理),ex一直都为空,也就是说这里记错误日志不行
  19:         //只有不使用全局的异常处理时,这里ex才不为空
  20:         //ex不为空时,记错误日志   
  21:         System.out.println("拦截器:---------释放资源--------");  
  22:  
  23:  
  24:     }
  25:  
  26:     @Override
  27:     //控制器执行完,生成视图之前可以执行
  28:     // 有机会修改ModelAndView
  29:     public void postHandle(HttpServletRequest request,
  30:             HttpServletResponse response, Object handler, ModelAndView arg3)
  31:             throws Exception {
  32:         System.out.println("拦截器:Action执行完,生成视图之前执行");
  33:     }
  34:  
  35:     @Override
  36:     // Action之前执行,可以进行编码、安全控制等处理
  37:     public boolean preHandle(HttpServletRequest request,
  38:             HttpServletResponse response, Object handler) throws Exception {
  39:         // 这里进行权限控制工作
  40:         System.out.println("拦截器:*********Action之前执行**********");
  41:         // return false;//不执行后续
  42:         return true;// 执行后续
  43:     }
  44:  
  45: }

7.com.zero.mvc.vo

   1: package com.zero.mvc.vo;
   2:  
   3: public class Client {
   4:     private String name;
   5:     private int age;
   6:  
   7:     public String getName() {
   8:         return name;
   9:     }
  10:  
  11:     public void setName(String name) {
  12:         this.name = name;
  13:     }
  14:  
  15:     public int getAge() {
  16:         return age;
  17:     }
  18:  
  19:     public void setAge(int age) {
  20:         this.age = age;
  21:     }
  22:  
  23: }

8.备注

applicationContext.xml相当与声明一个Spring容器来管理自己的实体bean,而springmvc-servlet.xml是SpringMVC的bean容器,管理controller等。访问 http://localhost:8080/mvc/hello/hello1 时会打印一下内容。

   1: 拦截器:*********Action之前执行**********
   2: /hello1
   3: 111
   4: Root WebApplicationContext: startup date [Sun Jan 11 17:24:49 CST 2015]; root of context hierarchy
   5: false
   6: true
   7: true
   8: 拦截器:Action执行完,生成视图之前执行
   9: 拦截器:---------释放资源--------

你可能感兴趣的:(SpringMVC学习)