博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入剖析Tomcat(2)
阅读量:6711 次
发布时间:2019-06-25

本文共 3299 字,大约阅读时间需要 10 分钟。

之前根据第一章的内容和代码写了一个博客,发现在看这个书的时候写博客和跑代码是比纯看书收获大的多得多的,因此还是很开心自己没有懒惰。

在看第二章的时候,我选择了直接看代码,这样就相当于同时做了复习和预习,然后看第二章的时候就可以跳过很多已知内容了。

第二章一共有两个例程,主要是引入了java包里面的Servlet,和门面Facade设计模式。

我们先看第二章的HttpServer1,这个程序中引入了Servlet。和第一章的服务端程序相比,这里多了一个功能,除了可以访问http://localhost:8080/index.html之外,还可以访问http://localhost:8080/servlet/primitiveServlet 来请求一个具体的servlet,然后返回那个servlet里面的service函数里面的内容。

我们还是从main函数入口看起。

这里是和第一章中HttpServer的主要区别。先看else的部分,比较简单。

 

这个StaticResourceProcessor类,十分简单,就是包装了request和response,然后调用response的sendStaticResource而已。

然后看一些response方法,主要的区别就是实现了ServletResponse接口,所有的接口方法返回null,只实现了getWriter。

 

这里返回了一个PrintWriter,并制定了autoFlush为true(这个参数会令任何println的调用都会刷新输出,但是print则不会)。这个printWriter是一个字符打印流的作用。

我们再来看main中的if里面的内容,判断如果解析出来的uri是以“/servlet”开头的话就会进入这个代码块。

这里的ServetProcessor1比之前的StaticResourceProcessor稍微麻烦一些。主要方法是process方法:

public void process(Request request, Response response) {
String uri = request.getUri(); String servletName = uri.substring(uri.lastIndexOf("/") + 1); URLClassLoader loader = null; try {
// create a URLClassLoader URL[] urls = new URL[1]; URLStreamHandler streamHandler = null; File classPath = new File(Constants.WEB_ROOT); // the forming of repository is taken from the createClassLoader method in // org.apache.catalina.startup.ClassLoaderFactory String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ; // the code for forming the URL is taken from the addRepository method in // org.apache.catalina.loader.StandardClassLoader class. urls[0] = new URL(null, repository, streamHandler); loader = new URLClassLoader(urls); } catch (IOException e) {
System.out.println(e.toString() ); } Class myClass = null; try {
myClass = loader.loadClass(servletName); } catch (ClassNotFoundException e) {
System.out.println(e.toString()); } Servlet servlet = null; try {
servlet = (Servlet) myClass.newInstance(); servlet.service((ServletRequest) request, (ServletResponse) response); } catch (Exception e) {
System.out.println(e.toString()); } catch (Throwable e) {
System.out.println(e.toString()); } }

这个方法应该是这个程序的核心了,用到了url类加载器来加载一个servlet。我们debug启动这个程序,然后直接在这个方法里面打一个断点,一步一步走就可以看到这个方法是怎么通过一个“/servlet/primitiveServlet” uri得到一个PrimitiveServlet类实例的。

重点看try里面的地方:

新建一个URL[]数组来给url类加载器使用,新建一个URLStreamHandler给URL的构造函数使用,然后找到存放资源的目录。

 

Constants常数类里面的WEB_ROOT可以直接找到真实的一个webroot文件夹。然后通过一个URL类的构造函数生成一个路径

String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;

这个函数会给传入的classPath前面加上file:,然后最后面加上“\”。

然后通过URL的另一个构造函数生成一个URL实例。

这个构造函数的定义是

public URL(URL context, String spec, URLStreamHandler handler)

上面那个构造函数的定义是

public URL(String protocol, String host, String file)

因此我们不能在调用的时候传入,URL(null, spec, null) 这样会找不到正确的构造函数,因此这里一开始新建的URLStreamHandler为null就有用了。

最后生成PrimitiveServlet类的类加载器。

然后我们看第二个程序HttpServer2

这里的主要的不同就是在ServletProcessor的process方法里面,process方法用了requestFacade和responseFacade。

 

(其实我没有完全懂得为什么要用外观类,按照书里面的说法)这里主要是为了安全性考虑,因为Request和Response里面的方法都是public方法,如果有懂容器机制的人通过向下转型来获取到了Request和Response类,那他们就会调用到里面的方法,因此我们需要将他们隐藏起来。这里就通过外观类来将Request和Response分别作为成员变量赋给外观类,然后再在外观类里面调用Request和Response里面的方法以达到安全的目的。

 

转载于:https://www.cnblogs.com/kobebyrant/p/how_tomcat_works_2.html

你可能感兴趣的文章
FLEX3中应用CSS完全详解手册
查看>>
Windows7添加usb3.0驱动
查看>>
模式——工程化实现及扩展(设计模式Java 版)
查看>>
如何干净的清除Slave同步信息
查看>>
Oracle动态采样学习
查看>>
借助开源工具高效完成Java应用的运行分析
查看>>
Transparent Huge Pages相关概念
查看>>
浅谈RAID和LVM
查看>>
初中高级LINUX运维所需具备技能
查看>>
从开发到测试
查看>>
ajax轮询
查看>>
ubuntu: System program problem detected 问题
查看>>
产品优化利器
查看>>
js,query 选择radio+选中select+checkbox选中
查看>>
FreeBSD小技巧
查看>>
kolla简介
查看>>
php入门教程: php中字符的使用和操作
查看>>
php变量2
查看>>
Spring aop 异常统一处理
查看>>
【JS进阶2】attachEvent()/addEventListener() 对象添加触发事件
查看>>