springMVC

 spring MVC在性能上是要比struts2要好的。struts2的性能低的原因是因为OGNL和值堆造成的,在springMVC中,如果并发性比较高,可以用freemaker进行显示,而不是用OGNL和值栈,这样性能上会有很大的提高。

springMVC运行流程图(在网上找的)

这个图化的很好,比官方文档的画的好多了

这里需要了解一个dispatcherServlet的初始化

  1.把初始化的那些init-param读到Servlet的属性里。我们知道Servlet的init-param是放在ServletConfig里的,我们可以用循环去取这些属性。但是每次都这么干实在太累了,干吗不把在Servlet里增加几个property,再这些init-param直放到Servlet的property里呢?呵呵,以后那些初始参数都可以直接拿来用啦,真方便。DispatchServlet的一个祖先类叫做HttpServletBean就是专门干这个的。以后假如我们要写自己的Servlet也可以直接继承HttpServletBean这个类,这样读ServletConfig的操作都省掉了,哈哈!

  2.从ServletContext里取出ApplicationContext,并扩展成自己的ApplicationContext.

  在Spring MVC里,我们却可以有好多个Servlet!它们可以处理不同类型的request,而且更重要的是它们的ApplicationContext不是相同的,它们共享了一个父ApplicationContext,也就是从ServletContext里取出来的那个,但是它们却会根据自己的配置作扩展,形成这个Servlet特有的ApplicationContext。这个子的ApplicationContext里有自己的namespace,也就是将一个叫做(假如servlet名称叫xiecc) xiecc-servlet.xml的配置文件读进来,行成一个自己的ServletContext。所以这些过程全是在DispatchSevlet的一个父类FrameworkServlet里干的

  3.初始化dispatcherServlet的接口,将applicationcontext定义好的接口注入dispatcherServlet中

initMultipartResolver();

initLocaleResolver();

initThemeResolver();

initHandlerMappings();

initHandlerAdapters();

initHandlerExceptionResolvers();

initViewResolvers();

  dispatcherServlet是不负责具体的操作的,他将具体的操作都委托给相应的接口,这是Template Method的Strategy模式

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

  这里在web.xml中配置dispatcherServlet,文档解释dispatcherServlet    Central dispatcher for HTTP request handlers/controllers,Dispatches to registered handlers for processing a web request, providing convenient mapping and exception handling facilities意思基本是处理request请求并注册handlers

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/hib-config.xml,/WEB-INF/springmvc-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

  2.DispatcherServlet对请求URL进行解析。DispatcherServlet里面的BeanNameUrlHandlerMapping这个类实现了HandlerMapping这个接口。用来实现映射(The mapping is from URL to bean name)。BeanNameUrlHandlerMapping 的解释

Implementation of the org.springframework.web.servlet.HandlerMapping interface that map from URLs to beans with names that start with a slash ("/"), similar to how Struts maps URLs to action names.

用的多的还是handlerMapping的SimpleUrlHandlerMapping,

这是dispatcherServlet中定义的handlerMapping的集合

 

    /** List of HandlerMappings used by this servlet */
    private List<HandlerMapping> handlerMappings;

 

这里我请求的url

http://oulin:8080/springMVC/user.do?uname=123&method=reg3

requestUrl字符串一截,拿到"/user.do"再去handlerMappings里去找对应的"/user.do",将对应的controller和一组interceptor组装成handlerExecutionChain。
<mvc:interceptors>中拿到一组interceptor

<?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:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd    
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd    
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <!-- 对web包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
    <context:component-scan base-package="com.sxt.web" />
    
    <mvc:annotation-driven />  <!-- 支持spring3.0新的mvc注解 -->
    <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="cacheSeconds" value="0" />
        <property name="messageConverters">
            <list>
                <bean
                    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
            </list>
        </property>
    </bean>
    <mvc:interceptors>
        <bean class="com.sxt.interceptor.MyInterceptor"></bean> <!-- 拦截所有springmvc的url! -->
        <mvc:interceptor>
            <mvc:mapping path="/user.do" />
            <!--<mvc:mapping path="/test/*" />-->
            <bean class="com.sxt.interceptor.MyInterceptor2"></bean>
        </mvc:interceptor>
    </mvc:interceptors>




    <!--对模型视图名称的解析,即在模型视图名称添加前后缀 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:suffix=".jsp">
        <!-- 如果使用jstl的话,配置下面的属性 -->
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
    </bean>

    <!-- 处理文件上传 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="gbk" /> <!-- 默认编码 (ISO-8859-1) -->
        <property name="maxInMemorySize" value="10240" /> <!-- 最大内存大小 (10240)-->
        <property name="uploadTempDir" value="/upload/" /> <!-- 上传后的目录名 (WebUtils#TEMP_DIR_CONTEXT_ATTRIBUTE) -->
        <property name="maxUploadSize" value="-1" /> <!-- 最大文件大小,-1为无限止(-1) -->
    </bean>


</beans>

userController.java

package com.sxt.action;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import com.sxt.po.User;
import com.sxt.service.UserService;

@Controller
@RequestMapping("/user.do")
@SessionAttributes({"u","a"})
public class UserController  {
    @Resource
    private UserService userService;
    @RequestMapping(params="method=reg")
    public String reg(String uname){
        System.out.println("UserController.reg()");
        System.out.println(uname);
        userService.add(uname);
        return "index";
    }
    @RequestMapping(params="method=reg2")
    public ModelAndView reg2(User user){
        System.out.println("UserController.reg2()");
        System.out.println(user.getUname());
        ModelAndView mav = new ModelAndView("index");
        return mav;
    }
    @RequestMapping(params="method=reg3")
    public String reg3(@RequestParam("uname") String name,HttpServletRequest req,ModelMap map){
        System.out.println("UserController.reg()");
        System.out.println(name);
        req.getSession().setAttribute("c", "ccc");
        map.put("a", "aaa");
        return "index";
    }
    @RequestMapping(params="method=reg4")
    public String reg4(@ModelAttribute("a") String a,HttpServletRequest req,ModelMap map){
        System.out.println("UserController.reg4()");
        System.out.println(a);
        return "redirect:http://www.baidu.com";
    }
    @RequestMapping(params="method=reg5")
    public ModelAndView reg5(String uname){
        System.out.println("UserController.reg5()");    
        ModelAndView mav = new ModelAndView();
        mav.setViewName("index");        
        User u = new User("123");
        User u2 = new User("1234");
        mav.addObject(u);
        mav.addObject("uu", u2);
        return mav;
    }
    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    
}

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

我前面说了HandlerExecutionChain就是一个Controller和一组interceptors。这是我们执行一个request最基本的单元啦。

不过现实情况会稍有些出入,HandlerExecutionChain实际上包括的一个Object和一组interceptor。这个Object是Adaptor,它可以是Controller的Adaptor,也可以是其它类的Adaptor。但现实中我们一般用到的都是Controller,因此不详细分析啦,这里用了Adaptor后大大降低了代码的可读性,来换取与Controller非紧耦合的灵活性。至少我现在认为这样做不是太值。

  4.  提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
      HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
      数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
      数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
      数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
      5.  Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
详见method=reg2
      6.  根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
 
      7. ViewResolver 结合Model和View,来渲染视图
      8. 将渲染结果返回给客户端。

 

posted @ 2015-11-25 10:27  俗家弟子  阅读(234)  评论(0编辑  收藏  举报