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 ...
随机推荐
- CentOS 7下载地址(ISO文件)
CentOS安装文件有两类(32位和64位),每类下载对应有不同的版本,这些版本适合不同需求的用户.CentOS 7官方下载地址:https://www.centos.org/download/在Ce ...
- Method Overloading in WCF zt
Method overloading is the process of implementing Polymorphism in Object-Oriented Programming. A met ...
- PCB的技巧
(1)首先元件的移动,如下图中,向让D1的2引脚和R49的2引脚齐平,但是移动的距离每次都超过,不能平齐 修改元件最小移动距离即可,如下图,其中有很多可以改动的地方,但是需要改的是Component ...
- 兼容的placeholder属性
作为一个.net后台开发的程序猿,博客里既然大多都是前端相关的博文.是不是该考虑换方向了,转前端开发得了 ... 小小吐槽一下,近期受该不该跳槽所困惑,我有选择困难症! 继续前端,这次说一下输入框 p ...
- 控制反转(IoC)与依赖注入(DI)
前言 最近在学习Spring框架,它的核心就是IoC容器.要掌握Spring框架,就必须要理解控制反转的思想以及依赖注入的实现方式.下面,我们将围绕下面几个问题来探讨控制反转与依赖注入的关系以及在Sp ...
- [Python]网络爬虫(一):抓取网页的含义和URL基本构成
一.网络爬虫的定义 网络爬虫,即Web Spider,是一个很形象的名字. 把互联网比喻成一个蜘蛛网,那么Spider就是在网上爬来爬去的蜘蛛.网络蜘蛛是通过网页的链接地址来寻找网页的. 从网站某一个 ...
- android 使用intent传递参数实现乘法计算
主界面上是两个EditText和一个按钮.用于输入两个数字参数. calcute.xml: <?xml version="1.0" encoding="utf-8& ...
- 解决SDK下载时速度过慢的问题
1.打开android sdk manager 2.打开tool->options,如图所示 3.将Proxy Settings 里的HTTP Proxy Server和HTTP Proxy P ...
- Asp.net mvc 自定义全局的错误事件HandleErrorAttribute无效
Asp.net mvc 自定义全局的错误事件HandleErrorAttribute,结果无效, 原因: 1.没有在RegisterGlobalFilters 里面添加或者你要的位置添加. 2.你把这 ...
- String+,StringBuilder,String.format运行效率比较
实现String字符串相加的方法有很多,常见的有直接相加,StringBuilder.append和String.format,这三者的运行效率是有差异的,String是final类型的,每次相加都会 ...