读了两章的 How Tomcat Works
周一发现了一本书.How Tomcat Works 惯例先到豆瓣搜书评.结果书评出奇的好.然后下载了PDF.从简介中看,本书的每个章节都会不断的围绕怎么建造一个Tomcat讲解.我本人比较喜欢这种造轮子的书.原因很简单,比较笨.如果书中没有代码,很难从脑海中构件代码结构.可是万万没想到,看到第三章,就发现,书中的代码不全,完整的代码还要到GitHub下载.无奈只能放下这本好书.(个人觉得看书就是要了解本质,如果书中的源码不全,而是给出片段,剩下的还要到项目中找,我觉得你还不如让我去直接看Tomcat的源码.实名DISS,因为这件事昨晚都没睡好.)不过开卷有益,贴出来两段代码,安慰下自己.
本次代码都有注释,就不一一介绍了.
public class HttpServer {
//C:\workspace\yourTomcat\src /webroot
public static final String WEB_ROOT = System.getProperty("user.dir")+ File.separator+ "webroot";
//停止语句
private static final String SHUTDOWN_COMMAND="/SHUTDOWN";
//停止标识符
private boolean shutdown = false;
/*
* @author 顶风少年
* @date 2019/9/16 16:57
* @mail dfsn199703132038@foxmail.com
* @throws
* @param
* @result void
* @notify 监听请求
* version 1.0
*/
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 input = null;
OutputStream output = null;
try {
//客户端发送请求这里则会监听到
socket = serverSocket.accept();
//获取输入流
input = socket.getInputStream();
//获取输出流
output = socket.getOutputStream();
//解析请求对象
Request request = new Request(input);
request.parse();
//创建相应对象
Response response = new Response(output);
response.setRequest(request);
response.sendStaticResource();
//关闭socket通道
socket.close();
//如果客户端传递的停止则,更改监听标记
shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
}catch (Exception e){
e.printStackTrace();
continue;
}
}
}
}
public class Request {
private InputStream input;
private String uri;
public Request(InputStream input) {
this.input = input;
}
/*
* @author 顶风少年
* @date 2019/9/16 16:57
* @mail dfsn199703132038@foxmail.com
* @throws
* @param
* @result void
* @notify 解析请求内容
* version 1.0
*/
public void parse() {
//将字节转换成字符
StringBuffer request = new StringBuffer(2048);
//是否读取结束
int i;
//将字节读取到此处
byte[] buffer = new byte[2048];
try {
//读取
i = input.read(buffer);
} catch (IOException e) {
e.printStackTrace();
i = -1;
}
//循环将字节放到String中
for (int j = 0; j < i; j++) {
request.append((char) buffer[j]);
}
//解析请求资源路径
uri = parseUri(request.toString());
}
/*
* @author 顶风少年
* @date 2019/9/16 16:59
* @mail dfsn199703132038@foxmail.com
* @throws
* @param
* @param requestString
* @result java.lang.String
* @notify 解析请求资源路径
* version 1.0
*/
private String parseUri(String requestString) {
//记录前两个空格,第一个空格和第二个空格之间是 请求路径 GET /SHUTDOWN HTTP/1.1
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;
}
/*
* @author 顶风少年
* @date 2019/9/16 17:00
* @mail dfsn199703132038@foxmail.com
* @throws
* @param
* @result java.lang.String
* @notify 获取请求路径
* version 1.0
*/
public String getUri() {
return uri;
}
}
public class Response {
private static final int BUFFER_SIZE = 1024;
Request request;
OutputStream output;
public Response(OutputStream output) {
this.output = output;
}
/*
* @author 顶风少年
* @date 2019/9/16 17:01
* @mail dfsn199703132038@foxmail.com
* @throws
* @param
* @param request
* @result void
* @notify 设置request
* version 1.0
*/
public void setRequest(Request request) {
this.request = request;
}
/*
* @author 顶风少年
* @date 2019/9/16 17:02
* @mail dfsn199703132038@foxmail.com
* @throws
* @param
* @result void
* @notify 相应资源
* version 1.0
*/
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);
//如果读取到了内容
output.write("HTTP/1.1 200 OK\\r\\nContent-Type: text/html\r\n\r\n".getBytes());
while (ch != -1) {
//将内容写入到响应体
output.write(bytes, 0, ch);
//再次读取
ch = fis.read(bytes, 0, BUFFER_SIZE);
}
} 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>";
//写入提示信息
output.write(errorMessage.getBytes());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
if (fis != null) {
fis.close();
}
}
}
}
说起来这是我加入博客园一来,第一次写带感情的文章.从16年6月认识java.到18年工作做得微信小程序,以及少量的java工作.再到今年的运维,偏向java.这几年,我一直不断的学习java.java基础的书看了三本.
其他的语言js,html,c++,c#包括sql.这么多语言来讲,我还是最喜欢java,起先写java就是写demo,工作后的一段时间写crud觉得十分无趣.在后来读了几本书,才知道原来在crud的工作中,也可以加入设计模式,编
程思想.以后的工作,我时常将一些模式,和一些设计写到工作中的crud代码中,力图让工作不在那么无趣,也让自己写的代码看上去优雅些.对于java只想说,不忘初心,方得始终.
最后希望明年我能找到一份真正的java开发工作.在这最后的几个月,我也将继续修炼内功.学习更多的招式.晚安!
读了两章的 How Tomcat Works的更多相关文章
- How tomcat works(深入剖析tomcat)阅读笔记1-4章
How tomcat works chapter 1 简单的web服务器 这一张的主要内容就是实现一个简单的静态资源服务器,socket编程,利用java提供的socket和serverSocket编 ...
- 深入刨析tomcat 之---第8篇 how tomcat works 第11章 11.9应用程序,自定义Filter,及注册
writed by 张艳涛, 标签:全网独一份, 自定义一个Filter 起因:在学习深入刨析tomcat的学习中,第11章,说了调用过滤链的原理,但没有给出实例来,自己经过分析,给出来了一个Filt ...
- how tomcat works 札记(两)----------一个简单的servlet集装箱
app1 (看着眼前这章建议读者,看how tomcat works 札记(一个)----------一个简单的webserver http://blog.csdn.net/dlf123321/art ...
- 深入刨析tomcat 之---第11篇 how tomcat works( 第15章 ) 如何解析web.xml 文件
writedby 张艳涛 记得当年是学习jsp的时候,写过web.xml中的标签.在之后的springmvc中也是有关于配置mvc 过滤器 和dispatchServlet的标签,之前是看不懂呢!看到 ...
- How tomcat works(深入剖析tomcat)servlet容器
How tomcat works (5)servlet容器阅读笔记 第四章阅读了tomcat默认连接器的实现,当时connector中的使用的容器是自定义的容器,也是非常之简单奥,一个人就干完了所有的 ...
- How Tomcat Works(十八)
在前面的文章中,如果我们要启动tomcat容器,我们需要使用Bootstrap类来实例化连接器.servlet容器.Wrapper实例和其他组件,然后调用各个对象的set方法将它们关联起来:这种配置应 ...
- how tomcat works 读书笔记四 tomcat的默认连接器
事实上在第三章,就已经有了连接器的样子了,只是那仅仅是一个学习工具,在这一章我们会開始分析tomcat4里面的默认连接器. 连接器 Tomcat连接器必须满足下面几个要求 1 实现org.apache ...
- how tomcat works 总结
希望各位网友在看完<<how tomcat works>>一书或者鄙人的tomcat专栏文章后再看这篇博客 这里主要是梳理各个章节的核心概念 第一章 一个简单的Web服务器 第 ...
- How tomcat works(深入剖析tomcat)(7) Logger
How tomcat works (7)日志记录器 总体概述 顾名思义,这一章将的是tomcat的日志记录器组件,比较简单,tomcat提供了几种类型不同的日志记录器,但是所有的日志记录器都需要实现L ...
随机推荐
- C#通过PInvoke调用c++函数的备忘录
目前知道的情况被调用的C/C++函数只能是全局函数 不能调用类中的成员方法 被调用的C函数必须使用extern “C“包含,保证采用的导出函数名生成规则和.NET一致 函数调用约定通常使用WINAPI ...
- ADO.NET中的5个主要对象
1.Connection:主要是开启程序和数据库之间的连接.没有利用连接对象将数据库打开,是无法从数据库中取得数据的. Close和Dispose的区别,Close以后还可以Open,Dispose以 ...
- 大话区块链【Blockchain】
最近这几天区块链又粉墨登场了,新闻媒体也一直在大量报道,宣称可能要在金融界掀起一番浪潮.甚至有人说很久之前中国就出现了区块链的产物——麻将.那么区块链到底是什么,麻将和区块链又有什么关系呢? 笔者这两 ...
- 用maven对ssm进行整合
网上有很多ssm整合的教程,这里给像我这样的初学的新手提供一个整合方法,同时也记录一下自己的学习进度. 同时推荐观看相关视频 https://www.bilibili.com/video/av536 ...
- 前端开发JS——快速入门
1.JS的核心标准ECMAScript 组成 ECMAScript------>核心语法标准 DOM------------->对文档节点的操作 ...
- vue学习指南:第十篇(详细) - Vue的 动画
Vue 提供了一些不同的过度效果,主要根 v-if v-show 动态组件 1. Vue给动画分了6个过程,在css中,扮演6个类, 1. .v-enter定义动画的开始状态 2. .v-ente ...
- 【原创】Airflow调用talend
核心原理 因为talend job build出来是一个可直接运行的程序,可以通过shell命名启动job进程,因此可以使用airflow的bashoperator调用生成好的talend job包里 ...
- 流程及迭代驱动测试管理软件, itest 发布到开源中国
itest 源码已发布到码云 ,项目已被开源中国收录!详见 https://www.oschina.net/p/itest-cn 测试人自己开发,汇聚10年沉淀,独创流程驱动测试.度量展现测试人价值 ...
- python3 AES 加解密
#coding:utf-8 import base64 from Crypto.Cipher import AES #注:python3 安装 Crypto 是 pip3 install -i htt ...
- git fatal: remote origin already exists错误解决方案
$ git remote add origin git@github.com:AntonioSu/learngitWindows.git 在运行以上代码出现的错误,此错误是因为已经存在了远程分支,只需 ...