今天我们就仿照Tomcat服务器来手写一个最简单最迷你版的web服务器,仅供学习交流。

 1. 在你windows系统盘的F盘下,创建一个文件夹webroot,用来存放前端代码。
  2. 代码介绍:

(1)ServerThread.java 核心代码,主要用于web文件的读取与解析等。代码如下:

  1 package server;
2
3 import java.io.*;
4 import java.net.Socket;
5 import java.util.Date;
6 import java.util.HashMap;
7 import java.util.Map;
8
9 /**
10 * @ClassName: ServerThread
11 * @Description:
12 * @Author: liuhefei
13 * @Date: 2019/6/23
14 * @blog: https://www.imooc.com/u/1323320/articles
15 **/
16 public class ServerThread implements Runnable {
17
18 private static Map<String, String> contentMap = new HashMap<>();
19
20 //可以参照Tomcat的web.xml配置文件
21 static {
22 contentMap.put("html", "text/html");
23 contentMap.put("htm", "text/html");
24 contentMap.put("jpg", "image/jpeg");
25 contentMap.put("jpeg", "image/jpeg");
26 contentMap.put("gif", "image/gif");
27 contentMap.put("js", "application/javascript");
28 contentMap.put("css", "text/css");
29 contentMap.put("json", "application/json");
30 contentMap.put("mp3", "audio/mpeg");
31 contentMap.put("mp4", "video/mp4");
32 }
33
34 private Socket client;
35 private InputStream in;
36 private OutputStream out;
37 private PrintWriter pw;
38 private BufferedReader br;
39
40 private static final String webroot = "F:\\webroot\\"; //此处目录,你可以自行修改
41
42 public ServerThread(Socket client){
43 this.client = client;
44 init();
45 }
46
47 private void init(){
48 //获取输入输出流
49 try {
50 in = client.getInputStream();
51 out = client.getOutputStream();
52 } catch (IOException e) {
53 e.printStackTrace();
54 }
55
56 }
57
58 @Override
59 public void run() {
60 try {
61 gorun();
62 } catch (Exception e) {
63 e.printStackTrace();
64 }
65 }
66
67 private void gorun() throws Exception {
68 //读取请求内容
69 BufferedReader reader = new BufferedReader(new InputStreamReader(in));
70 String line = reader.readLine().split(" ")[1].replace("/", "\\"); //请求的资源
71 if(line.equals("\\")){
72 line += "index.html";
73 }
74 System.out.println(line);
75 String strType = line.substring(line.lastIndexOf(".")+1, line.length()); //获取文件的后缀名
76 System.out.println("strType = " + strType);
77
78 //给用户响应
79 PrintWriter pw = new PrintWriter(out);
80 InputStream input = new FileInputStream(webroot + line);
81
82 //BufferedReader buffer = new BufferedReader(new InputStreamReader(input));
83 pw.println("HTTP/1.1 200 ok");
84 pw.println("Content-Type: "+ contentMap.get(strType) +";charset=utf-8");
85 pw.println("Content-Length: " + input.available());
86 pw.println("Server: hello");
87 pw.println("Date: " + new Date());
88 pw.println();
89 pw.flush();
90
91 byte[] bytes = new byte[1024];
92 int len = 0;
93 while ((len = input.read(bytes)) != -1){
94 out.write(bytes, 0, len);
95 }
96 pw.flush();
97
98 input.close();
99 pw.close();
100 reader.close();
101 out.close();
102
103 client.close();
104 }
105 }
(2)HttpServer.java   (普通版)服务端
 1 package server;
2
3 import java.io.*;
4 import java.net.ServerSocket;
5 import java.net.Socket;
6 import java.util.Date;
7
8 /**
9 * @ClassName: HttpServer
10 * @Description: 服务端
11 * @Author: liuhefei
12 * @Date: 2019/6/23
13 * @blog: https://www.imooc.com/u/1323320/articles
14 **/
15 public class HttpServer {
16 public static void main(String[] args) throws IOException {
17 //启动服务器,监听9005端口
18 ServerSocket server = new ServerSocket(9005);
19 System.out.println("服务器启动,监听9005端口....");
20 while (!Thread.interrupted()){
21 //不停接收客户端请求
22 Socket client = server.accept();
23 //开启线程
24 new Thread(new ServerThread(client)).start();
25 }
26 server.close();
27 }
28 }

  (2)HttpServer1.java  (线程池版)服务端


 1 package server;
2
3 import java.io.IOException;
4 import java.net.ServerSocket;
5 import java.net.Socket;
6 import java.util.concurrent.ExecutorService;
7 import java.util.concurrent.Executors;
8
9 /**
10 * @ClassName: HttpServer
11 * @Description: 服务端
12 * @Author: liuhefei
13 * @Date: 2019/6/23
14 * @blog: https://www.imooc.com/u/1323320/articles
15 **/
16 public class HttpServer1 {
17 public static void main(String[] args) throws IOException {
18 //创建线程池
19 ExecutorService pool = Executors.newCachedThreadPool();
20
21 //启动服务器,监听9005端口
22 ServerSocket server = new ServerSocket(9005);
23 System.out.println("服务器启动,监听9005端口....");
24 while (!Thread.interrupted()){
25 //不停接收客户端请求
26 Socket client = server.accept();
27 //向线程池中提交任务
28 pool.execute(new ServerThread(client));
29 }
30 server.close();
31 pool.shutdown();
32 }
33 }

