Tomcat源码解析一(概论)

首先来明确一下下面几个问题,这有助于我们理解TOMCAT的作用

1. 什么是HTTP协议?
 
  其实就是一种数据格式,想想看分布在网络上的各种应用程序数不胜数
客户端数量更是庞大,人们使用的浏览器也不同,HTTP协议就是规定客户端发送请求的数据格式,
和服务器端返回的数据格式,当我们使用不同的浏览器请求一个网站或服务时,浏览器发送的数据格式
都是遵照HTTP协议的,比如第一行写什么,第二行写什么,中间有没有空格等,这样所有基于HTTP协议的应用程序
服务器(TOMCAT)接收到客户端传递过来的请求信息后都能通过这些信息确定用户所要请求的具体功能,然后调用它
最后组合一个符合HTTP协议规定的返回信息发送给客户端,客户端浏览器负责接收这些信息,然后通过自己的解析
引擎呈现给用户页面

2. 浏览器如何发送数据,服务器如何返回数据?
    Socket,浏览器通过Socket发送符合HTTP协议的请求信息,服务器处理后通过Socket返回符合
HTTP协议的返回信息

3. 一个HTTP请求信息
POST /ScmWeb/Login.do HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,application/x-shockwave-flash, application/vnd.ms-excel,application/vnd.ms-powerpoint, application/msword, *
public static String url2Str(String urlString) {
try {
    StringBuffer html = new StringBuffer();  
    URL url = new URL(urlString);  
    HttpURLConnection conn = (HttpURLConnection)url.openConnection(); //只是创建实例,不连接 
    URLConnection c = conn; 
    String contentType = c.getContentType();  
    String characterEncoding = null;  
    int index = contentType.indexOf("charset="); 
    if(index == -1){  
      characterEncoding = "UTF-8";  
    }else{  
      characterEncoding =contentType.substring(index + 8, contentType.length()); 
    }  
    InputStreamReader isr = newInputStreamReader(conn.getInputStream(), characterEncoding); 
    BufferedReader br = new BufferedReader(isr); 
    String temp;  
    while ((temp = br.readLine()) != null) {  
            html.append(temp).append("\n");  
    }  
    br.close();  
    isr.close();  
    return html.toString();  
} catch (Exception e) {
  e.printStackTrace();  
    return null;  
}
}


5. 一个简单的HTTP服务器
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.File;
public class HttpServer {
public static final String WEB_ROOT =System.getProperty("user.dir") + File.separator + "webroot";
//关闭命令
private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
//是否关闭
private boolean shutdown = false;
public static void main(String[] args) {
   HttpServer server = new HttpServer();
    server.await();  //循环等待客户端请求
}
public void await() {
    ServerSocket serverSocket = null; 
    int port = 8080; 
    try { 
        //创建服务端Socket
        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对象并解析
            Request request = newRequest(input); 
            request.parse(); 
            //创建Response对象
          Response response = newResponse(output); 
          response.setRequest(request); 
          //返回静态页面信息(如HTML等)
          response.sendStaticResource(); 
          //关闭Socket流
          socket.close();
          //检测是否是关闭服务的命令URI
          shutdown =request.getUri().equals(SHUTDOWN_COMMAND); 
      } catch (Exception e) { 
            e.printStackTrace(); 
            continue; 
     
   
  }

}


*** Request对象 ***

import java.io.InputStream;
import java.io.IOException;
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input) {
this.input = input;
}

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<i; j++) {
    request.append((char) buffer[j]); 
}
System.out.print(request.toString());
    uri = parseUri(request.toString());
}

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对象 ***

import java.io.OutputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.File;
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 = newFileInputStream(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 { 
          // file not found 
          String errorMessage = "HTTP/1.1404 File Not Found\r\n" 
          + "Content-Type:text/html\r\n" 
          + "Content-Length: 23\r\n"+"\r\n" 
          +"<h1>File NotFound</h1>"; 
          output.write(errorMessage.getBytes()); 
     
    } catch (Exception e) { 
    // thrown if cannot instantiate a Fileobject 
    System.out.println(e.toString() );
    } finally { 
      if (fis!=null) 
      fis.close(); 
    }
  }
}

运行程序:
    浏览器中输入: http://localhost:8080/index.html,这里有必要提醒下的是,当我们在浏览器中输入url后,浏览器会根据域名找到IP,再结合端口号创建客户端Socket,并向服务器发送字节流信息.前面我们创建的HttpServer会接收到此次请求 -- 获取请求的地址信息(index.html) --调用response的sendStaticResource,注意我们这里返回的只有index.html文件本身的内容,并没有上面列举的标准返回信息中的头信息部分(HTTP/1.1302 Found Server: SAP J2EEEngine/7.00)这是因为我们只out了index.html,容器如tomcat一般都会在Response对象中设置一些默认值,当然我们也可以自己设置它的一些值,比如response.setContentType()...,最后容器在out的时候会根据response中的值组合成符合http协议规范的格式返回给客户端浏览器,浏览器根据response的一些头信息决定做什么动作,比如我们在response里设置response.setHeader("Content-disposition","attachment; filename=test.xls");  则浏览器会识别出是文件输出流,则会调用系统的文件对话框,显示打开或是保存,剩下的事情就是系统的事了.
    本章先简单介绍一下HTTP请求,并搭建了一个最简单的HttpServer,这个Server的IP和端口都是固定好的(后面显然要可配置),而且没有对应具体应用名称(如http://localhost:8080/ScmWeb/index.html),只是简单的返回了HTML页面,没有处理Servlet请求的能力,没有日志和session管理,没有监听器和过滤器的处理,所有信息都是硬编码,不是可配置的,等等,这些都是TOMCAT所具备的功能,会在后续章节中一一呈现,此篇仅是序言,所有程序
代码来自<< How Tomcat Work>>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值