Tomcat作为开源的轻量级WEB服务器,虽然不是很适合某些大型项目,但是它开源,读其源代码可以很好的提高我们的编程功底和设计思维。Tomcat中用到了很多比较好的设计模式,其中代码风格也很值得我们去效仿。前阵子看了Tomcat源码分析这本书,特此过来分享分享自己的学习过程记录。说得不好,大神不要喷我。

  也不废话了,直入主题上代码。Tomcat是什么,Tomcat是一个web服务器,能够接收请求,作出响应。接收请求,作出响应让我们联想到Socket编程。我们可以起一个线程服务ServerSocket来监听本机的8080端口(可配置),然后就可以在浏览器上访问http://localhost:8080/index.html,这个时候就可以通过socket的inputstream获取到浏览器封装的HTTP请求了,然后就可以针对这个请求来大做文章。以下是服务端的代码

 package cn.tim.server.core;

 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; /**
* HTTP服务器,主类
* @author TIM
*
*/
public class HttpServer { /**
* 端口
*/
public int PORT = 8080; /**
* 关闭指令
*/
public final static String SHUTDOWN = "SHUTDOWN"; /**
* webroot根目录
*/
public static final String WEB_ROOT =
System.getProperty("user.dir") + File.separator + "WebRoot"; public static void main(String[] args) { new HttpServer().await(); } /**
* 线程监听
*/
private void await() { ServerSocket server = null;
try {
server = new ServerSocket(PORT,1,
InetAddress.getByName("127.0.0.1"));
} catch (Exception e) {
e.printStackTrace();
} boolean shutdown = false;
while(!shutdown) {
Socket client = null;
InputStream in = null;
OutputStream out = null;
try {
// 获取到请求socket
client = server.accept();
in = client.getInputStream();
out = client.getOutputStream(); // 生成request同时解析请求
Request request = new Request(in);
request.parse(); // 生成response
Response response = new Response(out);
response.setRequest(request);
// 根据资源定位符发送对应资源
response.sendStaticResource();
client.close(); shutdown = request.getUri().equals(SHUTDOWN);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
continue;
} } } }

  既然服务端HttpServer都出来了,Request都干些什么,request顾名思义,请求肯定是封装请求的一个JAVA类,肯定要能够解析HTTP请求,例如访问静态资源,就得获取到静态资源的资源定位符uri。

  HTTP请求Request类:

 GET /index.html HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; MALCJS)
Accept-Encoding: gzip, deflate
Host: localhost:8080
DNT: 1
Connection: Keep-Alive
Cookie: principal=user:admin__password:admin
 package cn.tim.server.core;

 import java.io.IOException;
import java.io.InputStream; /**
* 封装请求
* @author TIM
*
*/
public class Request { /**
* 请求输入流
*/
private InputStream in; /**
* 资源定位符
*/
private String uri; /**
* 初始化request,传入socket输入流
* @param in
*/
public Request(InputStream in) {
this.in = in;
} /**
* 根据请求字符串解析请求
*/
public void parse() { try {
byte[] bytes = new byte[2048];
int i = in.read(bytes); StringBuffer buffer = new StringBuffer(2048);
for(int j=0; j<i; j++) {
buffer.append((char)bytes[j]);
}
System.out.println(buffer.toString());
uri = parseUri(buffer.toString());
System.out.println(uri);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } /**
* 解析出资源定位符uri,实际上就是用字符串分拆获取到GET /index.html HTTP/1.1中的/index,html
* @return
*/
private String parseUri(String requestString) { int index1 = requestString.indexOf(" ");
if(index1 != -1) {
int index2 = requestString.indexOf(" ", index1+1);
if(index2>index1) {
return requestString.substring(index1+1, index2);
}
}
return null;
} public InputStream getIn() {
return in;
} public String getUri() {
return uri;
} }

  获取到资源定位符,接下来就是根据资源定位符来作出相应,当然实际的Tomcat处理方式肯定是很复杂的,我们只模仿其中简单的方式,访问静态资源。

  Response类:

 package cn.tim.server.core;

 import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; public class Response { /**
* 输出
*/
private OutputStream out; /**
* 缓冲大小
*/
public final static int BUFFER_SIZE = 2048; /**
* 请求,根据请求作出对应的响应
*/
private Request request; public Response(OutputStream out) {
this.out = out;
} /**
* 发送静态资源
*/
public void sendStaticResource() { byte[] bytes = new byte[BUFFER_SIZE];
InputStream in = null;
try {
File file = new File(HttpServer.WEB_ROOT, request.getUri());
// 请求的资源存在
if(file.exists()) {
in = new FileInputStream(file);
int ch;
if((ch=in.read(bytes, 0, BUFFER_SIZE))!=-1) {
out.write(bytes, 0, ch);
}
}
// 请求资源不存在报404
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" +
"<h1>File Not Found</h1>";
out.write(errorMessage.getBytes());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(in!=null)
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} } public void setRequest(Request request) {
this.request = request;
} }

