Tomcat学习1

来源:互联网 发布:国企混改 知乎 编辑:程序博客网 时间:2024/06/06 03:20

本文是学习《Tomcat深入剖析》后,对书中内容对总结,主要用于自己学习记录,纯手打。。。

Http请求分为三部分:

1、请求方法-------统一资源标识符--------协议/版本

2、请求头

3、实体(实体和请求头之间有一个空行)

如下:

GET /sample.jsp HTTP/1.1

Accept:image/gif.image/jpeg,*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)

Accept-Encoding:gzip,deflate

 

username=jinqiao&password=1234

Http响应同样分为三部分:

1、协议-----状态码-----描述

2、响应头

3、响应实体(响应头和响应实体之间有一个空行)

如下:

HTTP/1.1 200 OK

Date: Sat, 31 Dec 2005 23:59:59 GMT

Content-Type: text/html;charset=ISO-8859-1

Content-Length: 122


<html>

<head>

<title>Wrox Homepage</title>

</head>

<body>

<!-- body goes here -->

</body>

</html>

下面是一个例子(包括三个类:MyHttpServer,Request,Response),用浏览器访问本机IP地址和端口号,然后再控制台输出对应的内容。

====================分割线====================

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;import java.net.UnknownHostException;/** *  * MyHttpServer类主要作用: * 设置服务器根路径WEB_ROOT * new一个SeverSocket实例监听对应的端口当有响应到达时,调用accept方法返回一个Socket实例 * 获取Socket实例的输入输出流,使用自定义的Request对输入流按照Http协议进行解析,Response则按照Http协议进行数据的发送 */public class MyHttpServer {/** * 设置服务器根目录,里面存放各种资源 * 注意:“webroot”后面如果有分隔符则表示“webroot”是一个目录,下面还有子文件,如果后面没有分隔符则表示“webroot”是一个具体的文件 */public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"WebRoot"+File.separator;/** * 定义服务关闭指令 */private static final String SHUTDOWN_COMMAND="/SHUTDOWN";/** * 定义服务器关闭状态,默认为false */private boolean shutdown=false;public  static void main(String[] args){MyHttpServer myMailServer=new MyHttpServer();myMailServer.await();}public void await(){ServerSocket serverSocket=null;/** * 指定服务器默认监听端口 */int port = 8888;/** * 指定服务器请求队列最大长度 */int backlog=1;/** * 指定serverSocket监听的主机 */InetAddress address= null;try {address= InetAddress.getByName("127.0.0.1");serverSocket=new ServerSocket(port, backlog, address);}catch(UnknownHostException e){e.printStackTrace();System.exit(1);}catch (IOException e) {e.printStackTrace();System.exit(1);}System.out.println("服务器已成功启动");while(!shutdown){Socket socket=null;InputStream inputStream=null;OutputStream outputStream=null;try {/** * 当没有请求到达时,accept()会一直等待 */socket=serverSocket.accept();System.out.println("服务器收到一个请求");inputStream=socket.getInputStream();outputStream=socket.getOutputStream();/** * 构建一个Request类,用以解析Http请求的原始数据 */ Request request =new Request(inputStream);/** * 解析Http请求 */request.parse();/** * 构建一个Response类,用以返回请求 */Response response=new Response(outputStream);/** * 设置response,为返回请求做准备 */response.setRequest(request);/** * 判断Http请求静态资源还是servlet */response.sendStaticResource();socket.close();shutdown=request.getUri().equals(SHUTDOWN_COMMAND);} catch (Exception e) {e.printStackTrace();} }System.out.println("服务器关闭");}}

====================分割线====================

import java.io.IOException;import java.io.InputStream;public class Request {private InputStream inputStream;private String uri;/** * 创建Request时传入一个InputStream对象 */public Request(InputStream inputStream) {this.inputStream=inputStream;}public void parse() {/** * 定义一个StringBuffer对象,用以存储InputStream中传入的数据 */StringBuffer request=new StringBuffer(2048);byte[] bytes=new byte[2048];int i=-1;try {/** * 读取inputStream中的数据,并把读取的存入一个byte数组中 */i=this.inputStream.read(bytes);} catch (IOException e) {e.printStackTrace();}for(int j=0;j<i;j++){/** * 将byte数组中的数据放入StringBuffer中 */request.append((char)bytes[j]);}System.out.println(request.toString());this.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;}public String getUri() {return this.uri;}}

====================分割线====================

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;


public class Response {
/**
* 定义一个默认缓存字节长度
*/
private static final int BUFFER_SIZE=1024;
private OutputStream outputStream;
/**
* 定义一个request对象,获取request中的uri
*/
private Request request;




public Response(OutputStream outputStream) {
this.outputStream=outputStream;
}




public void setRequest(Request request) {
this.request=request;
}


public void sendStaticResource() {
byte[] bytes=new byte[BUFFER_SIZE];
FileInputStream fis=null;




try {
/**
* 加载请求资源文件
*/
File file=null;
try{
file=new File(MyHttpServer.WEB_ROOT,request.getUri());
System.out.println("请求资源绝对路径"+file.getAbsolutePath());
}catch(NullPointerException e){



if(file.exists()){
fis=new FileInputStream(file);
/**
* 读取file,每次读取长度为BUFFER_SIZE
*/
int ch=fis.read(bytes, 0, BUFFER_SIZE);
while(ch!=-1){
this.outputStream.write(bytes, 0, ch);
ch=fis.read(bytes, 0, BUFFER_SIZE);
}
}else{
System.out.println("请求资源不存在");
String errorMessage="HTTP/1.1 404 File Not Found\r\n"+
"Context-Type:text/html\r\n"+
"Context-Length:23\r\n"+
"\r\n"+
"<h1>File Not Found</h1>";
this.outputStream.write(errorMessage.getBytes());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}




}

====================分割线====================

程序启动后,在浏览器输入127.0.0.1:8888后,控制台显示如下:

服务器已成功启动
服务器收到一个请求
GET /123.html HTTP/1.1
Host: 127.0.0.1:8888
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: zh-CN,zh;q=0.8,und;q=0.6

请求资源绝对路径F:\JAVA\MyHttpServer1.0\WebRoot\123.html

浏览器显示:

0 0