Tomcat源码学习记录--web服务器初步认识
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服务器初步认识的更多相关文章
- Tomcat源码学习(1)
Tomcat源码学习(1) IntelliJ IDEA 17.3.3 导入 Tomcat 9.0.6源码 下载源码 tomcat_9.0.6 启动 IDEA. 点击 Open,选择刚才下载的文件解压后 ...
- Tomcat源码学习
Tomcat源码学习(一) 转自:http://carllgc.blog.ccidnet.com/blog-htm-do-showone-uid-4092-type-blog-itemid-26309 ...
- 【Tomcat源码学习】-1.概述
Tomcat是用java语言开发的一个Web服务器,最近花了差不多两周时间对Tomcat 9.0源码进行了一遍学习,由于知识储备有限,也只是理解了一个大概,下面就由我来给大家分享一下我对Tomcat的 ...
- hashMap源码学习记录
hashMap作为java开发面试最常考的一个题目之一,有必要花时间去阅读源码,了解底层实现原理. 首先,让我们看看hashMap这个类有哪些属性 // hashMap初始数组容量 static fi ...
- Tomcat源码学习 - 环境搭建
一. 源码下载 PS: 多图预警 在开始阅读源码之前,我们需要先构建一个环境,这样才能便于我们对源码进行调试,具体源码我们可以到官网进行下载(这里我以8.5.63版本为例). 二. 项目导入 下载并解 ...
- Tomcat源码学习一
这段时间工作不太忙,所以抽时间学习了TOMCAT, TOMCAT实际就是负责保持TCP连接传递到部署的项目中.浏览器实质就是TCP发送器.将用户的请求封装成TCP发送请求.当然格式是双方协定的.使用的 ...
- java内置线程池ThreadPoolExecutor源码学习记录
背景 公司业务性能优化,使用java自带的Executors.newFixedThreadPool()方法生成线程池.但是其内部定义的LinkedBlockingQueue容量是Integer.MAX ...
- redux-thunk 源码学习记录
redux触发store更新,使用的dispatch(action),在关于createStore的源码解读中可以看到,store.dispatch限制了action必须是一个纯对象.是为了保持red ...
- selenium expected_conditions 源码学习记录
#expected_conditions模块收集了一系列的场景判断方法 #源码地址 # https://seleniumhq.github.io/selenium/docs/api/py/_modul ...
随机推荐
- HDU 5961 传递 【图论+拓扑】 (2016年中国大学生程序设计竞赛(合肥))
传递 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem ...
- MySqlCommand, MySqlParameter and "LIKE" with Percent Symbol
//Wrong way MySqlCommand cmd = oldDb.GetSqlStringCommand(CommandType.Text,"SELECT * _ FROM user ...
- 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 ...
- Java新手入门必须掌握的30个基本概念
今天给大家推荐的文章是有关Java基本概念的,掌握好这些基本概念对学习J2SE.J2EE.J2ME都很重要,也能更好地理解Java的精髓,初学者要注意啦! ▶Java概述: 目前Java主要应用于中间 ...
- Jquery Datatables 动态列名
Datatables中文网:http://dt.thxopen.com/index.html 尝试: <table id="sp_table" class="dis ...
- vmware 收缩硬盘大小(compat,shrink,vmware-vdiskmanager)
3.vmware-vdiskmanager 虚拟机在使用过程中,虚拟磁盘的大小会不断变大.即使你删除了磁盘中的文件,虚拟磁盘的大小仍然不会缩小.VMWare在VMWare Tools中推出了Shrin ...
- C语言练习题_北理工的恶龙
背景:最近,北理工出现了一只恶龙,它长着很多 头,而且还会吐火,它将会把北理工烧成废墟, 于是,校长下令召集全校所有勇士杀死这只恶龙.要杀死这只龙,必须把它所有的头都砍掉,每个勇士只能砍一个龙头,龙的 ...
- ios 页面滑入滑出
从左边滑进 CGRect r1,r2; r1 = app.testview.view.frame; r2 = self.view.frame; [app.testview.view setFrame: ...
- 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 ...
- js模拟下载
<a id="downFile" href="" style="display: none;"><span id=&quo ...