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. 将渲染结果返回给客户端。
  • 相关阅读:
    Docker容器进入的4种方式
    Linux启动/停止/重启Mysql数据库的方法
    MySQL replace函数替换字符串语句的用法(mysql字符串替换)
    php从数组中随机筛选出指定个数的值
    Beyond Compare 4 30天试用期后,破解方法
    MYSQL:1213 Deadlock问题排查历程
    uniapp 屏幕高度
    如何系统学习Spring框架
    mysql 批量修改表前缀
    DHCP中继配置案例
  • 原文地址:https://www.cnblogs.com/ouzilin/p/4993285.html
Copyright © 2011-2022 走看看