3. 将一个具有index.html的静态页面文件拷入到我们创建的webroot目录下。相关的静态web资源代码可以到源码之家下载或是自己编写。

4. 启动web服务,启动HttpServer.java 或HttpServer1.java都可以,服务启动之后将会监听9005端口。

5. 我们到浏览器上访问我们的服务,访问地址:http://localhost:9005/index.html,

 

手写一个最迷你的Web服务器的更多相关文章

  1. 手写一套迷你版HTTP服务器

    本文主要介绍如何通过netty来手写一套简单版的HTTP服务器,同时将关于netty的许多细小知识点进行了串联,用于巩固和提升对于netty框架的掌握程度. 服务器运行效果 服务器支持对静态文件css ...

  2. 『练手』手写一个独立Json算法 JsonHelper

    背景: > 一直使用 Newtonsoft.Json.dll 也算挺稳定的. > 但这个框架也挺闹心的: > 1.影响编译失败:https://www.cnblogs.com/zih ...

  3. 看年薪50W的架构师如何手写一个SpringMVC框架

    前言 做 Java Web 开发的你,一定听说过SpringMVC的大名,作为现在运用最广泛的Java框架,它到目前为止依然保持着强大的活力和广泛的用户群. 本文介绍如何用eclipse一步一步搭建S ...

  4. webview的简单介绍和手写一个H5套壳的webview

    1.webview是什么?作用是什么?和浏览器有什么关系? Webview 是一个基于webkit引擎,可以解析DOM 元素,展示html页面的控件,它和浏览器展示页面的原理是相同的,所以可以把它当做 ...

  5. 手把手教你手写一个最简单的 Spring Boot Starter

    欢迎关注微信公众号:「Java之言」技术文章持续更新,请持续关注...... 第一时间学习最新技术文章 领取最新技术学习资料视频 最新互联网资讯和面试经验 何为 Starter ? 想必大家都使用过 ...

  6. 手写一个虚拟DOM库,彻底让你理解diff算法

    所谓虚拟DOM就是用js对象来描述真实DOM,它相对于原生DOM更加轻量,因为真正的DOM对象附带有非常多的属性,另外配合虚拟DOM的diff算法,能以最少的操作来更新DOM,除此之外,也能让Vue和 ...

  7. 一个简单的Java web服务器实现

    前言 一个简单的Java web服务器实现,比较简单,基于java.net.Socket和java.net.ServerSocket实现: 程序执行步骤 创建一个ServerSocket对象: 调用S ...

  8. 教你如何使用Java手写一个基于链表的队列

    在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...

  9. 【spring】-- 手写一个最简单的IOC框架

    1.什么是springIOC IOC就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理. 如果我们手写一个最最简单的IOC,最终效果是怎样呢? xml配置: <b ...

随机推荐

  1. 【树形结构】51nod 1766 树上的最远点对

    题目内容 \(n\)个点被\(n−1\)条边连接成了一颗树,边有权值\(w_i\).有\(q\)个询问,给出\([a,b]\)和\([c,d]\)两个区间,表示点的标号请你求出两个区间内各选一点之间的 ...

  2. go 不停模拟 写日志

    package main import ( "os" "errors" "math/rand" "time" " ...

  3. PHP转Go系列:数组与切片 转

    数组的定义# 用过PHP的同学应该很清楚,无论多么复杂的数据格式都可以用数组来表达,什么类型的数据都可以往里塞,它是工作必备的一部分,使用很简单,易用程度简直变态. Copy $array = [1, ...

  4. linux(centos8):firewalld使用ipset管理ip地址的集合

    一,firewalld中ipset的用途: 1,用途 ipset是ip地址的集合, firewalld使用ipset可以在一条规则中处理多个ip地址, 执行效果更高 ​对ip地址集合的管理也更方便 2 ...

  5. ffmpeg实现视频转gif及gif缩放(ffmpeg4.2.2)

    一,为什么选择ffmpeg处理gif? 1,ffmpeg可以从视频中截取gif 2,ffmpeg在缩放gif时出错的机率较低, 而imagemagick在缩放gif时容易出错 我们在后面的例子中可以看 ...

  6. javascript arcgis 取区域中心点

    javascript arcgis 取区域中心点 //graphic是绘制完多边形之后返回的对象 //获得多边形的中心点坐标 var centerPoint=graphic.geometry.getE ...

  7. ES5新增数组的方法

    ES5新增数组的方法 ES5新增数组常见方法(indexOf/forEach/map/filter/some/every) .indexOf( data , start)  检测数组中是否存在指定数据 ...

  8. int是java.lang包中可用的类的名称

    int是java.lang包中可用的类的名称(x) int为基本数据类型,不是类

  9. Qlik Sense插件及QRS接口补充

    date: 2019-10-18 09:10:00 updated: 2019-10-18 15:18:00 Qlik Sense插件及QRS接口补充 1.插件 1.1 获取数据方式 理论上 Engi ...

  10. 基于Spring读写分离

    为什么是基于Spring的呢,因为实现方案基于Spring的事务以及AbstractRoutingDataSource(spring中的一个基础类,可以在其中放多个数据源,然后根据一些规则来确定当前需 ...