zoukankan      html  css  js  c++  java
  • 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. 将渲染结果返回给客户端。
  • 相关阅读:
    AX ERROR: Could not find my mock parent, most likely I am stale 不及格的程序员
    利用Segue在视图控制器间传值的问题 不及格的程序员
    Creating a Singleton Instance 不及格的程序员
    iPad 通知 UIKeyboardWillShowNotification 不会在keyBoard处在Undock状态下接到通知 不及格的程序员
    Why RootViewController's view is rotated Automatically by System when the app first loaded? 不及格的程序员
    如何弹出UIDatePicker最好 不及格的程序员
    jQuery开始做恶了 不及格的程序员
    what is the SEL,id and IMP,Class ,Method? 不及格的程序员
    Objectivec 字符串比较的陷井 不及格的程序员
    Unable to create any keyboard shortcuts after the iOS 6.1.3 update on iPad. 不及格的程序员
  • 原文地址:https://www.cnblogs.com/ouzilin/p/4993285.html
Copyright © 2011-2022 走看看