自己做一個微型靜態Web服務器
這一篇簡單粗暴一點,先上乾貨,看代碼註釋
JDK版本:1.8
實現自定義錯誤頁、404頁。
package com.hawkon;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;
public class MyServer {
public static String HOME_DIR = "d:/home"; //定義服務器默認的文件夾在哪裏
public static String NOT_FOUND_FILE = "d:/home/404.html"; //定義404錯誤頁
public static String ERR_FILE = "d:/home/err.html"; //定義500錯誤頁
public static String DEFAULT_FILE = "/index.html"; //定義默認頁面
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8009); //定義端口
while (true) { //循環是不斷的接受新的請求
Socket socket = serverSocket.accept(); //當服務器運行起來沒有請求的時候會在這裏等待
InputStream is = socket.getInputStream(); //創建一個輸入流
InputStreamReader sr = new InputStreamReader(is); //過渡代碼主要是爲下一行創建對象
BufferedReader br = new BufferedReader(sr); //創建BufferedReader對象,在本文中採用一行一行的讀的方式,比較方便。
try {
String request = "";
request = br.readLine(); //只讀取了第一行,後面報頭本文暫時沒用。
System.out.println("request:");
System.out.println(request); //輸出一下請求的報頭
String[] arr = request.split(" "); //拆分出第一行的三部分內容
do { //循環是爲了把剩下的請求內容讀完,否則會產生異常
request=br.readLine();
System.out.println(request); //把全部報頭都輸出
}while(!request.equals(""));
if (arr.length != 3 || !arr[0].equals("GET")) { //如果不是GET請求,拆分出的第一行也不是三部分內容直接返回錯誤頁
outPutFile(ERR_FILE, socket.getOutputStream(), 500);
} else {
String path = arr[1]; //取出請求的資源路徑
if(path.equals("/")) //如果請求的內容沒有指定文件,則返回默認的頁面
path=DEFAULT_FILE;
if (Files.exists(Paths.get(HOME_DIR + path))) { //判斷文件是否存在 ,如果不存在,返回404頁面
outPutFile(HOME_DIR + path, socket.getOutputStream(), 200);
} else { //如果文件不存在,返回404頁面
outPutFile(NOT_FOUND_FILE, socket.getOutputStream(), 404);
}
}
} catch (Exception ex) {
ex.printStackTrace(); //輸出異常信息
} finally {
br.close();
sr.close();
is.close();
}
}
}
public static void outPutFile(String fileName, OutputStream os, int status) throws IOException {
System.out.println("response:");
System.out.println(fileName);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("HTTP/1.1 " + status + " OK\r\n"); //輸出狀態碼
stringBuilder.append("Date: " + (new Date()).toString() + "\r\n");
stringBuilder.append("Server: MyServer 0.0.1\r\n"); //代表服務器的軟件名稱
stringBuilder.append("X-Powered-By: Hawkon\r\n"); //這行可以換成你的英文名,看起來會有點diao
stringBuilder.append("Keep-Alive: timeout=5, max=100\r\n");
stringBuilder.append("Connection: Keep-Alive\r\n");
stringBuilder.append("Content-Type: text/html;charset=utf-8\r\n"); //字符串編碼
stringBuilder.append("\r\n");//多輸出一個空行,用來分割報頭和報體,HTTP協議要求
FileInputStream fis = new FileInputStream(fileName);
byte[] bytes = new byte[1024];
int len;
os.write(stringBuilder.toString().getBytes("UTF-8")); //輸出響應報頭
while ((len = fis.read(bytes)) != -1) { //輸出文件內容
os.write(bytes, 0, len);
}
os.flush();
os.close();
fis.close();
}
}
下圖是請求響應的報頭信息。
瀏覽器運行的情況