how tomcat works<一>

本文详细介绍了如何利用Java实现一个简单的HTTP服务器,包括核心类HttpServer、Request和Response的功能与工作流程,以及如何启动服务器并在浏览器中访问静态资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇博文来自于《how tomcat works》一书的第一章

我们的服务器程序由下列三个类组成:

     HttpServer.java

     Request.java

     Response.java

HttpServer.java是程序的入口。它的main方法创建了一个HttpServer的实例,然后调用它的await方法,此方法等待客户端的

HTTP请求,处理请求,把响应传回客户端。此服务器程序只能处理静态的资源,如HTML文件和图片文件。


我们来看看HttpServer.java的源代码

[java]  view plain copy
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.io.OutputStream;  
  5. import java.net.InetAddress;  
  6. import java.net.ServerSocket;  
  7. import java.net.Socket;  
  8.   
  9. public class HttpServer {  
  10.     /** 
  11.      * WEB_ROOT是存放HTML文件的目录 
  12.      */  
  13.     public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";  
  14.       
  15.     //关闭命令  
  16.     private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";  
  17.       
  18.     //收到关闭命令  
  19.     private boolean shutdown = false;  
  20.   
  21.     /** 
  22.      * @param args 
  23.      */  
  24.     public static void main(String[] args) {  
  25.         HttpServer server = new HttpServer();  
  26.         server.await();  
  27.   
  28.     }  
  29.   
  30.     public void await() {  
  31.         ServerSocket serverSocket = null;  
  32.         int port = 8080;  
  33.         try{      
  34.             serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));   
  35.         }catch(IOException e){  
  36.             e.printStackTrace();  
  37.             System.exit(1);  
  38.         }  
  39.         //等待请求  
  40.         while(!shutdown){  
  41.             Socket socket = null;  
  42.             InputStream inputStream = null;  
  43.             OutputStream outputStream = null;  
  44.             try{  
  45.               
  46.                 socket = serverSocket.accept();  
  47.                 inputStream = socket.getInputStream();  
  48.                 outputStream = socket.getOutputStream();  
  49.                   
  50.                 //创建请求对象并解析  
  51.                 Request request = new Request(inputStream);  
  52.                 request.parse();  
  53.                   
  54.                 //创建响应对象  
  55.                 Response response = new Response(outputStream);  
  56.                 response.setRequest(request);  
  57.                 response.sendStaticResource();  
  58.                   
  59.                 //关闭socket  
  60.                 if(socket != null){  
  61.                      socket.close();  
  62.                 }  
  63.                     
  64.                 //检查URI是否是一个关闭命令  
  65.                 shutdown = SHUTDOWN_COMMAND.equals(request.getUri());  
  66.                   
  67.             }catch(Exception e){  
  68.                 e.printStackTrace();  
  69.                 continue;  
  70.             }  
  71.         }  
  72.     }  
  73.   
  74. }  

Request.java类代表一个HTTP请求,它的构造方法传入一个InputStream输入流,该输入流来自于与客户端交流的那个socket,即ServerSocket的accept方法返回的那个socket对象。下面是Request.java类的源代码:

[java]  view plain copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3.   
  4. public class Request {  
  5.     private InputStream inputStream;  
  6.     private String uri;  
  7.     public Request(InputStream inputStream) {  
  8.         this.inputStream = inputStream;  
  9.     }  
  10.       
  11.     public void parse(){  
  12.         StringBuffer request = new StringBuffer(2048);  
  13.         int i;  
  14.         byte[] buffer = new byte[2048];  
  15.         try{  
  16.             i = inputStream.read(buffer);  
  17.         }catch(IOException e){  
  18.             e.printStackTrace();  
  19.             i = -1;  
  20.         }  
  21.         for(int j=0;j<i;j++){  
  22.             request.append((char)buffer[j]);  
  23.         }  
  24.         System.out.println(request.toString());  
  25.         uri = parseUri(request.toString());  
  26.     }  
  27.       
  28.     private String parseUri(String requestString){  
  29.         int index1,index2;  
  30.         index1 = requestString.indexOf(" ");  
  31.         if(index1 != -1){  
  32.             index2 = requestString.indexOf(" ",index1 + 1);  
  33.             if(index2 > index1)  
  34.                 return requestString.substring(index1+1,index2);  
  35.             return null;  
  36.         }else{  
  37.             return null;  
  38.         }  
  39.     }  
  40.   
  41.     public String getUri() {  
  42.         return uri;  
  43.     }  
  44.   
  45.     public void setUri(String uri) {  
  46.         this.uri = uri;  
  47.     }  
  48.       
  49.       
  50.       
  51.   
  52. }  


方法parse()用来解析HTTP请求的数据。方法parseUri()根据传入的请求数据(一个字符串)解析出HTTP请求的URI,如GET  /index.html  HTTP/1.1中的 /index.html

就是一个HTTP请求的URI,方法parseUri()是通过搜索请求的第一个空格和第二个空格间的字符串来得到URI的。


Response.java类代表一个HTTP响应,源代码如下:


[java]  view plain copy
  1. import java.io.File;  
  2. import java.io.FileInputStream;  
  3. import java.io.IOException;  
  4. import java.io.OutputStream;  
  5.   
  6. public class Response {  
  7.     private static final int BUFFER_SIZE = 1024;  
  8.     Request request;  
  9.     OutputStream outputStream;  
  10.       
  11.     public Response(OutputStream outputStream) {  
  12.         this.outputStream =outputStream;  
  13.     }  
  14.   
  15.     public void setRequest(Request request) {  
  16.         this.request = request;  
  17.     }  
  18.   
  19.     public void sendStaticResource() throws IOException{  
  20.         byte bytes[] = new byte[BUFFER_SIZE];  
  21.         FileInputStream fis = null;  
  22.         try{  
  23.             File file = new File(HttpServer.WEB_ROOT,request.getUri());  
  24.             if(file.exists()){  
  25.                 fis = new FileInputStream(file);  
  26.                 int ch = fis.read(bytes,0,BUFFER_SIZE);  
  27.                 while(ch != -1){  
  28.                     outputStream.write(bytes, 0, ch);  
  29.                     ch = fis.read(bytes,0,BUFFER_SIZE);  
  30.                 }  
  31.             }else{  
  32.                 String errorMessage = "<h1>File not found</h1>";  
  33.                 outputStream.write(errorMessage.getBytes());  
  34.             }  
  35.         }catch(Exception e){  
  36.            System.out.println(e.toString());  
  37.         }finally{  
  38.             if(fis != null)  
  39.             fis.close();  
  40.         }  
  41.           
  42.           
  43.     }  
  44.       
  45.       
  46.   
  47. }  

Response类的构造方法传入一个OutputStream输出流,此输出流来自于socket的getOutputStream()方法,而此socket又来自于ServerSocket的accept方法返回的对象

Response类的sendStaticResource()方法先找到HTTP请求头的URI所代表的文件,将此文件读入到一个字节数组,再用OutputStream输出流将字节数组写入到客户端

的浏览器。如果URI所代表的文件不存在,就向浏览器写入一个错误信息。


启动HttpServer类,在浏览器中输入http://localhost:8080/index.html,(可以自己在此web工程的WebRoot根目录下新建一个index.html文件),你将看到index.html在浏览器

中显示出来。



转自:http://blog.youkuaiyun.com/wenjingyu/article/details/10168187

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值