- 浏览: 202647 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
qigeminghaofan:
第二个应用中说第一个不安全,熟悉servlet内部的程序员能向 ...
[How Tomcat Works]第2章 一个简单的Servlet容器 -
lliiqiang:
substring内存泄露问题只需要再加一个方法,让程序员明白 ...
优化变成了忧患:String.split引发的“内存泄露” -
tonghaoqi__:
必须点赞。。
如何控制War包访问Tomcat的内部实现类 -
jzzwy:
好文章 支持
Tomcat 5.5.26源代码分析——启动过程(一) -
wangzhewang:
牛!,希望更多分享!
Linux随机数发生器导致Apache进程全部Block的问题追查
译者 jarfield
博客 http://jarfield.iteye.com
获取参数
除非servlet
调用javax.servlet.http.HttpServletRequest
的getParameter
、getParameterMap
、getParameterNames
和getParameterValues
方
法来读取请求参数,否则,我们都不需要解析query string
或HTTP
请求体(request
body
)。 因此,HttpRequest
类实现的这四个方法,都
是先调用parseParameter
方法。
请求参数只需要被解析一次,而且也许只能被解析一次,因为如果请求参数是在请求体中,参数解析会导致SocketInputStream
到
达字节流的末尾。HttpRequest
类使用boolean
成员parsed
来
表示请求参数是否已经被解析。
如果是GET
请求,那
么所有的请求参数都在query sting
中。如果是POST
请求,在请求体中也可以找到一些参数。所有参数以名/值对的形式存储在一个HashMap
中。Servlet
程
序员能够以两种形式获取参数:Map
(调用HttpServletRequest
的getParameterMap
方
法)和名/值对。但是,这里有个“圈套”。Servlet
程序员不允许修改参
数的值。因此,使用了一个特殊的HashMap
:org.apache.catalina.util.ParameterMap
。
ParameterMap
类继承了java.util.HashMap
,并使用了一个boolean
成
员locked
。只有locked
的
值为false
时,名/值对才能被添加、修改和删除。否则,将会抛出一个IllegalStateException
异常。ParameterMap
的代码见Listing 3.6
。
它重载了添加、修改和删除元素的方法。这些方法只能在locked
值为false
才能被调用。
Listing
3.6: The org.apache.Catalina.util.ParameterMap class.
package org.apache.catalina.util; import java.util.HashMap; import java.util.Map; public final class ParameterMap extends HashMap { public ParameterMap() { super (); } public ParameterMap(int initialCapacity) { super(initialCapacity); } public ParameterMap(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } public ParameterMap(Map map) { super(map); } private boolean locked = false; public boolean isLocked() { return (this.locked); } public void setLocked(boolean locked) { this.locked = locked; } private static final StringManager sm = StringManager.getManager("org.apache.catalina.util"); public void clear() { if (locked) throw new IllegalStateException(sm.getString("parameterMap.locked")); super.clear(); } public Object put(Object key, Object value) { if (locked) throw new IllegalStateException (sm.getString("parameterMap.locked")); return (super.put(key, value)); } public void putAll(Map map) { if (locked) throw new IllegalStateException (sm.getString("parameterMap.locked")); super.putAll(map); } public Object remove(Object key) { if (locked) throw new IllegalStateException (sm.getString("parameterMap.locked")); return (super.remove(key)); } }
现在,让我们看看parseParameters
方法是如何工作的。
由于请求参数既可以存在于query string
中,也可以存在于
HTTP请求体中,parseParameters
方法必须都检查query string
和请求体。一旦解析完成,就可以在parameters
成员变量中找到这些参数。因此该方法首先检查成员变量parsed
的值,如果之前已经解析过,parsed
的
值就是true
。
if (parsed) return;
然后,parseParameters
方法声明创建一个名为results
的ParameterMap
变量,将它指向parameters
。如果parameters
为null
,就创建一个新的ParameterMap
对
象。
ParameterMap results = parameters; if (results == null) results = new ParameterMap();
接着,parseParameters 方法打开ParameterMap 的 锁,以便修改它。
results.setLocked(false);
下一步,parseParameters 方法检查编码,如果编码为空则赋予默认编码。
String encoding = getCharacterEncoding(); if (encoding == null) encoding = "ISO-8859-1";
接着,parseParameters
方
法尝试解析query string
。参数解析是由org.apache.Catalina.util.RequestUtil
类的parseParameter
方法完成的。
// Parse any parameters specified in the query string String queryString = getQueryString(); try { RequestUtil.parseParameters(results, queryString, encoding); } catch (UnsupportedEncodingException e) { ; }
下一步,parseParameters 方法尝试看看HTTP 请求体中是否包含参数。如果用户使用POST 方法发送请求,content length 大 于0 ,并且content type 是application/x-www-form-urlencoded , 那么请求体中就会包含参数。解析请求体的代码如下。
// Parse any parameters specified in the input stream String contentType = getContentType(); if (contentType == null) contentType = ""; int semicolon = contentType.indexOf(';'); if (semicolon >= 0) { contentType = contentType.substring (0, semicolon).trim(); } else { contentType = contentType.trim(); } if ("POST".equals(getMethod()) && (getContentLength() > 0) && "application/x-www-form-urlencoded".equals(contentType)) { try { int max = getContentLength(); int len = 0; byte buf[] = new byte[getContentLength()]; ServletInputStream is = getInputStream(); while (len < max) { int next = is.read(buf, len, max - len); if (next < 0 ) { break; } len += next; } is.close(); if (len < max) { throw new RuntimeException("Content length mismatch"); } RequestUtil.parseParameters(results, buf, encoding); } catch (UnsupportedEncodingException ue) { ; } catch (IOException e) { throw new RuntimeException("Content read fail"); } }
最后,parseParameters
方
法锁住ParameterMap
,设置parsed
成员的值为true
,并将results
赋值给parameters
。
// Store the final results results.setLocked(true); parsed = true; parameters = results;
创建HttpResponse 对 象
HttpResponse 类实现了javax.servlet.http.HttpServletResponse 接口,跟随该类的 还有一个门面类HttpResponseFacade 。Figure 3.3 展现了HttpResponse 和 相关类的类图。
在第2
章,我们使用的HttpResponse
类
仅包括部分功能。例如,它的getWriter
方法返回了一个java.io.PrintWriter
对象,该对象的print
方法并不会自动flush
。本章的应用将修复这个
问题。为了理解如何修复的,你需要知道Writer
是什么。
在servlet
内部,你使用PrintWriter
来
写入字符。你可以使用任何你希望的编码,但是字符总是作为字节流发送给浏览器。因此,第2
章
中ex02.pyrmont.HttpResponse
类getWriter
方法的实现也就不奇怪了:
public PrintWriter getWriter() { // if autoflush is true, println() will flush, // but print() will not. // the output argument is an OutputStream writer = new PrintWriter(output, true); return writer; }
看,我们是如何创建PrintWriter
对象的?传递一个java.io.OutputStream
实
例作为参数。任何内容传递给PrintWriter
的print
或println
方
法,都会被转成字节流,通过底层OutputStream
对象发送出去。
本章我们使用ex03.pyrmont.connector.ResponseStream
类
的实例作为PrintWriter
的OutputStream
。注意,ResponseStream
类
直接继承了java.io.OutputStream
类。
本章我们还使用继承了PrintWriter
的ex03.pyrmont.connector.ResponseWriter
类。ResponseWriter
类重写了所有的print
和println
方法,对这些方法的调用都会自动将输出flush
到底层的OutputStream
。因此,我们使
用以ResponseStream
对象作为底层的ResponseWriter
实例。
我们本可以将一个ResponseStream
对象作为参数,实例化ResponseWriter
类。然而,我们使用java.io.OutputStreamWriter
对
象桥接了ResponseWriter
对象和ResponseStream
对象。
有了OutputStreamWriter
,
被写入的字符自动按照指定的字符集被编码成字节。这里使用的字符集,或者通过名称来指定,或者显式指定Charset
对
象,或者使用平台默认的字符集。对write
方法的每次调用,都会对给定的字符进行编
码转换。在写入底层输入流之前,转换后的字节先被累积在缓冲区中。缓冲区的大小可以指定,但对于大多数场景来说,默认大小已经足够了。
因此,getWriter
方法就按下面的代码来实现:
public PrintWriter getWriter() throws IOException { ResponseStream newStream = new ResponseStream(this); newStream.setCommit(false); OutputStreamWriter osr = new OutputStreamWriter(newStream, getCharacterEncoding()); writer = new ResponseWriter(osr); return writer; }
静态资源处理器和Servlet 处 理器
ServletProcessor 类和第2 章的ex02.pyrmont.ServletProcessor 类 是类似的。它们都只有一个方法:process 。然而,ex03.pyrmont.connector.ServletProcessor 的process 方法接受一个HttpRequest 对 象和一个HttpResponse 对象,而不是Request 对象和Response 对 象。下面是本章应用的process 方法原型:
public void process(HttpRequest request, HttpResponse response) {
另外,process
方法使用HttpRequestFacade
和HttpResponseFacade
,作为请求和响应的门面类。而且在调用了servlet
的service
方
法后,还调用了HttpResponse
类的finishResponse
方法。
servlet = (Servlet) myClass.newInstance(); HttpRequestFacade requestPacade = new HttpRequestFacade(request); HttpResponseFacade responseFacade = new HttpResponseFacade(response); servlet.service(requestFacade, responseFacade); ((HttpResponse) response).finishResponse();
StaticResourceProcessor
类和ex02.pyrmont.StaticResourceProcessor
基本相同。
运行应用程序
要在Windows 运行该应用,在工作目录运行以下命令:
java -classpath ./lib/servlet.jar;./ ex03.pyrmont.startup.Bootstrap
在Linux
上,需要使用冒号来分
隔两个库。
java -classpath ./lib/servlet.jar:./ ex03.pyrmont.startup.Bootstrap
要显示index.html ,使用下面的URL :
http://localhost:808O/index.html
要调用PrimitiveServlet,直接在浏览器中访问下面的URL:
http://localhost:8080/servlet/PrimitiveServlet
你会在浏览器中看到下面的内容:
Hello. Roses are red. Violets are blue.
提示:第2章中运行
PrimitiveServlet
时,并没有输出第二行。
你也可以调用第2
章中没有的ModernServlet
。URL
是:
http://localhost:8080/servlet/ModernServlet
提
示:
ModernServlet
的代码在工作目录的
webroot
目录下。
你可以在URL后面拼上一个query stirng
,来测试servlet
。Figure 3.4
显示了,
以下面URL
运行ModernServlet
的
输出结果:
http://localhost:8080/servlet/ModernServlet?userName=tarzan&password=pwd
Figure 3.4
: 运行ModernServlet
总结
本章你已经学习到了连接器 是如何工作的。本章构建的连接器 ,是Tomcat 4 默 认连接器 的一个简化版本。正如你知道的,这个默认连接器 因为低效而被不推荐使用(deprecated )。 例如,所有的HTTP 请求headers都被解析,即使servlet 从来没有使用它们。结果,默认连接器 运行速度缓慢,并被更快的Coyote 代替。Coyote 的代码可以从Apache基金会网站下载到。无论如何,默认连接器都是一个很好的学 习工具,我们将在第4 章详细讨论它。
评论
基本用研究源代码的时间都可以找到很多替代品。
说实话,很同意你的看法,不过我一般还是会去查源代码。
基本用研究源代码的时间都可以找到很多替代品。
因人 而异
不错不错,同上
基本用研究源代码的时间都可以找到很多替代品。
因人 而异
基本用研究源代码的时间都可以找到很多替代品。
发表评论
-
如何控制War包访问Tomcat的内部实现类
2010-12-14 21:56 6318Tomcat默认部署了Manager应 ... -
[How Tomcat Works]第4章 Tomcat默认连接器
2010-06-29 20:17 8550译者 jarfield 博 客 ht ... -
[How Tomcat Works]第3章 连接器(一)
2010-04-10 21:55 8734译者 jarfield 博客 http://j ... -
Tomcat 5.5.26源代码分析——启动过程(二)
2010-03-25 14:38 7781init方法 Catalina_Home和Cat ... -
Tomcat 5.5.26源代码分析——启动过程(一)
2010-03-25 14:30 5033main方法 第一阶段 第二阶段 ... -
[How Tomcat Works]第2章 一个简单的Servlet容器
2010-03-14 00:43 4145译者 jarfield 博客 http: ... -
[How Tomcat Works]第1章 一个简单的Web服务器
2010-03-02 23:09 5525译者 jarfield 博客 http:// ... -
Tomcat 5.5.26的网络构建指南
2010-02-27 00:44 33481. 安装JDK ... -
[How Tomcat Works]第0章 介绍
2010-02-24 19:09 3224译者 jarfield 博客 ... -
Eclipse远程调试Tomcat
2010-01-24 20:24 4825最近,一直在研究Tomcat的工作内幕,主要的方法就是参考《H ...
相关推荐
《How Tomcat Works》中文版一书详细剖析了Tomcat服务器的内部工作机制。该书基于Tomcat 4.1.12和5.0.18两个版本,深入讲解了其servlet容器的架构和运作原理,尤其是代号为Catalina的核心组件。 Tomcat是一个开源的...
《译How Tomcat Works(第二章)》这篇文章主要讲解了Apache Tomcat服务器的工作原理,它是一个开源的Java Servlet容器,广泛用于部署Web应用程序。在这一章中,我们将深入探讨Tomcat如何处理HTTP请求,以及其内部架构...
《How Tomcat Works》是一本深入探讨Apache Tomcat工作原理的书籍,中文版的提供使得国内开发者能够更方便地理解这一流行的开源Java Servlet容器。这本书不仅涵盖了Tomcat的基础知识,还详细解析了其内部机制,对于...
1. **架构概述**:Tomcat的架构基于服务器-客户端模型,主要由Catalina(Servlet容器)、 Coyote(HTTP/HTTPS连接器)和Jasper(JSP引擎)三个主要组件构成。Catalina处理Servlet,Coyote处理网络通信,Jasper编译和...
《How Tomcat Works》是一本深入解析Apache Tomcat工作原理的书籍,同时也包含了源码,为读者提供了理论与实践相结合的深入学习体验。Tomcat是一款广泛使用的开源Java Servlet容器,它是Apache软件基金会 Jakarta...
《How Tomcat Works中文版》这本书是一本深入探讨Apache Tomcat服务器工作原理的专著。Apache Tomcat服务器,或简称为Tomcat,是世界上广泛使用的Java Servlet容器和JavaServer Pages(JSP)引擎,负责处理基于Java...
### How Tomcat Works中文版深度解析 #### 一、引言与概述 《How Tomcat Works》是一本针对Apache Tomcat服务器内部工作机制进行深入剖析的专业书籍。本书详细介绍了Tomcat 4.1.12和5.0.18两个版本的内部结构与...
《How Tomcat Works》这本书是理解Apache Tomcat服务器工作原理的宝贵资源,它全面深入地讲解了这个流行的Java Servlet和JavaServer Pages(JSP)容器的内部机制。书中的20个章节涵盖了从基础概念到高级特性的广泛...
《How Tomcat Works》这本书深入浅出地介绍了Apache Tomcat这款广泛应用的Java Servlet容器的工作原理。Tomcat作为开源软件,是许多Web应用的基础,尤其在轻量级开发和测试环境中非常常见。以下是对Tomcat核心知识点...
《How Tomcat Works》这本书是理解Apache Tomcat服务器工作原理的重要资源,第三章主要探讨了Tomcat的架构和核心组件。以下是对这部分内容的详细解读: Tomcat作为一款开源的Java Servlet容器,其核心功能是解析...
《HowTomcatWorks》是一本深入解析Apache Tomcat工作原理的书籍,中文版的发布使得更多的中国开发者能够理解和掌握这款广泛应用的开源Java Servlet容器的工作机制。Tomcat是Apache软件基金会Jakarta项目的一部分,它...
《how tomcat works》是一本深入探讨Apache Tomcat内部工作原理的专业书籍。Apache Tomcat是一个开源的Java Servlet容器,它实现了Java Servlet和JavaServer Pages技术规范,提供了Java Web服务器的功能。对于Java ...
《How Tomcat Works》是一本深入探讨Apache Tomcat工作原理的书籍,包含了中英文两个版本。这本书对于理解Java Servlet和JavaServer Pages(JSP)容器的运作方式具有极高的价值,特别是对于那些想要深入理解Web应用...
《How Tomcat Works》是一本深入解析Apache Tomcat服务器内部工作原理的重要参考资料,它提供了对Tomcat架构的全面理解,包括其设计、配置和优化。这本书的中文版和英文版都为读者提供了便利,无论你是母语为中文...