精华内容
下载资源
问答
  • *在这个包中,WEB_ROOT就是工作路径”webroot”。 *工作路径是文件系统中java命令所调用的位置。 */ public static final String WEB_ROOT = System.getProperty(“user.dir”)+File.separator + “webroot”; //...

    一个web服务器也叫做HTTP服务器,因为它使用HTTP协议同客户端(即浏览器)通信。一个基于Java的web服务器用到的两个重要类:java.net.Socket和java.net.ServerSocket,通信协议采用HTTP。因此,很自然的接下来我们就以HTTP和java的这两个类来谈谈web服务器。随后我们再介绍一个简单的web服务器应用。

    一、HTTP(The Hypertext Transfer Protocol):

    Http是允许web服务端和浏览器之间通过Internet发送/接收的协议,它是一个请求/响应的协议。浏览器请求一个文件,服务器会响应这个请求。Http用Tcp连接方式----默认端口是80.Http的第一个发布版本是Http/0.9,目前一般用的是Http1.1.

    通过Http协议,通常是浏览器通过建立连接并且发送请求来发起一个会话事务,服务器端会响应或者给浏览器一个响应的连接,浏览器端或者服务器端可以在会话中提前终止一个连接。例如,当用一个浏览器作为客户端,可以点击停止按钮就可以终止正在下载的文件,从而有效的关闭与web服务器端的Http连接。

    1.HTTP请求:

    一个Http请求包含以下3个部分:

    ·Method-URI-Protocal/Version

    ·Request headers

    ·Entity body

    一个HTTP请求的例子如下:

    POST /examples/default.jsp HTTP/1.1

    Accept:text/plain;text/html

    Accept-Language:en-gb

    Connection:Keep-Alive

    Host:localhost

    User-Agent:Mozilla/4.0(compatible;MSIE 4.01;windows 98)

    Content-Length:33

    Content-Type:application/x-www-form-urlencoded

    Accept-Encoding:gzip,deflate

    lastName=Franks&firstName=Michael

    Method-URI-Protocal/Version出现在请求的第一行,即:

    POST /examples/default.jsp HTTP/1.1

    其中POST表示是请求的方法,/examples/default.jsp代表URI,HTTP/1.1表示Protocol/Version.

    HTTP1.1支持七种请求方法:GET、POST、HEAD、OPTIONS、PUT、DELETE和TRACE。其中GET和POST是最常用的。

    URI完全地说明了源文件类型,一个URI通常是相对于服务器端的根目录。这样一来,URI的路径通常是这样的/*。URL统一资源定位符通常就是URI。协议版本代表所用的HTTP版本。

    请求的文件头request header可以体现出请求的浏览器信息和实体等重要信息。例如,它包含浏览器所用的编码方式,实体的长度等等。每一个header被CRLF(carriage return/linefeed)分开,CRLF即回车换行。

    在headers和entity实体之间,会有一个CRLF来分隔,这个对于HTTP请求格式非常重要。

    CRLF告诉HTTP服务器请求的内容从哪里开始。

    在上面的HTTP请求中,请求实体如下:

    lastName=Franks&firstName=Michael

    2.HTTP响应:

    与Http请求相似,一个Http响应也由以下三部分组成:

    ·Protocol-Status code-Description

    ·Response headers

    ·Entity body

    下面是一个HTTP响应的例子:

    HTTP/1.1 200 OK

    Server:Microsoft-IIS/4.0

    Date:Mon,5 Jan 2004 13:13:33 GMT

    Content-Type:text/html

    Last-Modified:Mon,5 Jan 2004 13:13:12 GMT

    Content-Length:112

    HTTP Response Example

    Welcome to Brainy Software

    响应的第一行与请求的第一行格式有些相似。它告诉协议是HTTP1.1,请求成功标志200.并且一切正常OK。响应的报文头与请求的报文头相似,也包含了一些环境参数。同样响应报文也以CRLF来分隔开。

    二、Socket类:

    Socket是网络连接的一个端口。Socket可以使应用程序在网络中读/写到数据。分别位于不同计算机的两款应用软件可以依靠Socket相互进行接收/读取数据,为使一台计算机上的应用软件发送信息给另一台电脑,需要知道其IP地址和端口号。在Java中,socket类即是java.net.Socket类。

    创建socket对象,可以用该类众多构造方法中的一种来构造对象,其中一个是这样的,需要host名字和端口号:public Socket (java.lang.String host,int port) .例如要连接端口号为80的yahoo.com,可以这样来写:new Socket(“yahoo.com”,80)。

    下面的代码片断创建了一个socket类,不过是同本机127.0.0.1通信。

    Socket socket = new Socket(“127.0.0.1”,”8080”);

    OutputStream os = socket.getOutputStream();

    boolean autoflush = true;

    PrintWriter out = new PrintWriter(socket.getOutputStream(),autoflush);

    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    //发送一个HTTP请求到web 服务器端

    out.println(“GET /index.jsp HTTP/1.1”);

    out.println(“Host:localhost:8080”);

    outprintln(“Connection:Close”);

    out.println();

    //读取响应

    boolean loop = true;

    StringBuffer sb = new StringBuffer(8096);

    while(loop){

    if(in.ready){

    int i=0;

    while(i!=-1){

    i = in.read();

    sb.append((char)i);

    }

    }

    loop = false;

    }

    Thread.currentThread().sleep(50);

    //响应结果到显示平台

    System.out.println(sb.toString());

    Socket.close();

    三、ServerSocket类

    Socket类代表“客户端”的socket,也就是说无论什么时候要连接远端服务器时,创建一个socket对象即可。现在,如果要想创建一个服务器应用,比如HTTP server或者FTP server,则需要用不同的方式。这是因为server端要实时接收客户端的请求。

    ServerSocket与Socket不同。ServerSocket的角色是一直在等待客户端的请求。一旦ServerSocket接收到客户端的请求,则会创建一个Socket对象来进行通信。

    要创建一个服务器套接字,你需要使用ServerSocket类提供的四个构造方法中的一个。你需要指定IP地址和服务器套接字将要进行监听的端口号。通常,IP地址将会是127.0.0.1,也就是说,服务器套接字将会监听本地机器。服务器套接字正在监听的IP地址被称为是绑定地址。服务器套接字的另一个重要的属性是backlog,这是服务器套接字开始拒绝传入的请求之前,传入的连接请求的****队列长度。

    其中一个ServerSocket类的构造方法如下所示:

    public ServerSocket(int port, int backLog, InetAddress bindingAddress);

    对于这个构造方法,绑定地址必须是java.net.InetAddress的一个实例。一种构造InetAddress对象的简单的方法是调用它的静态方法getByName,传入一个包含主机名称的字符串,就像下面的代码一样。

    InetAddress.getByName("127.0.0.1");

    下面一行代码构造了一个监听的本地机器8080端口的ServerSocket,它的backlog为1。

    new ServerSocket(8080, 1, InetAddress.getByName("127.0.0.1"));

    一旦你有一个ServerSocket实例,你可以让它在绑定地址和服务器套接字正在监听的端口上等待传入的连接请求。你可以通过调用ServerSocket类的accept方法做到这点。这个方法只会在有连接请求时才会返回,并且返回值是一个Socket类的实例。Socket对象接下去可以发送字节流并从客户端应用中接受字节流,就像前一节"Socket类"解释的那样。实际上,这章附带的程序中,accept方法是****用到的方法

    四、实例运用

    我们这个应用包含如下三个类:

    ·HttpServer

    ·Request

    ·Response

    该应用程序的入口(即main方法)在HttpServer类中,main方法创建一个HttpServer对象,然后调用其await方法,该方法正如其名,一直在监听给定的端口,等待HTTP请求,一旦有请求,则进行接收,然后返回response对象。这个方法一直在监听客户端的请求,直到有shutdown命令关闭之。

    这个应用不仅仅能发送静态资源,例如HTML文件、image图片以及某一文件夹下的文件,而且能处理动态传送而来的字节。但是它不传送任何的header,比如dates、cookies等。

    下面我们来详细的看看这三个类。

    HttpServer类

    HttpServer类是服务器端代码,如清单1.1。清单1.2详细展现await方法,在清单1.1中不再显示。

    list1.1:HttpServer类

    public class HttpServer{

    /**

    *WEB_ROOT这个路径下放置HTML文件和其他一些文件。

    *在这个包中,WEB_ROOT就是工作路径”webroot”。

    *工作路径是文件系统中java命令所调用的位置。

    */

    public static final String WEB_ROOT =

    System.getProperty(“user.dir”)+File.separator + “webroot”;

    //关闭命令

    private static final String SHUTDOWN_COMMAND = “/SHUTDOWN”;

    //接收shutdown命令

    private boolean shutdown = false;

    public static void main(String[] args){

    HttpServer server = new HttpServer();

    server.await();

    }

    public void await(){

    }

    }

    await方法详细如下:

    public void await(){

    ServerSocket serverSocket = null;

    int port = 8080;

    try{

    serverSocket =

    new ServerSocket(port,1,InetAddress.getByName(“127.0.0.1”));

    }catch(IOException e){

    e.printStackTrace();

    System.exit(1);

    }

    //循环等待请求

    while(!shutdown){

    Socket socket = null;

    InputStream input = null;

    OutputStream output = null;

    try{

    socket = serverSocket.accept();

    input = socket.getInputStream();

    output = socket.getOutputStream();

    //创建Request对象,并且parse

    Request request = new Request(input);

    request.parse();

    //创建Response对象

    Response response = new Response(output);

    response.setRequest(request);

    response.sendStaticResource();

    //关闭socket

    socket.close();

    //查看URI是否为关闭uri

    shutdown = request.getUri().equals(SHUTDOWN_COMMAND);

    }catch(Exception e){

    e.printStackTrace();

    continue;

    }

    }

    }

    这个web服务器可以访问到所有WEB_ROOT目录以及子目录下的静态资源,WEB_ROOT的初始化如下:public static final String WEB_ROOT =

    System.getProperty(“user.dir”)+File.separator +”webroot”;

    代码包含了一个叫做webroot的目录,该目录下有一些静态资源。要访问服务器下的静态资源,URL可以这样写:http://machineName:port/staticResource.如果是跨机器访问,那么machineName就是计算机的名字或者IP地址,如果是同一台机器,则为localhost或着计算机名,端口就是8080,staticResource就是你将要访问的文件名,但是该文件必须在WEB_ROOT目录下。

    例如,如果你在同一机器通过服务器访问,要访问该服务的index.html文件,URL为:http://localhost:8080/index.html.

    如果要关闭服务,则可以在浏览器上输入预先在程序中设置好的url路径。比如现在要停止当前正在运行的服务,我们这个例子中的关闭命令是通过HttpServer类中静态常量SHUTDOWN来控制,private static final String SHUTDOWN_COMMAND = “/SHUTDOWN”,因此我们要关闭该例子的服务,url可以这样来写:http://localhost:8080/SHUTDOWN.

    现在,让我们来看看await方法。这个方法名是await而不是wait,主要是因为java.lang.Object这个超类中有个关于多线程的方法名叫做wait。await方法一开始就创建了一个ServerSocket对象,然后进行一个while循环。

    serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));

    //循环等待request请求

    while (!shutdown) { ... }

    循环代码中当在端口8080上有HTTP的请求时,serverSocket便会通过accept方法返回一个socket对象,即:socket = serverSocket.accpet().

    Request类:

    该类代表一个HTTP request对象。该request对象实例化需要传递一个socket对象的inputstream对象。可以调用InputStream对象的read方法来获取HTTP request对象所传输的数据。

    该类的具体内容如下listing 1.3.该类含有两个方法,parse方法(listing 1.4)和getUri(listing 1.5)方法。

    listing 1.3:

    public class Request {

    private InputStream input;

    private String uri;

    public Request(InputStream input) {

    this.input = input;

    }

    public String getUri() {

    return uri;

    }

    public void parse() {

    ……

    }

    private String parseUri(String requestString) {

    ……

    }

    }

    Listing 1.4:

    public void parse() {

    // Read a set of characters from the socket

    StringBuffer request = new StringBuffer(2048);

    int i;

    byte[] buffer = new byte[2048];

    try {

    i = input.read(buffer);

    }

    catch (IOException e) {

    e.printStackTrace();

    i = -1;

    }

    for (int j=0; j

    request.append((char) buffer[j]);

    }

    System.out.print(request.toString());

    uri = parseUri(request.toString());

    }

    Parse方法解析了request对象传输而来的数据。这个方法别无它途,仅仅要获取该http请求中的url路径。下面的getUri方法则返回了该url路径。

    Listing 1.5:

    private String parseUri(String requestString) {

    int index1, index2;

    index1 = requestString.indexOf(' ');

    if (index1 != -1) {

    index2 = requestString.indexOf(' ', index1 + 1);

    if (index2 > index1)

    return requestString.substring(index1 + 1, index2);

    }

    return null;

    }

    Response类:

    该类如下:

    public class Response {

    private static final int BUFFER_SIZE = 1024;

    Request request;

    OutputStream output;

    public Response(OutputStream output) {

    this.output = output;

    }

    public void setRequest(Request request) {

    this.request = request;

    }

    public void sendStaticResource() throws IOException {

    byte[] bytes = new byte[BUFFER_SIZE];

    FileInputStream fis = null;

    try {

    File file = new File(HttpServer.WEB_ROOT, request.getUri());

    if (file.exists()) {

    fis = new FileInputStream(file);

    int ch = fis.read(bytes, 0, BUFFER_SIZE);

    while (ch!=-1) {

    output.write(bytes, 0, ch);

    ch = fis.read(bytes, 0, BUFFER_SIZE);

    }

    }else {

    // 找不到文件

    String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +

    "Content-Type: text/html\r\n" +

    "Content-Length: 23\r\n" +

    "\r\n" +

    "

    File Not Found

    ";

    output.write(errorMessage.getBytes());

    }

    }catch (Exception e) {

    // 如果不能实例化File对象,则会抛出一个异常

    System.out.println(e.toString() );

    }finally {

    if (fis!=null)

    fis.close();

    }

    }

    }

    首先注意到的是,通过构造函数获取到java.io.OutputStream对象,如下:

    public Response(OutputStream output) {

    this.output = output;

    }

    运行这个应用:

    在浏览器地址栏上输入地址:http://localhost:8080/index.html,可以看到测试页面。

    如果输入一个不存在的文件地址,http://localhost:8080/indexs.html 如下,则返回404错误。

    展开全文
  • As indicated in the diagram above, Tomcat creates the following class loaders as it is initialized:Bootstrap— This class loader contains the basic runtime classes provided by the Java Virtual Machine...

    As indicated in the diagram above, Tomcat creates the following class loaders as it is initialized:

    Bootstrap — This class loader contains the basic runtime classes provided by the Java Virtual Machine, plus any classes from JAR files present in the System Extensions directory ($JAVA_HOME/jre/lib/ext). Note: some JVMs may implement this as more than one class loader, or it may not be visible (as a class loader) at all.

    System — This class loader is normally initialized from the contents of the CLASSPATH environment variable. All such classes are visible to both Tomcat internal classes, and to web applications. However, the standard Tomcat startup scripts ($CATALINA_HOME/bin/catalina.sh or %CATALINA_HOME%\bin\catalina.bat) totally ignore the contents of the CLASSPATH environment variable itself, and instead build the System class loader from the following repositories:

    $CATALINA_HOME/bin/bootstrap.jar — Contains the main() method that is used to initialize the Tomcat server, and the class loader implementation classes it depends on.

    $CATALINA_BASE/bin/tomcat-juli.jar or $CATALINA_HOME/bin/tomcat-juli.jar — Logging implementation classes. These include enhancement classes to java.util.logging API, known as Tomcat JULI, and a package-renamed copy of Apache Commons Logging library used internally by Tomcat. See logging documentation for more details.

    If tomcat-juli.jar is present in $CATALINA_BASE/bin, it is used instead of the one in $CATALINA_HOME/bin. It is useful in certain logging configurations

    $CATALINA_HOME/bin/commons-daemon.jar — The classes from Apache Commons Daemon project. This JAR file is not present in the CLASSPATH built by catalina.bat|.sh scripts, but is referenced from the manifest file of bootstrap.jar.

    Common — This class loader contains additional classes that are made visible to both Tomcat internal classes and to all web applications.

    Normally, application classes should NOT be placed here. The locations searched by this class loader are defined by the common.loader property in $CATALINA_BASE/conf/catalina.properties. The default setting will search the following locations in the order they are listed:

    unpacked classes and resources in $CATALINA_BASE/lib

    JAR files in $CATALINA_BASE/lib

    unpacked classes and resources in $CATALINA_HOME/lib

    JAR files in $CATALINA_HOME/lib

    By default, this includes the following:

    annotations-api.jar — JavaEE annotations classes.

    catalina.jar — Implementation of the Catalina servlet container portion of Tomcat.

    catalina-ant.jar — Tomcat Catalina Ant tasks.

    catalina-ha.jar — High availability package.

    catalina-storeconfig.jar — Generation of XML configuration files from current state

    catalina-tribes.jar — Group communication package.

    ecj-*.jar — Eclipse JDT Java compiler.

    el-api.jar — EL 3.0 API.

    jasper.jar — Tomcat Jasper JSP Compiler and Runtime.

    jasper-el.jar — Tomcat Jasper EL implementation.

    jsp-api.jar — JSP 2.3 API.

    servlet-api.jar — Servlet 3.1 API.

    tomcat-api.jar — Several interfaces defined by Tomcat.

    tomcat-coyote.jar — Tomcat connectors and utility classes.

    tomcat-dbcp.jar — Database connection pool implementation based on package-renamed copy of Apache Commons Pool and Apache Commons DBCP.

    tomcat-i18n-**.jar — Optional JARs containing resource bundles for other languages. As default bundles are also included in each individual JAR, they can be safely removed if no internationalization of messages is needed.

    tomcat-jdbc.jar — An alternative database connection pool implementation, known as Tomcat JDBC pool. See documentation for more details.

    tomcat-spdy.jar — SPDY implementation

    tomcat-util.jar — Common classes used by various components of Apache Tomcat.

    tomcat-websocket.jar — WebSocket 1.1 implementation

    websocket-api.jar — WebSocket 1.1 API

    WebappX — A class loader is created for each web application that is deployed in a single Tomcat instance. All unpacked classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application, are made visible to this web application, but not to other ones.

    As mentioned above, the web application class loader diverges from the default Java delegation model (in accordance with the recommendations in the Servlet Specification, version 2.4, section 9.7.2 Web Application Classloader). When a request to load a class from the web application's WebappX class loader is processed, this class loader will look in the local repositories first, instead of delegating before looking. There are exceptions. Classes which are part of the JRE base classes cannot be overridden. For some classes (such as the XML parser components in J2SE 1.4+), the J2SE 1.4 endorsed feature can be used. Last, any JAR file that contains Servlet API classes will be explicitly ignored by the classloader — Do not include such JARs in your web application. All other class loaders in Tomcat follow the usual delegation pattern.

    Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:

    Bootstrap classes of your JVM

    /WEB-INF/classes of your web application

    /WEB-INF/lib/*.jar of your web application

    System class loader classes (described above)

    Common class loader classes (described above)

    If the web application class loader is configuered with delegate="true" then the order becomes:

    Bootstrap classes of your JVM

    System class loader classes (described above)

    Common class loader classes (described above)

    /WEB-INF/classes of your web application

    /WEB-INF/lib/*.jar of your web application

    展开全文
  • tomcat工作原理

    2017-02-13 18:41:00
    Tomcat工作原理 基于Java的Web 应用程序是 servlet、JSP 页面、静态页面、类和其他资源的集合,它们可以用标准方式打包,并运行在来自多个供应商的多个容器。Web 应用程序存在于结构化层次结构的目录中,该层次...

    基于Java的Web 应用程序是 servlet、JSP 页面、静态页面、类和其他资源的集合,它们可以用标准方式打包,并运行在来自多个供应商的多个容器。Web 应用程序存在于结构化层次结构的目录中,该层次结构是由 Java Servlet 规范定义的。Web 应用程序的根目录包含直接存储或存储在子文件夹中的所有公共资源,比如图像、HTML 页面等。构成:Web应用由Web组件(一组Java类库)、html文件,静态资源文件(如图像)、帮助类和库组成。

    1 – Tomcat Server的组成部分

    1.1 – Server

    A Server element represents the entire Catalina servlet container. (Singleton)

    1.2 – Service

    A Service element represents the combination of one or more Connector components that share a single Engine
    Service是这样一个集合:它由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求

    1.3 – Connector

    一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户
    TOMCAT有两个典型的Connector,一个直接侦听来自browser的http请求,一个侦听来自其它WebServer的请求
    Coyote Http/1.1 Connector 在端口8080处侦听来自客户browser的http请求
    Coyote JK2 Connector 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求

     

    1.4 – Engine

    The Engine element represents the entire request processing machinery associated with a particular Service
    It receives and processes all requests from one or more Connectors
    and returns the completed response to the Connector for ultimate transmission back to the client
    Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名
    当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理
    Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理

    1.5 – Host

     

    代表一个Virtual Host,虚拟主机,每个虚拟主机和某个网络域名Domain Name相匹配
    每个虚拟主机下都可以部署(deploy)一个或者多个Web App,每个Web App对应于一个Context,有一个Context path
    当Host获得一个请求时,将把该请求匹配到某个Context上,然后把该请求交给该Context来处理
    匹配的方法是“最长匹配”,所以一个path==”"的Context将成为该Host的默认Context
    所有无法和其它Context的路径名匹配的请求都将最终和该默认Context匹配

    1.6 – Context

    一个Context对应于一个Web Application,一个Web Application由一个或者多个Servlet组成
    Context在创建的时候将根据配置文件$CATALINA_HOME/conf/web.xml和$WEBAPP_HOME/WEB-INF/web.xml载入Servlet类
    当Context获得请求时,将在自己的映射表(mapping table)中寻找相匹配的Servlet类
    如果找到,则执行该类,获得请求的回应,并返回

    2 – Tomcat Server的结构图

     

     

    3 – 配置文件$CATALINA_HOME/conf/server.xml的说明

    该文件描述了如何启动Tomcat Server

     

     <!----------------------------------------------------------------------------------------------->

    <!-- 启动Server 在端口8005处等待关闭命令 如果接受到"SHUTDOWN"字符串则关闭服务器 -->

    <Server port="8005" shutdown="SHUTDOWN" debug="0">

    <!-- Listener ??? 目前没有看到这里 -->

    <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" debug="0"/>

    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" debug="0"/>

    <!-- Global JNDI resources ??? 目前没有看到这里,先略去 -->

    <GlobalNamingResources>

     ... ... ... ...

    </GlobalNamingResources>

    <!-- Tomcat的Standalone Service Service是一组Connector的集合 它们共用一个Engine来处理所有Connector收到的请求 -->

    <Service name="Tomcat-Standalone">

    <!-- Coyote HTTP/1.1 Connector className : 该Connector的实现类是org.apache.coyote.tomcat4.CoyoteConnector port :

    在端口号8080处侦听来自客户browser的HTTP1.1请求 minProcessors : 该Connector先创建5个线程等待客户请求,

    每个请求由一个线程负责 maxProcessors : 当现有的线程不够服务客户请求时,若线程总数不足75个,则创建新线程来处理请求

    acceptCount : 当现有线程已经达到最大数75时,为客户请求排队 当队列中请求数超过100时,后来的请求返回Connection refused

    错误 redirectport : 当客户请求是https时,把该请求转发到端口8443去 其它属性略 -->

    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"

     port="8080"

     minProcessors="5" maxProcessors="75" acceptCount="100"

     enableLookups="true"

     redirectPort="8443"

     debug="0"

     connectionTimeout="20000"

     useURIValidationHack="false"

     disableUploadTimeout="true" />

    <!-- Engine用来处理Connector收到的Http请求 它将匹配请求和自己的虚拟主机,

    并把请求转交给对应的Host来处理默认虚拟主机是localhost -->

    <Engine name="Standalone" defaultHost="localhost" debug="0">

    <!-- 日志类,目前没有看到,略去先 -->

    <Logger className="org.apache.catalina.logger.FileLogger" .../>

    <!-- Realm,目前没有看到,略去先 -->

    <Realm className="org.apache.catalina.realm.UserDatabaseRealm" .../>

    <!-- 虚拟主机localhost appBase : 该虚拟主机的根目录是webapps/ 它将匹配请求和

    自己的Context的路径,并把请求转交给对应的Context来处理 -->

    <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true">

    <!-- 日志类,目前没有看到,略去先 -->

    <Logger className="org.apache.catalina.logger.FileLogger" .../>

    <!-- Context,对应于一个Web App path : 该Context的路径名是"",故该Context是该Host的

    默认Context docBase : 该Context的根目录是webapps/mycontext/ -->

    <Context path="" docBase="mycontext" debug="0"/>

    <!-- 另外一个Context,路径名是/wsota -->

    <Context path="/wsota" docBase="wsotaProject" debug="0"/>

    </Host>

    </Engine>

    </Service>

    </Server>

    <!----------------------------------------------------------------------------------------------->

     

    4 – Context的部署配置文件web.xml的说明

    一个Context对应于一个Web App,每个Web App是由一个或者多个servlet组成的
    当一个Web App被初始化的时候,它将用自己的ClassLoader对象载入“部署配置文件web.xml”中定义的每个servlet类
    它首先载入在$CATALINA_HOME/conf/web.xml中部署的servlet类
    然后载入在自己的Web App根目录下的WEB-INF/web.xml中部署的servlet类
    web.xml文件有两部分:servlet类定义和servlet映射定义
    每个被载入的servlet类都有一个名字,且被填入该Context的映射表(mapping table)中,和某种URL PATTERN对应
    当该Context获得请求时,将查询mapping table,找到被请求的servlet,并执行以获得请求回应

    分析一下所有的Context共享的web.xml文件,在其中定义的servlet被所有的Web App载入

     

     <!----------------------------------------------------------------------------------------------->

    <web-app>

    <!-- 概述: 该文件是所有的WEB APP共用的部署配置文件, 每当一个WEB APP

    被DEPLOY,该文件都将先被处理,然后才是WEB APP自己的/WEB-INF/web.xml -->

    <!-- +-------------------------+ -->

    <!-- | servlet类定义部分 | -->

    <!-- +-------------------------+ -->

    <!-- DefaultServlet

    当用户的HTTP请求无法匹配任何一个servlet的时候,该servlet被执行

    URL PATTERN MAPPING : / -->

    <servlet>

    <servlet-name>default</servlet-name>

    <servlet-class>

    org.apache.catalina.servlets.DefaultServlet

    </servlet-class>

    <init-param>

       <param-name>debug</param-name>

       <param-value>0</param-value>

    </init-param>

    <init-param>

       <param-name>listings</param-name>

       <param-value>true</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>

    </servlet>

    <!-- InvokerServlet

    处理一个WEB APP中的匿名servlet 当一个servlet被编写并编译放入

    /WEB-INF/classes/中,却没有在/WEB-INF/web.xml中定义的时候

    该servlet被调用,把匿名servlet映射成/servlet/ClassName的形式

    URL PATTERN MAPPING : /servlet/* -->

    <servlet>

       <servlet-name>invoker</servlet-name>

       <servlet-class>org.apache.catalina.servlets.InvokerServlet </servlet-class>

       <init-param>

         <param-name>debug</param-name>

         <param-value>0</param-value>

       </init-param>

       <load-on-startup>2</load-on-startup>

    </servlet>

    <!-- JspServlet

    当请求的是一个JSP页面的时候(*.jsp)该servlet被调用

    它是一个JSP编译器,将请求的JSP页面编译成为servlet再执行

    URL PATTERN MAPPING : *.jsp -->

    <servlet>

      <servlet-name>jsp</servlet-name>

      <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>

      <init-param>

         <param-name>logVerbosityLevel</param-name>

         <param-value>WARNING</param-value>

      </init-param>

     <load-on-startup>3</load-on-startup>

    </servlet>

    <!-- +---------------------------+ -->

    <!-- | servlet映射定义部分 | -->

    <!-- +---------------------------+ -->

    <servlet-mapping>

      <servlet-name>default</servlet-name>

      <url-pattern>/</url-pattern>

    </servlet-mapping>

    <servlet-mapping>

       <servlet-name>invoker</servlet-name>

       <url-pattern>/servlet/*</url-pattern>

    </servlet-mapping>

    <servlet-mapping>

      <servlet-name>jsp</servlet-name>

      <url-pattern>*.jsp</url-pattern>

    </servlet-mapping>

    <!-- +------------------------+ -->

    <!-- | 其它部分,略去先 | -->

    <!-- +------------------------+ -->

    ... ... ... ...

    </web-app>

    <!----------------------------------------------------------------------------------------------->

     

    5 – Tomcat Server处理一个http请求的过程

    假设来自客户的请求为:

    http://localhost:8080/wsota/wsota_index.jsp

    1) 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
    2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
    3) Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host
    4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
    5) localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context
    6) Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为”"的Context去处理)
    7) path=”/wsota”的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet
    8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
    9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
    10)Context把执行完了之后的HttpServletResponse对象返回给Host
    11)Host把HttpServletResponse对象返回给Engine
    12)Engine把HttpServletResponse对象返回给Connector
    13)Connector把HttpServletResponse对象返回给客户browser

     

    转载于:https://www.cnblogs.com/yueminghai/p/6395013.html

    展开全文
  • Tomcat工作原理

    2018-12-13 14:57:41
    下面是 Tomcat 的总体结构: 从 上中可以看出 Tomcat 的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍。Connector 组件是可以被替换,这样可以提供给服务器设计者更多的选择,因....

    总体结构

    Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,找到了 Tomcat 最核心的模块,您就抓住了 Tomcat 的“七寸”。下面是 Tomcat 的总体结构图:

    从 上图中可以看出 Tomcat 的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍。Connector 组件是可以被替换,这样可以提供给服务器设计者更多的选择,因为这个组件是如此重要,不仅跟服务器的设计的本身,而且和不同的应用场景也十分相关,所以一 个 Container 可以选择对应多个 Connector。多个 Connector 和一个 Container 就形成了一个 Service,Service 的概念大家都很熟悉了,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非 Server 莫属了。所以整个 Tomcat 的生命周期由 Server 控制。

    Service 作为婚姻

    我们将 Tomcat 中 Connector、Container 作为一个整体比作一对情侣的话,Connector 主要负责对外交流,可以比作为 Boy,Container 主要处理 Connector 接受的请求,主要是处理内部事务,可以比作为 Girl。那么这个 Service 就是连接这对男女的结婚证了。是 Service 将它们连接在一起,共同组成一个家庭。当然要组成一个家庭还要很多其它的元素。

    说白 了,Service 只是在 Connector 和 Container 外面多包一层,把它们组装在一起,向外面提供服务,一个 Service 可以设置多个 Connector,但是只能有一个 Container 容器。这个 Service 接口的方法列表如下:

    从 Service 接口中定义的方法中可以看出,它主要是为了关联 Connector 和 Container,同时会初始化它下面的其它组件,注意接口中它并没有规定一定要控制它下面的组件的生命周期。所有组件的生命周期在一个 Lifecycle 的接口中控制,这里用到了一个重要的设计模式,关于这个接口将在后面介绍。

    Tomcat 中 Service 接口的标准实现类是 StandardService 它不仅实现了 Service 借口同时还实现了 Lifecycle 接口,这样它就可以控制它下面的组件的生命周期了。StandardService 类结构图如下:

    从 上图中可以看出除了 Service 接口的方法的实现以及控制组件生命周期的 Lifecycle 接口的实现,还有几个方法是用于在事件监听的方法的实现,不仅是这个 Service 组件,Tomcat 中其它组件也同样有这几个方法,这也是一个典型的设计模式,将在后面介绍。

    下面看一下 StandardService 中主要的几个方法实现的代码,下面是 setContainer 和 addConnector 方法的源码:

    public void setContainer(Container container) {

        Container oldContainer = this.container;

        if ((oldContainer != null) && (oldContainer instanceof Engine))

            ((Engine) oldContainer).setService(null);

        this.container = container;

        if ((this.container != null) && (this.container instanceof Engine))

            ((Engine) this.container).setService(this);

        if (started && (this.container != null) && (this.container instanceof Lifecycle)) {

            try {

                ((Lifecycle) this.container).start();

            } catch (LifecycleException e) {

                ;

            }

        }

        synchronized (connectors) {

            for (int i = 0; i < connectors.length; i++)

                connectors[i].setContainer(this.container);

        }

        if (started && (oldContainer != null) && (oldContainer instanceof Lifecycle)) {

            try {

                ((Lifecycle) oldContainer).stop();

            } catch (LifecycleException e) {

                ;

            }

        }

        support.firePropertyChange("container", oldContainer, this.container);

    }

    这段代码很简单,其实就是先判断当前的这个 Service 有没有已经关联了 Container,如果已经关联了,那么去掉这个关联关系—— oldContainer.setService(null)。如果这个 oldContainer 已经被启动了,结束它的生命周期。然后再替换新的关联、再初始化并开始这个新的 Container 的生命周期。最后将这个过程通知感兴趣的事件监听程序。这里值得注意的地方就是,修改 Container 时要将新的 Container 关联到每个 Connector,还好 Container 和 Connector 没有双向关联,不然这个关联关系将会很难维护。

    public void addConnector(Connector connector) {

        synchronized (connectors) {

            connector.setContainer(this.container);

            connector.setService(this);

            Connector results[] = new Connector[connectors.length + 1];

            System.arraycopy(connectors, 0, results, 0, connectors.length);

            results[connectors.length] = connector;

            connectors = results;

            if (initialized) {

                try {

                    connector.initialize();

                } catch (LifecycleException e) {

                    e.printStackTrace(System.err);

                }

            }

            if (started && (connector instanceof Lifecycle)) {

                try {

                    ((Lifecycle) connector).start();

                } catch (LifecycleException e) {

                    ;

                }

            }

            support.firePropertyChange("connector", null, connector);

        }

    }

    上面是 addConnector 方法,这个方法也很简单,首先是设置关联关系,然后是初始化工作,开始新的生命周期。这里值得一提的是,注意 Connector 用的是数组而不是 List 集合,这个从性能角度考虑可以理解,有趣的是这里用了数组但是并没有向我们平常那样,一开始就分配一个固定大小的数组,它这里的实现机制是:重新创建一个 当前大小的数组对象,然后将原来的数组对象 copy 到新的数组中,这种方式实现了类似的动态数组的功能,这种实现方式,值得我们以后拿来借鉴。

    最新的 Tomcat6 中 StandardService 也基本没有变化,但是从 Tomcat5 开始 Service、Server 和容器类都继承了 MBeanRegistration 接口,Mbeans 的管理更加合理。

     

     


    本教程由尚硅谷教育大数据研究院出品,如需转载请注明来源。

    展开全文
  • tomcat工作原理铺垫知识tomcat工作原理tomcat工作流程 今天嘞,我们来粗略的谈一下tomcat的工作原理,希望有错误的地方请大家积极指出! 铺垫知识 emmm,在说之前我先说一下基本的铺垫知识吧。 tomcat是使用java...
  • Tomcat 总体结构 ...下面是 Tomcat 的总体结构 1.Tomcat 的总体结构 从上中可以看出 Tomcat 的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍。Connector 组件是可以...
  • tomcat工作原理1

    2013-05-10 09:42:45
    本文以 Tomcat 5 为基础,也兼顾最新的 Tomcat 6 和 Tomcat 4。Tomcat 的基本设计思路和架构是具有一定连续性的。 Tomcat 总体结构 Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,... 1.Tomcat 的总体结构
  • Tomcat服务器工作原理

    2019-03-29 11:35:01
    本文以 Tomcat 5 为基础,也兼顾最新的 Tomcat 6 和 Tomcat 4。Tomcat 的基本设计思路和架构是具有一定连续性的。...0:tomcat访问流程 Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,...
  • Tomcat Connector原理

    2018-12-11 17:32:00
    Tomcat工作原理 要了解其中的工作原理我们首先看如下两个 Tomcat基本架构: Tomcat请求示意: 客户端的请求通过Connector接受处理后在到容器Engine->Host->Conetxt->进一步...
  • Tomcat工作原理   Server 要完成的任务很简单,就是要能够提供一个接口让其它程序能够访问到这个 Service 集合、同时要维护它所包含的所有 Service 的生命周期,包括如何初始化、如何结束服务、如何找到...
  • Tomcat servlet工作原理

    2017-04-17 22:16:22
    Tomcat 的容器等级中,Context 容器是直接管理 Servlet 在容器中的包装类 Wrapper,所以 Context 容器如何运行将直接影响 Servlet 的工作方式。 从上可以看出 Tomcat 的容器分为四个等级,真正管理 Servlet ...
  • tomcat工作原理介绍

    2018-12-26 09:54:04
    一、概念 Tomcat 服务器是一个开源的轻量级Web...Tomcat结构Tomcat主要组件:服务器Server,服务Service,连接器Connector、容器Container。连接器Connector和容器Container是Tomcat的核心。 一个Container容...
  • ​ SpringBoot的创造简化了我们创建项目和运行项目的工作。我们不必再像SpringMVC时代那样,将项目先打包成jar包,然后放入Tomcat中再启动。我们可以忽略打包的操作和tomat的配置问题,编写完代码后直接启动项目即可...
  • 1 部分,将主要从 Tomcat 如何分发请求、如何处理多用户同时请求,还有它的多级容器是如何协调工作的角度来分析 Tomcat工作原理,这也是一个 Web 服务器首要解决的关键问题。 本文以 Tomcat 5 为基础,也兼顾...
  • Tomcat原理

    2020-01-17 14:02:44
    2.1 Http 工作原理 Tomcat作为一个HTTP服务器干了什么? 接受链接,解析数据,处理请求和发送响应 2.2 Tomcat整体架构 2.2.1 Http服务器请求 处理 一即第一种请求处理方式 直接让服务器调用各业务类(用多个if...
  • Tomcat组成与工作原理

    2020-09-02 21:25:20
    Tomcat是什么 开源的 Java Web 应用服务器,实现了 Java EE(Java Platform Enterprise Edition)的部 分技术规范,比如 Java Servlet、Java Server Page、JSTL、Java WebSocket。Java EE 是 Sun 公 司为企业级应用...
  • 本文以 Tomcat 5 为基础,也兼顾最新的 Tomcat 6 和 Tomcat 4。Tomcat 的基本设计思路和架构是具有一定连续性的。 Tomcat 总体结构 ...下面是 Tomcat 的总体结构 1.Tomcat 的总体结构
  • 本文是第1部分,将主要从Tomcat如何分发请求、如何处理多用户同时请求,还有它的多级容器是如何协调工作的角度来分析Tomcat工作原理,这也是一个Web服务器首要解决的关键问题。本文以Tomcat5为基础,也兼顾最新的...
  • 一、HTTP工作原理 1、 Http协议是浏览器与服务器之间数据传送协议。作为应用层协议,Http是基于CP/IP协议来传递数据的(HTML文件、图片、查询结果等),HTTP协议不涉及数据包(Packet)传输,主要规定了客户端和...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 428
精华内容 171
关键字:

tomcat工作原理图