  这样,一个简单的Web服务器就实现了,可以访问静态资源,直接在浏览器上访问,没有找到对应的资源还可以报404错误。今天就写到这里,继续努力。。。

  

Tomcat源码学习记录--web服务器初步认识的更多相关文章

  1. Tomcat源码学习(1)

    Tomcat源码学习(1) IntelliJ IDEA 17.3.3 导入 Tomcat 9.0.6源码 下载源码 tomcat_9.0.6 启动 IDEA. 点击 Open,选择刚才下载的文件解压后 ...

  2. Tomcat源码学习

    Tomcat源码学习(一) 转自:http://carllgc.blog.ccidnet.com/blog-htm-do-showone-uid-4092-type-blog-itemid-26309 ...

  3. 【Tomcat源码学习】-1.概述

    Tomcat是用java语言开发的一个Web服务器,最近花了差不多两周时间对Tomcat 9.0源码进行了一遍学习,由于知识储备有限,也只是理解了一个大概,下面就由我来给大家分享一下我对Tomcat的 ...

  4. hashMap源码学习记录

    hashMap作为java开发面试最常考的一个题目之一,有必要花时间去阅读源码,了解底层实现原理. 首先,让我们看看hashMap这个类有哪些属性 // hashMap初始数组容量 static fi ...

  5. Tomcat源码学习 - 环境搭建

    一. 源码下载 PS: 多图预警 在开始阅读源码之前,我们需要先构建一个环境,这样才能便于我们对源码进行调试,具体源码我们可以到官网进行下载(这里我以8.5.63版本为例). 二. 项目导入 下载并解 ...

  6. Tomcat源码学习一

    这段时间工作不太忙,所以抽时间学习了TOMCAT, TOMCAT实际就是负责保持TCP连接传递到部署的项目中.浏览器实质就是TCP发送器.将用户的请求封装成TCP发送请求.当然格式是双方协定的.使用的 ...

  7. java内置线程池ThreadPoolExecutor源码学习记录

    背景 公司业务性能优化,使用java自带的Executors.newFixedThreadPool()方法生成线程池.但是其内部定义的LinkedBlockingQueue容量是Integer.MAX ...

  8. redux-thunk 源码学习记录

    redux触发store更新,使用的dispatch(action),在关于createStore的源码解读中可以看到,store.dispatch限制了action必须是一个纯对象.是为了保持red ...

  9. selenium expected_conditions 源码学习记录

    #expected_conditions模块收集了一系列的场景判断方法 #源码地址 # https://seleniumhq.github.io/selenium/docs/api/py/_modul ...

随机推荐

  1. HDU 5961 传递 【图论+拓扑】 (2016年中国大学生程序设计竞赛(合肥))

    传递 Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)     Problem ...

  2. MySqlCommand, MySqlParameter and "LIKE" with Percent Symbol

    //Wrong way MySqlCommand cmd = oldDb.GetSqlStringCommand(CommandType.Text,"SELECT * _ FROM user ...

  3. Never use GetDate() when comparing date timesoffsets, use SYSDATETIMEOFFSET()

    -- my current uk time is 2014-01-09 10:43:00 +0 ) = '2014-01-09 18:43:00 +08:00'; ) = '2014-01-09 02 ...

  4. Java新手入门必须掌握的30个基本概念

    今天给大家推荐的文章是有关Java基本概念的,掌握好这些基本概念对学习J2SE.J2EE.J2ME都很重要,也能更好地理解Java的精髓,初学者要注意啦! ▶Java概述: 目前Java主要应用于中间 ...

  5. Jquery Datatables 动态列名

    Datatables中文网:http://dt.thxopen.com/index.html 尝试: <table id="sp_table" class="dis ...

  6. vmware 收缩硬盘大小(compat,shrink,vmware-vdiskmanager)

    3.vmware-vdiskmanager 虚拟机在使用过程中,虚拟磁盘的大小会不断变大.即使你删除了磁盘中的文件,虚拟磁盘的大小仍然不会缩小.VMWare在VMWare Tools中推出了Shrin ...

  7. C语言练习题_北理工的恶龙

    背景:最近,北理工出现了一只恶龙,它长着很多 头,而且还会吐火,它将会把北理工烧成废墟, 于是,校长下令召集全校所有勇士杀死这只恶龙.要杀死这只龙,必须把它所有的头都砍掉,每个勇士只能砍一个龙头,龙的 ...

  8. ios 页面滑入滑出

    从左边滑进 CGRect r1,r2; r1 = app.testview.view.frame; r2 = self.view.frame; [app.testview.view setFrame: ...

  9. Get the largest sum of contiguous subarray in an int array

    When I finished reading this problem,I thought I could solve it by scanning every single subarray in ...

  10. js模拟下载

    <a id="downFile" href="" style="display: none;"><span id=&quo ...