zoukankan      html  css  js  c++  java
  • SpringMVC详细流程(一)

      Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
    与之相反的是基于组件的、事件驱动的Web框架,如Tapestry、JSF等。
      Spring Web MVC也是服务到工作者模式的实现,但进行可优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

      SpringMVC在Web应用中充当控制层(Controller)的角色,对请求进行分发处理。

    一、Spring请求流程

    1. 整体流程

     具体步骤:

    • 首先用户发送请求到前端控制器,前端控制器根据请求信息(如 URL)来决定选择哪一个页面控制器进行处理并把请求委托给它,即以前的控制器的控制逻辑部分;图中的 1、2 步骤;
    • 页面控制器接收到请求后,进行功能处理,首先需要收集和绑定请求参数到一个对象,这个对象在 Spring Web MVC 中叫命令对象,并进行验证,然后将命令对象委托给业务对象进行处理;处理完毕后返回一个 ModelAndView(模型数据和逻辑视图名);图中的 3、4、5 步骤;
    • 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染;图中的步骤 6、7;
    • 前端控制器再次收回控制权,将响应返回给用户,图中的步骤 8;至此整个结束。

    2. 核心流程

    具体步骤:

    • 第一步:发起请求到前端控制器(DispatcherServlet)
    • 第二步:前端控制器请求HandlerMapping查找 Handler (可以根据xml配置、注解进行查找)
    • 第三步:处理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略
    • 第四步:前端控制器调用处理器适配器去执行Handler
    • 第五步:处理器适配器HandlerAdapter将会根据适配的结果去执行Handler
    • 第六步:Handler执行完成给适配器返回ModelAndView
    • 第七步:处理器适配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一个底层对象,包括 Model和view)
    • 第八步:前端控制器请求视图解析器去进行视图解析 (根据逻辑视图名解析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可
    • 第九步:视图解析器向前端控制器返回View
    • 第十步:前端控制器进行视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域)
    • 第十一步:前端控制器向用户响应结果

    下面我们对出现的一些组件进行详细的介绍:

    (1) 前端控制器DispatcherServlet(不需要程序员开发)。
      作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。
    (2) 处理器映射器HandlerMapping(不需要程序员开发)。
      作用:根据请求的url查找Handler。
    (3) 处理器适配器HandlerAdapter(不需要程序员开发)。
      作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。
    (4) 处理器Handler(需要程序员开发)。
      注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
    (5) 视图解析器ViewResolver(不需要程序员开发)。
      作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
    (6) 视图View(需要程序员开发jsp)。
      注意:View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

    ps:不需要程序员开发的,需要程序员自己做一下配置即可。

    可以总结出:需要我们开发的工作只有处理器 Handler 的编写以及视图比如JSP页面的编写。可能你还对诸如前端控制器、处理器映射器等等名词不太理解,那么接下来我们对其进行详细的介绍。

    二、SpringMVC组件配置或开发说明

    根据前面所说,部分组件需要配置,部分组件需要程序员开发,接下来就介绍下如何配置和开发相关的组件。

    1. 配置前端控制器(DispatcherServlet)

    在web project的web.xml中配置:

    <!-- 配置前端控制器DispatcherServlet -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--springmvc.xml 是自己创建的SpringMVC全局配置文件,用contextConfigLocation作为参数名来加载 
            如果不配置 contextConfigLocation,那么默认加载的是/WEB-INF/servlet名称-servlet.xml,在这里也就是 
            springmvc-servlet.xml 参数多个值使用逗号隔开,如:a.xml,b.xml -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:springmvc.xml</param-value>
        </init-param>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--第一种配置:*.do,还可以写*.action等等,表示以.do结尾的或者以.action结尾的URL都由前端控制器DispatcherServlet来解析 
            第二种配置:/,所有访问的 URL 都由DispatcherServlet来解析,但是这里最好配置静态文件不由DispatcherServlet来解析,需要对静态资源单独处理 
            错误配置:/*,注意这里是不能这样配置的,因为如果这样写,最后转发到 jsp 页面的时候,仍然会由DispatcherServlet进行解析, 而这时候会找不到对应的Handler,从而报404!!! -->
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    2. 配置处理器映射器(HandlerMapping)

    在 springmvc.xml 文件中配置。通俗来讲就是请求的 URL 怎么能被 SpringMVC 识别,从而去执行我们编写好的 Handler。

    (1) 第一种方法

    <!-- 配置Handler -->   
    <bean name="/hello.do" class="com.asiainfo.spring.controller.HelloController" />
     
    <!-- 配置处理器映射器 将bean的name作为url进行查找,需要在配置Handler时指定bean name(就是url)-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

    这样配置的话,那么请求的 URL,必须为 http://ip:port/项目名/hello.do

    (2) 第二种方法

    <!-- 配置Handler -->   
    <bean id="hello" class="com.asiainfo.spring.controller.HelloController" />
    <bean id="hello2" class="com.asiainfo.spring.controller.HelloController2" />
    <!-- 简单URL配置处理器映射器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/hello.do">hello</prop>
                <prop key="/hello2.do">hello2</prop>
            </props>
        </property>
    </bean>

    这种配置请求的 URL可以为 http://ip:prot/项目名/hello.do,或者http://ip:port/项目名/hello2.do

    注:上面两种处理器映射器配置可以并存,前端控制器会正确的去判断 url 用哪个 Handler 去处理。

    3. 配置处理器适配器(HandlerAdapter)

    在 springmvc.xml 文件中配置。用来约束我们所需要编码的 Handler类。

    第一种配置:编写 Handler 时必须要实现 Controller,否则不能被适配器解析。

    <!-- 配置处理器适配器,所有适配器都得实现 HandlerAdapter接口 -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

    第二种配置:编写 Handler 时必须要实现 HttpRequestHandler

    <!-- 配置处理器适配器第二种方法,所有适配器都得实现 HandlerAdapter接口 ,这样配置所有Handler都必须实现 HttpRequestHandler接口-->
    <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />

    4. 开发处理器(Handler,即我们的Controller)

    在 springmvc.xml 文件中配置。通俗来讲,就是请求的 URL 到我们这里所编写的 Handler 类的某个方法进行一些业务逻辑处理。
    我们在上面讲解了两个处理器适配器来约束 Handler,那么我们就通过上面两种配置分别编写两个 Handler:

    (1) 第一种:实现Controller 接口

    public class HelloController implements Controller {
    
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            ModelAndView modelView = new ModelAndView();
            modelView.setViewName("/WEB-INF/jsp/index.jsp");
            return modelView;
        }
    }

    (2) 第二种:实现 HttpRequestHandler 接口

    public class HelloController2 implements HttpRequestHandler {
        public void handleRequest(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            request.setAttribute("name", "harvey");
            request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response);
        }
    }

    通常我们使用第一种方式来编写 Handler ,但是第二种没有返回值,我们可以通过 response 修改相应内容,比如返回 json 数据:
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=utf-8");
    response.getWriter().write("json字符串");

    所以具体使用哪一种根据实际情况来判断。

    5. 配置视图解析器(ViewResolver)

    第一种配置:

    <!-- 配置视图解析器 进行jsp解析,默认使用jstl标签,classpath下得有jstl的包-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />

    如果这样配,那么在 Handler 中返回的必须是路径+jsp页面名称+".jsp"

    第二种配置:

    <!--配置视图解析器  -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 返回视图页面的前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <!-- 返回页面的后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

    如果这样配,那么在 Handler 中只需要返回在 jsp 文件夹下的jsp 页面名就可以了。

    6. DispatcherServlet.properties

    上面我们讲解了各种配置,可能有人会问这么多配置,万一少配置了一样,那不就不能运行了,那我们能不能不配置呢?答案是肯定的,SpringMVC 给我们提供了一个 DispatcherServlet.properties 文件。系统会首先加载这里面的配置,如果我们没有配置,那么就默认使用这个文件的配置;如果我们配置了,那么就优先使用我们手动配置的。

    在 SpringMVC 运行之前,会首先加载 DispatcherServlet.properties 文件里面的内容
    ①、处理器适配器默认:org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
    ②、处理器映射器默认:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
    ③、视图解析器默认:org.springframework.web.servlet.view.InternalResourceViewResolver

    时刻与技术进步,每天一点滴,日久一大步!!! 本博客只为记录,用于学习,如有冒犯,请私信于我。
  • 相关阅读:
    Hanoi塔
    采药
    进制转换(大数)
    Load Balancing with NGINX 负载均衡算法
    upstream模块实现反向代理的功能
    epoll
    在nginx启动后,如果我们要操作nginx,要怎么做呢 别增加无谓的上下文切换 异步非阻塞的方式来处理请求 worker的个数为cpu的核数 红黑树
    粘性会话 session affinity sticky session requests from the same client to be passed to the same server in a group of servers
    负载均衡 4层协议 7层协议
    A Secure Cookie Protocol 安全cookie协议 配置服务器Cookie
  • 原文地址:https://www.cnblogs.com/myitnews/p/11565941.html
Copyright © 2011-2022 走看看