📄 542.html
字号:
<STYLE type=text/css>
<!--
body,td { font-size:9pt;}
hr { color: #000000; height: 1px}
-->
</STYLE>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD><TITLE>精选文章 >> Servlet >> Servlet深层讨论</title>
</head>
<body >
<p><IMG SRC="../image/jsp001_middle_logo.gif" WIDTH="180" HEIGHT="60" BORDER=0 ALT=""></p>
<table width=100% bgcolor="#cccccc" align=center cellpadding="2" cellspacing="0" border=1 bordercolorlight="#000000" bordercolordark="#FFFFFF">
<tr bgcolor="#EFF8FF"><td>
<a href=http://www.jsp001.com/list_thread.php?int_attribute=2>精选文章</a>
>> <a href=http://www.jsp001.com/list_thread.php?forumid=9&int_attribute=2>Servlet</a>
>> Servlet深层讨论 [<a href=http://www.jsp001.com/forum/showthread.php?goto=newpost&threadid=542>查看别人的评论</a>]<br>
<hr><p>由 amtd 发布于: 2001-02-27 10:56</p><p><img src="images/icons/icon1.gif" alt="Post" border=0> </p><p> Servlet深层讨论 (作者:doctor)<br> <br> Servlets(Java 小服务器程序)是Java中新增加的一个全新功能。一般来说,Servlets是由服务器端调用和执行的任何Java类,浏览器端运行的Java程序叫Applet,Web服务器端运行的Java程序叫做Servlet。自从有了Servlet后,Java的电子商务才真正的开始,之后的JSP又是在Servlet上有了更进一步的发展。了解Servlet的机制也就掌握到了到JSP的实现原理。 <br> 我们在编写Servlet的时候不需要关心一个Servlet是如何被装载、服务器环境,只需要调用Java Servlet API编程接口就行了。在使用Servlet API的时候,程序员完全可以不必了解内部运行方式,服务器头、Cookies、会话都可以通过Servlet来处理。但当我们需要一些特殊功能的时候,就需要了解它的一些实现机制了。 <br> 先从Servlet的生命周期说起。一般情况下,可以归纳为几点:<br> 1. 装载Servlets。这项操作一般是动态执行的。有些Server提供了相应的管理功能,可以在启动的时候就装载Servlet; <br> 2. Server创建一个Servlet实例;<br> 3. Server调用Servlet的init()方法; <br> 4. 一个客户端的请求到达Server; <br> 5. server创建一个请求对象;<br> 6. Server创建一个响应对象;<br> 7. Server激活Servlet的Service()方法,并传递请求和响应对象;<br> 8. service()方法获得关于请求对象的的信息、处理请求、访问其他资源、获得需要的信息;<br> 9. service()方法使用响应对象的方法,将响应传回Server,最终到达客户端。Service()方法可能机或其他方法已处理请求,如doGet()或doPost()或程序员自己开发的方法; <br> 10. 对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用init()方法。也就是说,Servlet()只初始化一次。 <br> 11. 当Server不再需要Servlet时(一般是当Server关闭的时候),Server调用Servlets的destroy()方法。 <br> 从前面我们还可以更进一步得出以下几点:<br> Servlet运行时是多线程的,在开发的时候由Servlet API实现,开发人员不需要做特别的处理。<br>Servlet的init()、destroy()的使用就像是一个C++编写的结构、析构函数,要注意前后的一致。比如在init()打开了一个数据库,就要在destroy()中关闭。<br> 对一些底层的处理,如要控制消息响应的方式,我们就要重载server()方法,并重新编写。<br>为便于解释Servlet的实现机制,围绕HttpServlet,用下图描述Javax.Http包中常用到的类之间的关系(除掉了JSP部分),限于篇幅,没有给出每个接口、类的属性和方法。通过图示,我们很容易开发一些较低层次的代码。 <br><img src="../upload_image/611_1" border=0><br> 从上图,非常明显的可以看出HttpServlet是从GenericServlet类继承下来的。而事实上,GenericServlet类主要是为了起到三个接口的联合(这个词用得可能不科学):Servlet,ServletConfig,Serializable,以获得系统的支持;除了init()外几乎没有实现方法操作。真正调用系统所支持的各项功能是在HttpServlet类中。 <br> 就HttpServlet的service()方法,一般来说,当它接收到一个OPTIONS请求时,会调用doOptions()方法,当接收到一个TRACE请求时调用doTrace()。doOptions()缺省执行方式是自动决定什么样的HTTP被选择并且返回哪个信息。相关源代码如下: <br> public void service(ServletRequest req,ServletResponse res) <br> throws ServletException,IOException { <br> HttpServletRequest request;<br> HttpServletResponse response;<br> try <br> { <br> request = (HttpServletRequest)req;<br> response = (HttpServletResponse)res;<br> } <br> catch(ClassCastException _ex)<br> { <br> throw new ServletException("non-HTTP request or response"); <br> } service(request, response); <br> }<br> protected void service(HttpServletRequest req, HttpServletResponse resp)<br> throws ServletException, IOException <br> { <br> String method = req.getMethod(); <br> if(method.equals("GET")) <br> { <br> long lastModified = getLastModified(req);<br> if(lastModified == -1L) <br> {<br> doGet(req, resp);<br> }<br> else<br> {<br> long ifModifiedSince = req.getDateHeader("If-Modified-Since"); <br> if(ifModifiedSince < (lastModified / 1000L) * 1000L) <br> { <br> maybeSetLastModified(resp, lastModified); doGet(req, resp);<br> } <br> else <br> { <br> resp.setStatus(304); <br> }<br> } <br> } <br> else if(method.equals("HEAD"))<br> {<br> long lastModified = getLastModified(req); <br> maybeSetLastModified(resp, lastModified); <br> doHead(req, resp); <br> } <br> else <br> if(method.equals("POST")) <br> doPost(req, resp);<br> else <br> if(method.equals("PUT"))<br> doPut(req, resp);<br> else <br> if(method.equals("DELETE")) <br> doDelete(req, resp); <br> else<br> if(method.equals("OPTIONS"))<br> doOptions(req, resp);<br> else<br> if(method.equals("TRACE")) {<br> doTrace(req, resp);<br> } <br> else<br> { <br> String errMsg = lStrings.getString("http.method_not_implemented"); <br> Object errArgs[] = new Object[1];<br> errArgs[0] = method; <br> errMsg = MessageFormat.format(errMsg, errArgs); <br> resp.sendError(501, errMsg);<br> } <br> }<br> protected void doOptions(HttpServletRequest req, HttpServletResponse resp)<br> throws ServletException, IOException <br> { <br> Method methods[] = getAllDeclaredMethods(getClass());<br> boolean ALLOW_GET = false; boolean ALLOW_HEAD = false; <br> boolean ALLOW_POST = false; boolean ALLOW_PUT = false; <br> boolean ALLOW_DELETE = false; boolean ALLOW_TRACE = true; <br> boolean ALLOW_OPTIONS = true;<br> for(int i = 0; i < methods.length; i++)<br> { <br> Method m = methods[i];<br> if(m.getName().equals("doGet"))<br> {<br> ALLOW_GET = true; <br> ALLOW_HEAD = true;<br> }<br> if(m.getName().equals("doPost"))<br> ALLOW_POST = true;<br> if(m.getName().equals("doPut"))<br> ALLOW_PUT = true; <br> if(m.getName().equals("doDelete"))<br> ALLOW_DELETE = true;<br> }<br> String allow = null; <br> if(ALLOW_GET && allow == null) <br> allow = "GET"; <br> if(ALLOW_HEAD) <br> if(allow == null) <br> allow = "HEAD";<br> else allow = allow + ", HEAD";<br> if(ALLOW_POST) <br> if(allow == null) <br> allow = "POST"; <br> else allow = allow + ", POST"; <br> if(ALLOW_PUT) <br> if(allow == null) <br> allow = "PUT";<br> else allow = allow + ", PUT"; <br> if(ALLOW_DELETE) <br> if(allow == null)<br> allow = "DELETE"; <br> else allow = allow + ", DELETE";<br> if(ALLOW_TRACE) <br> if(allow == null) <br> allow = "TRACE"; <br> else allow = allow + ", TRACE"; <br> if(ALLOW_OPTIONS) <br> if(allow == null) <br> allow = "OPTIONS"; <br> else allow = allow + ", OPTIONS"; <br> resp.setHeader("Allow", allow); <br> } <br> protected void doTrace(HttpServletRequest req, HttpServletResponse resp) <br> throws ServletException, IOException<br> { <br> String CRLF = "\r\n"; <br> String responseString = "TRACE " + req.getRequestURI() + " " + req.getProtocol();<br> for(Enumeration reqHeaderEnum = req.getHeaderNames();<br> reqHeaderEnum.hasMoreElements();) <br> { <br> String headerName = (String)reqHeaderEnum.nextElement(); <br> responseString = responseString + CRLF + headerName + ": " + req.getHeader(headerName);<br> } <br> responseString = responseString + CRLF; int responseLength = responseString.length();<br> resp.setContentType("message/http");<br> resp.setContentLength(responseLength); <br> ServletOutputStream out = resp.getOutputStream(); <br> out.print(responseString);<br> out.close(); <br>}<br> 如果我们改写了上面的代码,将可以写出一些针对性更强的特殊领域中的应用。限于篇幅,这里将不在举例。为了便于读者的分析,将随邮件发送javax.servlet.http包中的源代码。 在HttpServlet类(或子类)中,可以对一些系统底层支持的功能进行一些操作,比如Session、Cookie等。其中HttpSession接口在Sun公司提供的包中没有找到它的类,应该是由Server引擎来实现、管理它的相关功能。笔者曾试着扩展HttpSession以实现一些额外的功能,但由于Session与另外几个接口Request、Response等结合非常紧密,又是系统直接支持,所以没有成功。<br> 笔者注:由于 Java虚拟机的特点,使我们能够了解到一些比较底层的包。但又因为Java引擎的强大功能,组件式的调用为更深入的分析带来了很大的困难。如果有错误还恳请读者指正,也欢迎对此感兴趣的朋友能够经常交流,共同提高我们的Java应用水平。我的邮件地址是jiangcheng@staff.yesky.com<br><br>[已被 amtd 编辑过, 在 2001-03-05 10:42]<br>__________________<br><font color=red>真实源于生活! </font><br>请访问我们的网站: <br>(VB爱好者乐园) <br><a href="http://www.vbgood.com" target=_blank>http://www.vbgood.com</a><br><a href="http://www.d1vb.com" target=_blank>http://www.d1vb.com</a><br><a href="http://61.128.97.225/vbgood/index.asp" target=_blank>http://61.128.97.225/vbgood/index.asp</a><br>拥有1800多个资料! </p></td>
</tr>
</table>
<p>
<CENTER><a href="http://www.jsp001.com/forum/newreply.php?action=newreply&threadid=542">点这里对该文章发表评论</a></CENTER>
<p>该文章总得分是 <font color=red>6</font> 分,你认为它对你有帮助吗?
[<a href=javascript:void(0) onclick=window.open("http://www.jsp001.com/forum/codeVote.php?threadid=542&intVote=4","","menubar=no,toolbar=no,location=no,directories=no,status=no,resizable=no,scrollbars=no,width=70,height=40,top=0,left=0")>非常多</a>](<font color=red>1</font>)
[<a href=javascript:void(0) onclick=window.open("http://www.jsp001.com/forum/codeVote.php?threadid=542&intVote=2","","menubar=no,toolbar=no,location=no,directories=no,status=no,resizable=no,scrollbars=no,width=70,height=40,top=0,left=0")>有一些</a>](<font color=red>1</font>)
[<a href=javascript:void(0) onclick=window.open("http://www.jsp001.com/forum/codeVote.php?threadid=542&intVote=1","","menubar=no,toolbar=no,location=no,directories=no,status=no,resizable=no,scrollbars=no,width=70,height=40,top=0,left=0")>无帮助</a>](<font color=red>1</font>)
[<a href=javascript:void(0) onclick=window.open("http://www.jsp001.com/forum/codeVote.php?threadid=542&intVote=-1","","menubar=no,toolbar=no,location=no,directories=no,status=no,resizable=no,scrollbars=no,width=70,height=40,top=0,left=0")>是灌水</a>](<font color=red>1</font>) </p>
<script language="javascript" src="http://www.jsp001.com/include/read_thread_script.php?threadid=542"></script>
<p><CENTER>
Copyright © 2001 - 2009 JSP001.com . All Rights Reserved <P>
<IMG SRC="../image/jsp001_small_logo.gif" WIDTH="85" HEIGHT="30" BORDER=0 ALT="">
</CENTER></p>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -