Spring MVC学习(一)----原理分析

环境 Spring 4.2.3
一下内容学习总结于《精通Spring 4.x——企业应用开发实战》,跟开涛学习Spring MVC

Spring MVC 体系结构

来自网络
整个框架中DispatcherServlet处于核心的位置,他负责协调和组织不同 的组件以完成请求处理并返回相应的工作。 Spring MVC通过一个前端Servlet接受所有的请求,并将具体的工作委托 给其他组件进行处理,DispatcherServlet就是SpringMVC的前端的Servlet。

下面对Spring MVC处理请求的整体过程讲解

  1. 客户端发出一个HTTP请求,Web应用服务器接受到这个请求,如果匹配 DispatcherServlet的请求映射路径(在web.xml指定),则Web容器将请求转 交给 DispatcherServlet 处理。例如:
 <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.html</url-pattern>
        <!--通过servlet-mapping指定DispatcherServlet处理所有的.html为后缀的http请求-->
    </servlet-mapping>
  1. DispatcherServlet接受处理这个请求后,根据这个请求的信息(URL,请 求参数,报文头,Cookie等)以HandlerMapping的配置找到处理请求的处理器(Handler)。可将HanderMapping看作路由控制器,将Handlei•看作目标 主机。实际上任伯I 一个Object都可以看作请求处理器。
  2. 当DispatcherServlet根据HandlerMapping得到对应当前请求的Hanlder 后,通过HandlerAdapter对Handler进行封装,再以统一的是适配器接口调用 Handler。HandlerAdapter是一个适配器,它用统一的接口对各种Handler方法 进行调用。
  3. 处理器完成业务逻辑的处理后将放回的ModelAndView给 DispatcherServlet, ModelAnd View包含了视图逻辑名,和模式数据信息。
  4. ModelAndView包含逻辑视图名而非是真正的视图对象。DispatcherServlet 倍由ViewResolver完成逻辑视图名到真实视图对象的解析工作。
  5. 得到真正的视图对象View后,DispatchersServlet就使用这个View对象对 ModelAndView中的模型数据进行视图渲染。
  6. 最终返回到客户到的可能是HTML, XML、JSON、PDF等

以上每一步骤都包含丰富的知识点。

要了解Spring MVC 框架机制工作机理,也要知道几个问题

问题

  1. DispatcherServlet框架如何拦截特定的HTTP请求,并交由Spring MVC处理?
  2. 位于Web层的Spring容器(WebApplicationContext)如何与位于业务层的Spring容器(ApplicationContext)建立关联,以使Web层的Bean可以调用业务层的Bean?
  3. 如何初始化SpringMVC的各个组件,并将他们装配到DispatcherServlet中?

项目结构

1、配置DispatcherServlet,截取特定的URL请求。

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- ① -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/appcationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet><!-- ② -->
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping><!-- ③ -->
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.html</url-pattern>
        <!--通过servlet-mapping指定DispatcherServlet处理所有的.html为后缀的http请求-->
    </servlet-mapping>
</web-app>

①:contextConfigLocation:,表示用于加载Bean的配置文件。通过contextConfigLocation参数指定业务层Spring容器的配置文件;
②:配置名为springmvc的DispatcherServlet,他默认会自动加载/WEB/INF/springmvc-servlet.xml(servlet-Name-servlet.xml)的Webc层的Spring配置文件,启动Web层的Spring容器。
③:所有带.html为后缀的HTTP请求会被DispatcherServlet截获处理。

我们也可通过Java 编程方式来配置Servlet容器。不需要web.xml,思路一样
参考官方描述

将web,xml文件的配置全部注解掉,添加SpringmvcApplicationInitializer类,实现WebApplicationInitializer接口。 启动,效果是一样的。

package com.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class SpringmvcApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("/WEB-INF/springmvc-servlet.xml");
        ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(appContext));
        dynamic.setLoadOnStartup(1);
        dynamic.addMapping("*.html*");
    }
}

可能有人会疑问为什么实现WebApplicationInitializer接口就能配置Servlet了呢?

在Spring 3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer的类,如果返现有实现的类,就会调用它,配置Servlet容器。在Spring中,org.springframework.web.SpringServletContainerInitializer类实现了ServletContainerInitializer接口,同时这个类会查找实现org.springframework.web.WebApplicationInitializer接口的类,并将配置任务交给这些实现类去完成。

扩充知识:

applicationContext.xml与servlet-Name-servlet.xml 区别,关系与加载顺序
引言:

  1. 多个Spring容器之间可设置子父的关系的,以实现良好的解耦。

  2. 这里“Web层”Spring容器将作为“业务层”Spring容器的子容器,即 “Web层”容器可以引用“业务层”容器的Bean,而“业务层”容器访问不到“Web层”容器的Bean。

关系与区别:

  1. applicationContext.xml文件通常用于加载业务层spring系统级别的组件,比如bean的初始化
  2. servlet-Name-servlet.xml文件通常用于加载controller层需要的类,比如拦截器,mvc标签加载的类
  3. 如果直接使用SpringMVC是可以不添加applicationContext.xml文件的,其实我的applicatiContext.xml是空,如下。因为applicationContext.xml是随着ContextLoaderListener的加载儿执行的。由于没有配置applicationContext.xml所以我们就可以去掉web.xml文件中的 context-param标签、listener标签。
    直接采用SpringMVC,只需要把所有相关配置放到servlet-Name-servlet.xml中就OK了

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--没有内容-->
</beans>

加载先后:
以下内容摘自
首先applicationContext.xml是随ContextLoaderListener的加载而执行的,而servlet-Name-servlet.xml是随DispatcherServlet的加载而执行的,在web.xml中;
加载顺序是listener>filter>servlet;

2、探究DispatcherServlet的内部逻辑

DispatcherServlet详解
图三

来自网络

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值