文档章节

SpringMvc 框架阅读记录

lemos
 lemos
发布于 2016/11/18 09:50
字数 1061
阅读 4
收藏 0

简介

springmvc 是spring框架的一个模块,springmvc和spring 无需通过中间整合层进行整合。
springmvc是一个基于mvc的web框架。

MVC模式最早由Trygve Reenskaug在1978年提出[1],是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件架构。MVC模式的目的是实现一种动态的程式设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。软件系统通过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组:

  • 控制器(Controller)- 负责转发请求,对请求进行处理。
  • 视图(View) - 界面设计人员进行图形界面设计。
  • 模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。

 

MVC 在B/S 系统下的应用

 

SpringMVC框架

官方文档

Spring Web MVC 是基于 Servlet API 设计的,它被部署到 Servlet 容器 中

 

DispatcherServlet (前端控制器)

WebApplicationContext 是根据自己的配置对普通的 ApplicationContext 进行扩展。

它有一个指向 ServletContext 容器和其相关联的 Servlet 的连接。

 

1> Web 系统读取 web.xml 文件

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

...


<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>

 

2> ContextLoaderListener 寻找相应的 /WEB-INF/applicationContext*.xml 文件并加载

此时 Spring 创建一个 WebApplicationContext 对象,将其存储在 ServletContext 中。

注:可以通过下面的方法从 ServletContext 中获取当时的 WebApplicationContext。

WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);

 

Spring 容器分级

由下图可以看出 , DispatcherServlet 需要 WebApplicationContext。Web  ApplicationContext 一般 需要分级成 两级容器:一级是 Root WebApplicationContext,另一级是 Servlet WebApplicationContext 。前者被多个 servlet 共享,后者则是根据自己应用的 servlet 配置而来。

由图还可以看出,Root WebApplicationContext 与 Servlet WebApplicationContext  不是包含关系,只是存在引用Servlet WebApplicationContext 引用 Root WebApplicationContext

 


注:不分级的话,只有一个 单独的 WebApplicationContext 也是足够的,则所有 beans 都要从 Root WebApplicationContext 中获取。

 

再结合具体代码去理解:

1)通过 web.xml 配置 ServletContext(Servlet 容器),包含 RootApplicationContext 根容器,前端控制器( Servlet WebApplicationContext 子容器)

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value> // Root WebApplicationContext 根容器配置
    </context-param>

    <servlet>
        <servlet-name>app1</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/app1-context.xml</param-value> // Servlet WebApplicationContext 子容器配置
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app1</servlet-name>
        <url-pattern>/app1/*</url-pattern>
    </servlet-mapping>

</web-app>

2)引入了一个 前端控制器(包含一个 Servlet WebApplicationContext 子容器 )

import org.springframework.web.WebApplicationInitializer;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

3)引入了一个 前端控制器(包含一个 Servlet WebApplicationContext 子容器)

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

 

基本处理流程

上面的容器部署好了,下面开始 DispatcherServlet 处理请求:

用户发出请求 -> WebApplicationContext  绑定request 作为自己的一个属性,以便 Controller可以访问到。实际上也是绑定 request 到 Thread ->  locale resolver,theme resolver,multipart file resolver 依次绑定到 request ,让其决定使用哪个resolver -> 搜索合适的 handler 处理,执行链 preprocessors, postprocessors, and controllers,直接返回或填充 model -> 回收 model,渲染视图。

WebApplicationContext 上声明的 HandlerExceptionResolver 负责处理请求过程中的异常。

 

实际应用

HandlerMapping 可以实现 Interception 拦截器

  • preHandle(..) — before the actual handler is executed

  • postHandle(..) — after the handler is executed

  • afterCompletion(..) — after the complete request has finished

还支持 Filter(如 cors filter),这类 Filter 不包括在 servlet 中。注解 请看,RestTemplate 请看

 

参考资料

https://zh.wikipedia.org/wiki/MVC

https://spring.io/docs/reference

http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html

© 著作权归作者所有

共有 人打赏支持
lemos
粉丝 6
博文 178
码字总数 90644
作品 0
芜湖
后端工程师
Spring Cloud构建微服务架构服务注册与发现

Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、...

明理萝
06/11
0
0
Springsecurity学习

先上一张图,如下图1,此图来自于《Pro Spring security》的Chapter3。我觉得原文说的很好,建议读者看该书,内容是"Spring Security’s interception model of security applies to two mai...

克虏伯
09/03
0
0
Spring源码剖析开篇:Spring概述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a724888/article/details/73033273 欢迎阅读完整的专栏博客内容:Spring源码解析 本文首发于我的个人公众号:...

你的猫大哥
2017/06/11
0
0
教你十分钟构建好 SpringBoot + SSM 框架

目前最主流的 java web 框架应该是 SSM,而 SSM 框架由于更轻便与灵活目前受到了许多人的青睐。而 SpringBoot 的轻量化,简化项目配置, 没有 XML 配置要求等优点现在也得到了大众的青睐 而本...

全部原谅
07/30
0
0
【Spring Boot 实战开发】第2讲 Kotlin类型系统与空安全

Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。在 Java 开发领域的诸多著名框架:Spring 框架及其衍生框架、做缓存Redis、消息...

程序员诗人
04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

多线程

1. 多线程概念。并发和并行的概念。 多线程指的是一段时间内cpu同时执行多个线程。一个程序至少运行>=1个进程,进程就是运行中的程序,而一个进程至少运行>=1个线程,线程是操作系统能调度的...

鱼想吃肉
38分钟前
0
0
HBase 表修复在线方式和离线方式

一、在线修复 1.1 使用检查命令 $ ./bin/hbase hbck 该命令可完整修复 HBase 元数据信息;存在有错误信息会进行输出; 也可以通过如下命令查看详细信息: $ ./bin/hbase hbck -details 1.2 ...

Ryan-瑞恩
今天
2
0
redis 系列二 -- 常用命令

1.基础命令 info ping quit save dbsize select flushdb flushall 2.键命令 2.1 set 直接赋值 set a a 2.2 get 取值 get a 2.3 exists 是否存在 exists a 2.4 expire 设置剩余时间 秒 expire......

imbiao
今天
2
0
php foreach

<?php// 数组的引用$a=array(1,2,3,4,5);foreach($a as $key=>&$value){$value=$value*2;}print_r($a);echo " $key -------------------$value\r\n";/** * ...

小张525
今天
3
0
12-利用思维导图梳理JavaSE-多线程

12-利用思维导图梳理JavaSE-多线程 主要内容 1.线程概念 2.线程开发 3.线程的状态 4.线程的同步和死锁 5.Java5.0并发库类 QQ/知识星球/个人WeChat/公众号二维码 本文为原创文章,如果对你有一...

飞鱼说编程
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部