Web应用程序中服务端消息处理机制探究—以Spring框架为例

1 Servlet概述

Servlet命名的想法来自于存在于客户端的、用Java编写的小程序技术Applet,是存在于服务器端、根据程序员编写的处理逻辑处理用户传输过来的数据的应用程序,所以被称作Server上的Applet。狭义上来讲Servlet就是一个拥有init(ServletConfig)、destroy()、service(ServletRequest,ServletResponse)、getServletConfig()、getServletInfo()方法的Java接口。这五个函数定义了Servlet开始和结束的动作、怎么执行业务逻辑与Servlet的一些必要信息的获取。

init()与destroy()方法分别用来初始化(与加载load相区分)与释放Servlet实例,其中Servlet只在第一次运行时初始化,其主要工作是通过配置对象参数将Servlet的配置信息保存起来。service()方法通过写入开发者所需要的处理逻辑来处理传入Servlet的数据,返回值为void的函数service()包含了两个参数,一个是保存了客户端发送过来的请求的各种属性的ServletRequest,另一个是与之对应的用于设置如何响应客户端的ServletResponse[1]。另外两个参数getServlet()与getServletInfo()分别用于获取Servlet配置对象与字符串格式的Servlet基本信息。

2 Servlet容器

2.1 Servlet容器简介

Servlet其本身并不与消息直接接触也不负责管理客户对资源的访问,而是由Servlet容器来监听和接收客户端的消息,Servlet只需要处理整个数据事务处理过程的某些部分,只有通过Servlet容器的调度才能生效。每个容器允许容纳多个Servlet,并且由容器决定将消息交由哪个Servlet来处理,待Servlet处理完成后予以反馈。当下由各公司开发的Servlet容器有很多并且其中以tomcat使用最为广泛。

2.2 Tomcat架构

Web应用程序中服务端消息处理机制探究—以Spring框架为例_第1张图片 图1 Tomcat架构

如图1所示,Server是Tomcat最外层的一个容器,工作时可以将其看做一个Tomcat。Server上面允许运行数量不止一个、代表着一套完整的服务的Service并且由数量至少为一个的Connector连接器与数量只允许为一个的Container构成的Service服务。Connector用于监听、获取和回复Client传来的消息,它是Tomcat中最先接触到客户端消息的组件,而且内部还有许多监听接收消息与解析Socket的组件,将在小节3予以介绍。

Container内部由后面所述的几种层层包含的子容器所构成,它们分别是Engine、Host、Context与Wrapper。Engine是Service的引擎,一个服务只允许有一个引擎来驱动,一个引擎上允许有多个虚拟主机的运行。因此图中所示有多个Host容器工作在Engine上。Host容器上又承载着一定数量的应用程序的上下文实例——Context,一个Host上可以运行一定数量的应用。每个应用程序上下文包含多个用来封装Servlet的Wrapper。

2.3 Servlet容器与Web服务器的关系

以当下最流行的Web服务器Apache为例,Apache通常只用来访问静态资源,虽然有CGI协议来进行动态资源的访问,但是CGI技术已经落后。而Servlet容器的目的就在于在服务器端动态生成网页,Servlet容器一般架设在Web服务器上(Apache可以单向联通Tomcat)但也可以单独使用(二者均接收HTTP请求)。

因此尽管以其灵活的配置与支持交互性Tomcat可以被当做Web服务器来使用,但是它归根结底还是一个Servlet容器,通常与Apache搭配使用。

3 Tomcat消息处理机制

Web应用程序中服务端消息处理机制探究—以Spring框架为例_第2张图片 图2 Connector消息处理机制

 参照图1,Tomcat的消息处理机制如下,由于Servlet本身并没有Main函数,所以它的方法全部由Tomcat来操控:

(1)Tomcat通过一个Connector接收到HTTP请求。

(2)Connector解析请求并将消息映射到相应的Engine上。Connector组件及解析流程如图2所示,ProtocolHandler有不同种类,解析不同的套接字,它包括了三种部件:EndPoint内的Acceptor用来监听消息,Handler模块从Acceptor获取套接字并将其传给Processor;Processor从前一个模块接收到套接字后,将其解析为HTTP请求传递给Adapter模块。最后到达Container。

(3)Tomcat检查Servlet是否被已经被加载,如果没有,则通过JVM实例化一个Servlet。

(4)Tomcat通过Servlet的init()方法初始化Servlet,该方法传入一个ServletConfig对象告诉Tomcat Servlet的配置信息和可能需要的资源,Tomcat需要将这些资源准备好管理好。

(5)一旦Servlet初始化完成,其service()方法就可以被调用去处理请求了。

(6)在Servlet的生命周期内(从Servlet被加载到被销毁的全过程)Tomcat通过监听类实时监听Servlet的状态,Tomcat可以以各种方式保存和检索这些状态的更改,并且允许其他Servlet访问这些状态,这些状态由同一Context下各类组件通过一个或多个用户Session进行访问与维护。在一个应用中一个用户的Session即使在客户端切换路由的时候仍然会得以维护和保存。

(7)最后,或由被监控的状态的更改触发,或由Tomcat接收的外部命令触发,Tomcat调用Servlet的destroy()函数销毁Servlet。

4 Spring MVC消息处理机制

4.1 Spring MVC简介

