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. [PeterDLax著泛函分析习题参考解答]第7章 Hilbert 空间结果的应用

    1. 对测度是 $\sigma$ 有限的情形证明 Radon-Nikodym 定理. 证明: 设 $\mu,\nu$ 均为 $\sigma$ 有限的非负测度, 则存在分割 $$\bex X=\cup_ ...

  2. 利用MsChart控件绘制多曲线图表 z

    在.Net4.0框架中,微软已经将Mschart控件集成了进来,以前一直在web下面用过,原来winform下的Mschart控件更加简单更加方便,今天我们用mschart绘制一个多曲线图,话不多说, ...

  3. bat处理打开关门exe

    @echo off rem rem 注释 tastkill /f /im a.exe cd %CD% %CD:~0,1%: cd  %Cd%b start %CD%a.exe cd .. %CD:~0 ...

  4. 关于缓存的tips——HTTP权威指南读书心得(十三)

    上一章介绍了缓存新鲜度判断的基本原理,本章对于缓存新鲜度判断方法进行一些补充(更新间隔略长略长..). 关于缓存的TIPS 服务器可以通过http定义的几种header对可以缓存数据的存在时间进行控制 ...

  5. Linux方向职业规划

    Linux方向职业分析 引言: 据了解,Linux普通网络管理人员的月薪大约5000元左右,负责编程的Linux软件工程师月薪大约在8000元到12000元之间,Linux嵌入式软件开发人员的月薪大约 ...

  6. 转载: pyExcelerator(Python操作Excel内库)API 文档

    1.pyExcelerator 主要通过俩个Object操作Excel: Workbook 和Worksheet2.pyExcelerator 读取Excel文件 parase_xls(filenam ...

  7. HTML5 UTF-8 中文乱码

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. hihocoder 1077线段树

    http://hihocoder.com/problemset/problem/1077 #include <bits/stdc++.h> using namespace std; #de ...

  9. ASP.NET- Web.Config配置大文件上传

    在web.config中的<system.web></system.web>内加入如下代码: <httpRuntime executionTimeout="60 ...

  10. (3/18)重学Standford_iOS7开发_Objective-C_课程笔记

    第三课: 本节课主要是游戏实现的demo,因此我将把课程中简单的几个编程技巧提取出来,重点介绍如何自己实现作业中的要求. 纸牌游戏实现: ①游戏的进行是模型的一部分(理解什么是模型:Model = W ...