How Tomcat Works 5

2024-03-15 00:32
文章标签 tomcat works

本文主要是介绍How Tomcat Works 5,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一节简单介绍了tomcat中的流水线,当connector收到一条消息的时候,将socket交给processor来处理,processor构造出来request和response对象并解析http请求,然后processor调用container的的invoke方法来处理这两个对象。invoke方法是父类ContainerBase中的方法,主要是调用该Container对应的Pipeline处理请求。Tomcat中StandardEngine对应的pipeline是StandardPipeline,其中的basicValve是StandardEngineValve,每个basicValve都是该容器中最后被调用的valve。它其中的一个任务便是调用自己下层组件的invoke方法,继续流水线的处理,直到最后的的wrappervalve。值得提一点的是一个servlet对应一个wrapper。流程图如下:


本节重点介绍的是tomcat处理一个请求的大体过程。

在tomcat的外层web.xlm会配置一个默认的serverlet——org.apache.catalina.servlets.DefaultServlet当根据mapping未匹配到需要处理的servlet的时候,会使用该servlet处理请求,DefaultServlet在tomcat启动的时候便会被加载。

假设我们访问的地址为http://localhost:8080/myapp/primi myapp是我自己写的一个app,非常简单的结构如下:


在WEB-INF下只有一个web.xml,配置了servlet的映射关系

  <servlet><servlet-name>PrimitiveServlet</servlet-name><servlet-class>PrimitiveServlet</servlet-class><init-param><param-name>debug</param-name><param-value>2</param-value></init-param></servlet><!-- Define the Manager Servlet Mapping --><servlet-mapping><servlet-name>PrimitiveServlet</servlet-name><url-pattern>/primi</url-pattern></servlet-mapping>

那么下面就来看看tomcat是如何一步步找到这个servlet并处理我们的请求的。


connector将收到的请求交给Engine来处理,一个在Engine的标准valve中会调用下面的方法来匹配到对应的host

// Select the Host to be used for this RequestStandardEngine engine = (StandardEngine) getContainer();Host host = (Host) engine.map(request, true);if (host == null) {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST,sm.getString("standardEngine.noHost",request.getRequest().getServerName()));return;}// Ask this Host to process this requesthost.invoke(request, response);
可以看到通过engine的map方法找到对应的host,其中在tomcat4版本中匹配url的过程是通过Mapper类完成的,这里会匹配到标识为localhost的Host容器,也就是所有对localhost的访问都会由localhost容器处理,获取到对应的Host后调用它的invoke方法,接下来的处理过程类似上面。

// Select the Context to be used for this RequestStandardHost host = (StandardHost) getContainer();Context context = (Context) host.map(request, true);if (context == null) {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,sm.getString("standardHost.noContext"));return;}
Context对应的就是webapps目录下一个个的应用程序,由Host匹配合适Context的方法在StandardHostMapper类中:

