今天我们就仿照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,