自定義服務器整個項目結構
- 自定義請求類MyHttpServletRequest,處理請求
package com.myserver;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
/**
* 自定義請求類,處理請求
* @author fang
*
*/
public class MyHttpServletRequest {
/**
* 請求的動作
*/
private String action;
/**
* 存放請求的參數
*/
private Map<String, String> paramMap = new HashMap<String, String>();
public MyHttpServletRequest() {
}
public MyHttpServletRequest(InputStream is) throws IOException {
// 創建一個用來接收的數據盒子
byte[] buf = new byte[1024];
// 接收並返回長度
int len = is.read(buf);
if (len == 0) {
return;
}
// 取得請求數據,進行解碼,防止中文亂碼
String data = new String(buf, 0, len);
data = URLDecoder.decode(data, "utf-8");
// 處理GET請求
if (data.startsWith("GET")) {
// 判斷是否帶參數
if (data.contains("?")) {
// 取得參數的字符串
String params = data.substring(data.indexOf("?") + 1, data.indexOf("HTTP/1.1") - 1);
// 取得帶參數的請求動作
this.action = data.substring(data.indexOf("/"), data.indexOf("?"));
// 解析取得請求動作,將取得請求的參數存放到HashMap中
if (params != null && !"".equals(params)) {
parseParams(params);
}
} else {
this.action = data.substring(data.indexOf("/"), data.indexOf("HTTP") - 1);
}
}
// 處理PSOT請求
if (data.startsWith("POST")) {
int start = data.indexOf("POST") + 6;
int end = data.indexOf("HTTP/1.1") - 1;
// 取得請求動作
this.action = data.substring(start, end);
// 最後一個換行符
int beginIndex = data.lastIndexOf("\n") + 1;
// 取得請求參數的字符串
String params = data.substring(beginIndex);
// 解析參數
if (params != null && !"".equals(params)) {
parseParams(params);
}
}
}
/**
* 解析參數,將取得請求的參數存放到HashMap中
*
* @param params 參數字符串
* @return 請求動作
*/
private void parseParams(String params) {
// 解析參數字符串
if (params.contains("&")) {
// 多個參數以&爲分割符
String[] temp = params.split("&");
if (temp != null) {
for (int i = 0; i < temp.length; i++) {
// key=value的形式
String[] t = temp[i].split("=");
// 存入集合
paramMap.put(t[0], t[1]);
}
}
} else {
String[] p = params.split("=");
// 存入集合
paramMap.put(p[0], p[1]);
}
}
/**
* 取得請求的動作
*
* @return action
*/
public String getAction() {
return action;
}
/**
* 取得屬性值
*
* @param key 鍵值
* @return 屬性值
*/
public String getAttributeValue(String key) {
if (paramMap.size() <= 0) {
return null;
}
return paramMap.get(key);
}
/**
* 設置屬性
*
* @param key 鍵值
* @param value 屬性值
*/
public void setAttribute(String key, String value) {
paramMap.put(key, value);
}
/**
* 移除屬性
*
* @param key 屬性對應的鍵值
*/
public void removeAttribute(String key) {
paramMap.remove(key);
}
}
- 自定義響應類MyHttpServletResponse,響應請求
package com.myserver;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
/**
* 自定義請求類,處理請求
* @author fang
*
*/
public class MyHttpServletRequest {
/**
* 請求的動作
*/
private String action;
/**
* 存放請求的參數
*/
private Map<String, String> paramMap = new HashMap<String, String>();
public MyHttpServletRequest() {
}
public MyHttpServletRequest(InputStream is) throws IOException {
// 創建一個用來接收的數據盒子
byte[] buf = new byte[1024];
// 接收並返回長度
int len = is.read(buf);
if (len == 0) {
return;
}
// 取得請求數據,進行解碼,防止中文亂碼
String data = new String(buf, 0, len);
data = URLDecoder.decode(data, "utf-8");
// 處理GET請求
if (data.startsWith("GET")) {
// 判斷是否帶參數
if (data.contains("?")) {
// 取得參數的字符串
String params = data.substring(data.indexOf("?") + 1, data.indexOf("HTTP/1.1") - 1);
// 取得帶參數的請求動作
this.action = data.substring(data.indexOf("/"), data.indexOf("?"));
// 解析取得請求動作,將取得請求的參數存放到HashMap中
if (params != null && !"".equals(params)) {
parseParams(params);
}
} else {
this.action = data.substring(data.indexOf("/"), data.indexOf("HTTP") - 1);
}
}
// 處理PSOT請求
if (data.startsWith("POST")) {
int start = data.indexOf("POST") + 6;
int end = data.indexOf("HTTP/1.1") - 1;
// 取得請求動作
this.action = data.substring(start, end);
// 最後一個換行符
int beginIndex = data.lastIndexOf("\n") + 1;
// 取得請求參數的字符串
String params = data.substring(beginIndex);
// 解析參數
if (params != null && !"".equals(params)) {
parseParams(params);
}
}
}
/**
* 解析參數,將取得請求的參數存放到HashMap中
*
* @param params 參數字符串
* @return 請求動作
*/
private void parseParams(String params) {
// 解析參數字符串
if (params.contains("&")) {
// 多個參數以&爲分割符
String[] temp = params.split("&");
if (temp != null) {
for (int i = 0; i < temp.length; i++) {
// key=value的形式
String[] t = temp[i].split("=");
// 存入集合
paramMap.put(t[0], t[1]);
}
}
} else {
String[] p = params.split("=");
// 存入集合
paramMap.put(p[0], p[1]);
}
}
/**
* 取得請求的動作
*
* @return action
*/
public String getAction() {
return action;
}
/**
* 取得屬性值
*
* @param key 鍵值
* @return 屬性值
*/
public String getAttributeValue(String key) {
if (paramMap.size() <= 0) {
return null;
}
return paramMap.get(key);
}
/**
* 設置屬性
*
* @param key 鍵值
* @param value 屬性值
*/
public void setAttribute(String key, String value) {
paramMap.put(key, value);
}
/**
* 移除屬性
*
* @param key 屬性對應的鍵值
*/
public void removeAttribute(String key) {
paramMap.remove(key);
}
}
- 定義處理請求線程類ProcessedThread
package com.myserver;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import com.servlet.LoginServlet;
/**
* 定義處理請求線程類
*
* @author fang
*
*/
public class ProcessedThread implements Runnable {
/**
* 客戶端套接字
*/
private Socket socket = null;
public ProcessedThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream is = null;
OutputStream os = null;
try {
is = socket.getInputStream();
if (is == null) {
throw new NullPointerException();
}
os = socket.getOutputStream();
if (os == null) {
throw new NullPointerException();
}
// 創建響應對象實例
MyHttpServletResponse response = new MyHttpServletResponse(os);
// 創建請求對象
MyHttpServletRequest request = new MyHttpServletRequest(is);
// 取得請求動作
String action = request.getAction();
String filePath = null;
if (action == null || "".equals(action)) {
response.forward("404.html");
return;
}
boolean result = isSuffix(action);
// 處理靜態業務類
if (result) {
filePath = "webContent" + request.getAction();
File file = new File(filePath);
if (!file.exists()) {
response.forward("404.html");
return;
}
response.write(new FileInputStream(filePath));
}
// 處理動態業務類
if (!result) {
if (action.endsWith("login.do")) {
LoginServlet loginServlet = new LoginServlet();
loginServlet.doService(request, response);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//靜態業務 允許請求的後綴
String[] suffixs = { ".html", ".js", ".css", ".jpg", ".ico" };
public boolean isSuffix(String action) {
boolean isAllow = false;
// 判斷是否有
for (String suffix : suffixs) {
if (action.endsWith(suffix)) {
isAllow = true;
break;
}
}
return isAllow;
}
}
- 實現自定義服務器類MyServer
package com.myserver;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 實現自定義服務器
* @author fang
*
*/
public class MyServer {
/**
* 服務端套接字
*/
private ServerSocket serverSocket=null;
/**
* 客戶端套接字
*/
private Socket socket=null;
/**
* 初始化服務器
* @param port 端口號 默認80
* @throws IOException
*/
public MyServer(int port) throws IOException {
//開啓服務端
serverSocket=new ServerSocket(port);
System.out.println("服務器開啓成功");
while(true) {
//等待客戶端連接
socket=serverSocket.accept();
//創建處理請求的線程
ProcessedThread processedThread=new ProcessedThread(socket);
//使用定長線程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
//開始執行
fixedThreadPool.execute(processedThread);
}
}
public Socket getSocket() {
return socket;
}
public static void main(String[] args) throws IOException {
new MyServer(80);
}
}
- 測試登錄類
package com.servlet;
import java.io.FileNotFoundException;
import java.io.IOException;
import com.myserver.MyHttpServletRequest;
import com.myserver.MyHttpServletResponse;
/**
* 測試登錄
* @author fang
*
*/
public class LoginServlet {
public void doService(MyHttpServletRequest request,MyHttpServletResponse response) throws FileNotFoundException, IOException{
//取得帳號和密碼
String userName=request.getAttributeValue("userName");
String password=request.getAttributeValue("password");
if ("fangzi".equals(userName) && "666".equals(password)) {
response.forward("/main.html");
}else {
response.forward("/failed.html");
}
}
}
前端頁面
首頁index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>歡迎界面</title>
</head>
<body>
<h1>歡迎使用自定義服務器</h1>
</body>
</html>
登錄界面login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄</title>
</head>
<body>
<h1>登錄界面</h1>
<form action="login.do" method="post">
<p>
賬號:<input name="userName" />
</p>
<p>
密碼:<input name="password" />
</p>
<p>
<button>登錄</button>
</p>
</form>
</body>
</html>
登錄成功main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首頁</title>
</head>
<body>
登錄成功
</body>
</html>
登錄失敗failed.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄失敗</title>
</head>
<body>
<h1>賬號或密碼錯誤</h1>
<hr>
<p>
<a href="login.html">返回</a>
</p>
</body>
</html>
圖標文件favicon.ico
注意:圖標這個文件一定要有,可以新建一個文件後綴名設置爲.ico