public Container map(Request request, boolean update) {// Has this request already been mapped?if (update && (request.getContext() != null))return (request.getContext());// Perform mapping on our request URIString uri = ((HttpRequest) request).getDecodedRequestURI();Context context = host.map(uri);// Update the request (if requested) and return the selected Contextif (update) {request.setContext(context);if (context != null)((HttpRequest) request).setContextPath(context.getPath());else((HttpRequest) request).setContextPath(null);}return (context);}
获取到uri,该例子中为/myapp/primi。由于我们在server.xml中配置了localhost下有一个名字为myapp的Context,所以按照从后往前按照反斜杠/截取的过程,最终会匹配到mayapp这个context,同样类似上面的处理过程,context的invoke方法会被调用。也就是请求和响应消息被传递给名字为myapp的context来处理。

StandardContextValve中队消息的处理代码如下:

Context context = (Context) getContainer();// Select the Wrapper to be used for this RequestWrapper wrapper = null;try {wrapper = (Wrapper) context.map(request, true);} catch (IllegalArgumentException e) {badRequest(requestURI, (HttpServletResponse) response.getResponse());return;}if (wrapper == null) {notFound(requestURI, (HttpServletResponse) response.getResponse());return;}// Ask this Wrapper to process this Requestresponse.setContext(context);wrapper.invoke(request, response);
上面的主要逻辑是在一个应用上下文中匹配出对该消息处理的servlet,这里是一个Wrapper。由于我们设置了servletmapping,因此会匹配到StandardWrapper[PrimitiveServlet]这个wrapper。最后会由StandardWrapperValve处理该消息,主要逻辑如下:

servlet = wrapper.allocate();
上面是非常重要的一个步骤,就是获取一个对应的Servlet实例,allocate的主要逻辑如下:

if (!singleThreadModel) {// Load and initialize our instance if necessaryif (instance == null) {synchronized (this) {if (instance == null) {try {instance = loadServlet();} catch (ServletException e) {throw e;} catch (Throwable e) {throw new ServletException(sm.getString("standardWrapper.allocate"), e);}}}}if (!singleThreadModel) {if (debug >= 2)log("  Returning non-STM instance");countAllocated++;return (instance);}}
该方法中会判断一个Servlet是否实现了单线程的模式,如果不是单线程的模式每次都会返回相同的实例,也就是只有一个实例存在。生成servlet的方法由loadServlet使用类加载器加载对应的Servelet,加载过程我们前面几节已经涉及到了,这里不再赘述(针对servlet的init和service等方法的调用是在loadServlet方法中完成的)。如果是单线程模式会将特定数量的实例放到对象池中,每次从池中获取可用的对象,如果池中没有可用的实例,此时会阻塞,可以看出单线程模式会有性能问题。

到此针对一个请求寻找到合适的servlet处理的过程大概就如上面所讲。


这篇关于How Tomcat Works 5的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/810231

相关文章

详解Tomcat 7的七大新特性和新增功能(1)

http://developer.51cto.com/art/201009/228537.htm http://tomcat.apache.org/tomcat-7.0-doc/index.html  Apache发布首个Tomcat 7版本已经发布了有一段时间了,Tomcat 7引入了许多新功能,并对现有功能进行了增强。很多文章列出了Tomcat 7的新功能,但大多数并没有详细解释它们

Tomcat性能参数设置

转自:http://blog.csdn.net/chinadeng/article/details/6591542 Tomcat性能参数设置 2010 - 12 - 27 Tomcat性能参数设置 博客分类: Java Linux Tomcat 网络应用 多线程 Socket 默认参数不适合生产环境使用,因此需要修改一些参数   1、修改启动时内存参数、并指定J

TL-Tomcat中长连接的底层源码原理实现

长连接:浏览器告诉tomcat不要将请求关掉。  如果不是长连接,tomcat响应后会告诉浏览器把这个连接关掉。    tomcat中有一个缓冲区  如果发送大批量数据后 又不处理  那么会堆积缓冲区 后面的请求会越来越慢。

Tomcat下载压缩包解压后应有如下文件结构

1、bin:存放启动和关闭Tomcat的命令的路径。 2、conf:存放Tomcat的配置,所有的Tomcat的配置都在该路径下设置。 3、lib:存放Tomcat服务器的核心类库(JAR文件),如果需要扩展Tomcat功能,也可将第三方类库复制到该路径下。 4、logs:这是一个空路径,该路径用于保存Tomcat每次运行后产生的日志。 5、temp:保存Web应用运行过程中生成的临时文件

docker学习系列(四)制作基础的base项目镜像--jdk+tomcat

前面已经完成了docker的安装以及使用,现在我们要将自己的javaweb项目与docker结合 1.1准备jdk+tomcat软件 ​​我下载了apache-tomcat-7.0.68.tar.gz和jdk-7u79-linux-x64.tar.gz,存储于Linux机器的本地目录/usr/ect/wt/下(利用xshell上传)。利用linux命令 tar -zxvf apache-tom

Tomcat服务详解

一、部署Tomcat服务器 JDK安装官方网址:https://www.oracle.com/cn/java Tomcat安装官方网址:Apache Tomcat® - Welcome! 安装JDK 1.获取安装包wget https://download.oracle.com/otn/java/jdk/8u411-b09/43d62d619be4e416215729597d70b8ac

龙芯小本8089b安装debian7+java+tomcat+mysql

之前团购了一个龙芯小本8089b,cpu很差劲,内存也只有1G,根本不能用来娱乐,于是想把它换个纯字符系统,然后搭建java服务器平台,用作局域网固定的mini服务器开发用。 以下是我搭建过程,当然实际比这做的多,这是多次尝试之后的成功过程,分享给大家,自己也做个笔记 debian7纯字符系统安装龙芯专有java安装tomcat安装mysql安装 一、debian7安装参考 圣域☆

eclipse中,更新JDK之后,启动Tomcat报错:

更新到这个版本之后,启动Tomcat报错: 四月 25, 2016 10:13:20 上午 org.apache.catalina.core.AprLifecycleListener lifecycleEvent INFO: The APR based Apache Tomcat Native library which allows optimal performance in prod

在Eclipse环境下修改Tomcat编码的问题

问题: 由于BMS需要设置UTF-8编码,要不就会出现中文乱码问题; 一、项目保持UTF-8格式; 二、由于可能会多次移除项目、加载项目,不想每次都要修改tmp0\conf 原因: 如果在eclipse中配置了tomcat后,其实,tomcat所用的所有tomcat配置文件,都不是catalina_home/config下面的xml文件,而是在eclipse所创建的Serve

Eclipse发布Maven项目到tomcat,无法加载到lib文件夹下的jar包

BMS 解决方法: 当我们发布web项目到tomcat时,访问地址时会报一个classnotfound的错误,但是eclipse中的项目中都已经添加了相应的类,有一种比较容易犯的错误是,你没有把额外所需的jar包加到tomcat中的lib文件夹中,在这里介绍一种在项目中直接添加jar包到lib目录下:  右键已创建的web项目——properties属性——点击Deployment Assem