How Tomcat Works 2

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

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

上一节(How Tomcat Works 1 编写一个简单静态web服务器)编写了一个简单的web服务器,只能处理静态的资源,本节将继续向前迈出一个小步,创建两个不同的servlet容器,能够利用servlet简单的处理动态内容。注意每节的代码都是基于上一节的继续丰富,因此有必要从第一节开始看起。

在编写代码之前,需要先大体了解一下Servlet是什么,方便后面的理解,下面就是一个最简单的Servlet什么也没做:

package prymont;import java.io.IOException;import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/*** 每个Servlet都实现Servlet接口* 该接口有5个方法需要实现,该Servlet只是为了让大家对* Servlet有个整体的印象,因此所有方法都未实现。*/
public class PrimitiveServlet implements Servlet{//当servlet容器正在被关闭或者servlet容器内存不够的时候,该方法由servlet容器调用,且只调用一次//该方法通常用来清除资源。@Overridepublic void destroy() {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}//当servlet已经初始化的时候,该方法由servlet容器调用,且只调用一次//该方法适合做一些一次性的加载动作,比如数据库驱动等。@Overridepublic void init(ServletConfig arg0) throws ServletException {}//servlet容器负责为每一次请求调用一次service方法,并且传递一个ServletRequest(封装客户端请求)//和ServletResponse(封装响应)对象。@Overridepublic void service(ServletRequest arg0, ServletResponse arg1)throws ServletException, IOException {}}

先来说说我们的第一个版本的Servlet容器要实现的功能:等待Http请求,如果是请求静态资源则交给静态资源处理器,如果是请求动态资源则加载相应的Servlet并调用它的service方法,同时传递ServletRequest和ServletResponse对象。(第一个版本每次请求servlet类都被加载)

本版本针对上次主要新增StaticResourceProcessor和ServletProcessor1两个类分别处理静态资源和动态资源,同时Request和Response对象也各自集成了

http://machineName:port/staticResource请求的是一个静态资源,http://localhost:8080/servlet/PrimitiveServlet请求的则是一个动态的资源,因此对于HttpServer1只需要稍稍改动一下即可满足需求。

StaticResourceProcessor只是简单的调用了response的sendStaticResource()方法,也没有可讲的,下面重点讲解一下ServletProcessor1的实现:

package server1;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/*** 完成servlet类的动态加载* 并调用servlet的service的方法**/
public class ServletProcessor1 {/*** 加载Servlet* * @param request* @param response*/public void process(Request request, Response response) {// /servlet/servetclassString uri = request.getUri();// 截取servlet名字String servletName = uri.substring(uri.lastIndexOf("/") + 1);// jdk提供的URL类加载器,根据URL加载classURLClassLoader loader = null;URL[] urls = new URL[1];// 指定加载webapp下所有的class文件File classPath = new File(Constant.WEB_APP);URLStreamHandler streamHandler = null;try {// 使用file协议从本机的classPath加载class// getCanonicalPath返回绝对路径(不带.)String repository = new URL("file", null,classPath.getCanonicalPath() + File.separator).toString();urls[0] = new URL(null, repository, streamHandler);} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}loader = new URLClassLoader(urls);Class clazz = null;try {// 根据servlet名字加载class,这里对名字的处理并不完善,实际需要根据包名做拼接//为了简单servlet类全不不带包名clazz = loader.loadClass(servletName);} catch (ClassNotFoundException e) {e.printStackTrace();}Servlet servlet = null;try {// 反射创建实例servlet = (Servlet) clazz.newInstance();// 向下转型调用service方法servlet.service((ServletRequest) request,(ServletResponse) response);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ServletException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
上面就是处理Servlet的整个过程,可以通过http://localhost:8080/servlet/PrimitiveServlet来访问我们的servlet。

我们的第一个程序有一个严重的问题,就是当传递给servlet的service方法的时候将Request和Response对象都向上转型了,这样如果知道内部实现的人,则可以在写自己的Servlet的时候向下转型成Request和Response对象,并调用他们的方法,实际上这两个对象是容器私有的不应该暴露给开发者(具体是有些方法不能让开发者使用),有一个方法是让这两个类使用默认的包访问权限,其实有一个更优雅的实现方式就是门面模式。

在本节的第二版中增加两个类,RequestFacade和ResponseFacade用来控制某些方法的可见性。具体的方式是给RequestFacade提供一个带参构造函数,参数类型为Request对象,门面类封装servletrequest方法,其实只是传递给Request对象实现,这样在调用service方法时传递的facade对象,这样即使通过向下转型得到的也是被封装过的Facade对象。RequestFacade对象片段如下:

public class RequestFacade implements ServletRequest {private ServletRequest request = null;public RequestFacade(Request request) {this.request = request;}/* implementation of the ServletRequest*/public Object getAttribute(String attribute) {return request.getAttribute(attribute);}
ResponseFacade对象类似,不贴出来代码了。

还有一点不同的是ServletProcessor1的部分处理,具体变化的如下:

Servlet servlet = null;RequestFacade requestFacade = new RequestFacade(request);ResponseFacade responseFacade = new ResponseFacade(response);try {// 反射创建实例servlet = (Servlet) clazz.newInstance();// 向下转型调用service方法servlet.service((ServletRequest) requestFacade,(ServletResponse) responseFacade);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ServletException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
通过Request对象构造RequestFacade对象并向上转型传递给service方法。

以上就是本节实现的一个简单的servlet容器。下一节将会接触到tomcat中一个非常重要的概念——连接器


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



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

相关文章

详解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