这篇博文来自于《how tomcat works》一书的第一章
我们的服务器程序由下列三个类组成:
HttpServer.java
Request.java
Response.java
HttpServer.java是程序的入口。它的main方法创建了一个HttpServer的实例,然后调用它的await方法,此方法等待客户端的
HTTP请求,处理请求,把响应传回客户端。此服务器程序只能处理静态的资源,如HTML文件和图片文件。
我们来看看HttpServer.java的源代码
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class HttpServer {
- /**
- * WEB_ROOT是存放HTML文件的目录
- */
- public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
- //关闭命令
- private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
- //收到关闭命令
- private boolean shutdown = false;
- /**
- * @param args
- */
- public static void main(String[] args) {
- HttpServer server = new HttpServer();
- server.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 inputStream = null;
- OutputStream outputStream = null;
- try{
- socket = serverSocket.accept();
- inputStream = socket.getInputStream();
- outputStream = socket.getOutputStream();
- //创建请求对象并解析
- Request request = new Request(inputStream);
- request.parse();
- //创建响应对象
- Response response = new Response(outputStream);
- response.setRequest(request);
- response.sendStaticResource();
- //关闭socket
- if(socket != null){
- socket.close();
- }
- //检查URI是否是一个关闭命令
- shutdown = SHUTDOWN_COMMAND.equals(request.getUri());
- }catch(Exception e){
- e.printStackTrace();
- continue;
- }
- }
- }
- }
Request.java类代表一个HTTP请求,它的构造方法传入一个InputStream输入流,该输入流来自于与客户端交流的那个socket,即ServerSocket的accept方法返回的那个socket对象。下面是Request.java类的源代码:
- import java.io.IOException;
- import java.io.InputStream;
- public class Request {
- private InputStream inputStream;
- private String uri;
- public Request(InputStream inputStream) {
- this.inputStream = inputStream;
- }
- public void parse(){
- StringBuffer request = new StringBuffer(2048);
- int i;
- byte[] buffer = new byte[2048];
- try{
- i = inputStream.read(buffer);
- }catch(IOException e){
- e.printStackTrace();
- i = -1;
- }
- for(int j=0;j<i;j++){
- request.append((char)buffer[j]);
- }
- System.out.println(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;
- }else{
- return null;
- }
- }
- public String getUri() {
- return uri;
- }
- public void setUri(String uri) {
- this.uri = uri;
- }
- }
就是一个HTTP请求的URI,方法parseUri()是通过搜索请求的第一个空格和第二个空格间的字符串来得到URI的。
Response.java类代表一个HTTP响应,源代码如下:
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- public class Response {
- private static final int BUFFER_SIZE = 1024;
- Request request;
- OutputStream outputStream;
- public Response(OutputStream outputStream) {
- this.outputStream =outputStream;
- }
- 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){
- outputStream.write(bytes, 0, ch);
- ch = fis.read(bytes,0,BUFFER_SIZE);
- }
- }else{
- String errorMessage = "<h1>File not found</h1>";
- outputStream.write(errorMessage.getBytes());
- }
- }catch(Exception e){
- System.out.println(e.toString());
- }finally{
- if(fis != null)
- fis.close();
- }
- }
- }
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