Spring MVC是Spring家族中依据MVC(Model-View-Controller)设计模式开发的模型框架,和Spring家族的其他产品一样,它以Spring引擎为基础,消除了重复代码的编写,减小了Web开发中代码的耦合。Spring MVC主要由分发器或叫作前端控制器(DispatcherServlet)、控制器(Controller)、模型和视图(ModelAndView)等组件构成,一般Spring MVC默认使用Tomcat。

MVC设计模式中Model代表了程序的数据及访问、处理数据的业务逻辑;View负责把视图或者模型数据展示给用户;Controller负责接收用户的输入、将请求分配给相应的业务逻辑并将结果反馈给视图,用于管理Model与View之间的交互。这样的设计模式使得模型与视图可以拥有“一对多”的关系,只需修改一个模型中的代码就可以改变视图从而减少了代码的重复编写[2],而且在保持公用接口的前提下,各部分可以轻松扩展而不会影响到其他部分[3]。

4.2 Servlet与Spring MVC的关系

Web应用程序中服务端消息处理机制探究—以Spring框架为例_第3张图片 图3 Servlet消息传输示意图

 

Web应用程序中服务端消息处理机制探究—以Spring框架为例_第4张图片 图4 “三层架构”下消息传输示意图

在Web还是利用Servlet进行开发的时代,为了能应付不同的处理要求,Tomcat抽出一块(Servlet)给开发者自行编写处理逻辑,如图3所示,后来为了方便开发出现了解耦合的三层架构(Controller-Service-Dao),于是原来Servlet的处理逻辑被Controller、Service和Dao三个部分所分担。Spring MVC在用户进行编程的时候同样遵循这个三层架构,它用一个扩展的Servlet——DispatcherServlet来分发请求和转发一些模块产生的中间数据,调度各个模块的运作,如图4所示。

Spring MVC中DispatcherServlet有着很长的一段“继承链”,这个继承链的顶端是“祖先”GenericServlet抽象类。“继承链”中间从底端到顶端依次为FrameworkServlet、HttpServletBean、HttpServlet类。本质上来讲,DispatcherServlet就是一个将通用Servlet经过HTTP定义、将Servlet功能与Web应用程序上下文集成在一起、被封装成适合Spring MVC的Servlet。

另外Spring MVC在运作的时候,会创建Spring容器和Spring MVC容器,它们分别是父容器和子容器,父容器用来存放service层、Dao层以及实体类,子容器存放Spring MVC的各种组件包括前端控制器、处理器适配器、controller等,子容器只能单向访问父容器。

所以综上所述,Spring MVC是一个Web开发的框架,遵循这个框架的规范可以帮助我们以轻耦合更便捷的方式来开发程序,Servlet是Tomcat里面的一个小程序。由于Spring MVC容器的组件都是围绕着DispatcherServlet运作的,所以归根结底Spring MVC还是在使用Servlet来工作。

4.3 Spring MVC处理消息的流程

Web应用程序中服务端消息处理机制探究—以Spring框架为例_第5张图片 图5 Spring MVC运行流程

在初始化的时候,Spring MVC会根据Controller层的注解代码解析为资源URI和处理器Handler之间的映射关系HandlerMapping,并且生成HandlerExecutionChain(包含用来执行控制器Controller的方法的处理器与其对应的拦截器),这个执行链里包括了开发者利用“三层架构”写出的Controller层、Service层、Dao层的处理逻辑。另外,Spring MVC会按照Context上下文实例化化处理器适配器、视图解析器等组件。

如图5所示,在消息来到的时候,Spring MVC的消息处理机制如下:

(1)当消息到来时,DispatcherServlet通过映射关系获取待执行的执行链,但是此时还不能执行执行链,缺乏处理器适配器。

(2)通过Context上下文获取HandlerAdapter,然后才可以运行处理器。由于处理程序的对象类型有很多,此时需要一个能够与处理程序“对话”的处理器适配器才能运行得起来,这个适配器由DispatcherServlet默认实例化。

(3)获取适配器后执行HandlerExecutionChain执行链处理消息,返回模型和视图给DispatcherServlet。

(4)DispatcherServlet获取到处理器返回的Model和View后,如果视图信息是逻辑视图(视图名),DispatcherServlet将视图信息传送给视图解析器ViewResolver解析出视图View。如果视图信息封装的是视图View,则不需要执行本过程[4]。

(5)DispatcherServlet将数据模型渲染到视图上,反馈给用户。

5 总结

Web开发由最早的只能传输静态资源到serlvet开发再到快速更新迭代的三层架构Web开发框架,这些越来越高级的封装使Web开发越来越便捷,但是同样也使人们越来越看不清底层的实现过程。其实,Spring框架下还是Servlet在帮助我们做事情,只不过Spring MVC为了帮助我们省去了部分原本需要在Servlet里做的重复性的事情,在Servlet之上拓展了一些组件,它并没有改变Servlet在底层的运作方式。


【参考文献】

[1]邹靖霖,李树英.用Servlet开发Web应用[J].计算机应用研究,2001(03):125-126.

[2]郑建华,朱蓉,邱振国.基于Servlet的MVC控制器框架设计[J].计算机时代,2015(04):43-46.

[3]张砚秋,陈川,何明德.基于MVC设计模式构筑JSP/Servlet+EJB的Web应用[J].计算机工程,2001(11):71-73.

[4]邵刚. 基于Spring框架的MVC控制器的优化与改进[D].山东大学,2011.

你可能感兴趣的:(Java开发,spring,servlet,tomcat)