思考
在解析請求之前我們要思考一個問題,我們解析的是其中的哪些內(nèi)容?
對于最基本的實現(xiàn),當(dāng)然是請求類型,請求的url以及請求參數(shù),我們可以根據(jù)請求的類型作出對應(yīng)的處理,通過url在我們的mapstore中找到servlet,那么請求的參數(shù)我們是不是還沒有儲存的地方呢?
所以我們要先定義一個類來存儲參數(shù)
HttpServletRequest
當(dāng)然你也可以通過接口的形式來規(guī)范方法,我在這里進行的是最基本的仿寫,就不做復(fù)雜的設(shè)計了,下面這個類是存儲請求信息的類,我們在后續(xù)還會進行擴展,因我們還要實現(xiàn)cookie、session等功能
package com.tomcatServer.domain;
import java.util.HashMap;
import java.util.Map;
/**
* http servlet請求
*
* @author ez4sterben
* @date 2023/08/15
*/
public class HttpServletRequest {
private final Map<String,String> params = new HashMap<>();
private String requestBody;
public String getRequestBody() {
return requestBody;
}
public void setRequestBody(String requestBody) {
this.requestBody = requestBody;
}
public Map<String, String> getParams() {
return params;
}
public String getParam(String paramName){
return params.get(paramName);
}
}
http請求解析,HttpServletRequest
我們再給服務(wù)器發(fā)一個帶參數(shù)的請求看看http信息是什么樣子的
http://localhost:8080/test?aaa=aaa
這個信息的第一行就是請求的類型、url和參數(shù),那么我們直接對這里進行解析就行了
// 解析request param
String url = requestData.split(" ")[1];
String[] urlContent = url.split("\\?");
// ?前的是請求地址
String requestPath = urlContent[0];
// 問號后的是參數(shù)
String params = urlContent[1];
// 參數(shù)按照=分割
String[] paramsKeyValue = params.split("=");
存入map
// 設(shè)置請求參數(shù)
HttpServletRequest request = new HttpServletRequest();
Map<String, String> paramsMap = request.getParams();
for (int i = 0; i < paramsKeyValue.length; i += 2) {
paramsMap.put(paramsKeyValue[i],paramsKeyValue[i+1]);
}
響應(yīng)類HttpServletResponse
這個類中要注意的是我們要給返回的信息拼上一個頭部信息代表著成功編號和信息類型
package com.tomcatServer.domain;
import java.io.PrintWriter;
/**
* http servlet響應(yīng)
*
* @author ez4sterben
* @date 2023/08/15
*/
public class HttpServletResponse {
private final PrintWriter out;
private static final String response;
public HttpServletResponse(PrintWriter out) {
this.out = out;
}
static {
response = "HTTP/1.1 200 OK\r\n" +
"Content-Type: text/plain\r\n" +
"\r\n";
}
/**
* 寫
*
* @param content 內(nèi)容
*/
public void write(String content) {
out.println(response + content);
}
}
代理
既然實現(xiàn)到這里了,自然會想到,執(zhí)行誰的響應(yīng)呢?
沒錯,當(dāng)然是servlet中的,那就需要我們使用代理來調(diào)用其中的方法了
package com.tomcatServer.utils;
import com.tomcatServer.annotation.WebServlet;
import com.tomcatServer.domain.HttpServletRequest;
import com.tomcatServer.domain.HttpServletResponse;
import com.tomcatServer.servlet.MapStore;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* servlet工具類
*
* @author tomcatProject.ez4sterben
* @date 2023/08/15
*/
public class ServletUtil {
/**
* 是web servlet
*
* @param className 類名
* @return {@link Boolean}
*/
public static Boolean isWebServlet(String className){
try {
Class<?> aClass = Class.forName(className);
WebServlet annotation = aClass.getAnnotation(WebServlet.class);
if (annotation == null){
return Boolean.FALSE;
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return Boolean.TRUE;
}
/**
* 初始化servlet
*
* @param className 類名
*/
public static void initServlet(String className){
try {
Class<?> aClass = Class.forName(className);
String url = aClass.getAnnotation(WebServlet.class).value();
if (url.startsWith("/")) {
MapStore.servletMap.put(url,aClass);
}else {
MapStore.servletMap.put("/" + url,aClass);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
/**
* 調(diào)用get方法
*
* @param url url
* @param request
*/
public static void invokeGet(String url, HttpServletRequest request, HttpServletResponse response){
Class<?> aClass = MapStore.servletMap.get(url);
try {
Method doGet = aClass.getDeclaredMethod("doGet", HttpServletRequest.class, HttpServletResponse.class);
Object instance = aClass.newInstance();
doGet.invoke(instance, request, response);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* 調(diào)用后
*
* @param url url
* @param request 請求
* @param response 響應(yīng)
*/
public static void invokePost(String url, HttpServletRequest request, HttpServletResponse response){
Class<?> aClass = MapStore.servletMap.get(url);
try {
Method doPost = aClass.getDeclaredMethod("doPost", HttpServletRequest.class, HttpServletResponse.class);
Object instance = aClass.newInstance();
doPost.invoke(instance, request, response);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
HttpServlet規(guī)范
接下來定義一個抽象類來規(guī)范servlet類
package com.tomcatServer.domain;
import java.io.IOException;
/**
* http servlet
*
* @author ez4sterben
* @date 2023/08/15
*/
public abstract class HttpServlet {
/**
* 做得到
*
* @param request 請求
* @param response 響應(yīng)
* @throws IOException ioexception
*/
public abstract void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException;
/**
* 做帖子
*
* @param request 請求
* @param response 響應(yīng)
* @throws IOException ioexception
*/
public abstract void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException;
}
然后在項目中創(chuàng)建一個測試的servlet類
package tomcatProject.com.ez4sterben.servlet;
import com.tomcatServer.annotation.WebServlet;
import com.tomcatServer.domain.HttpServlet;
import com.tomcatServer.domain.HttpServletRequest;
import com.tomcatServer.domain.HttpServletResponse;
/**
* 登錄servlet
*
* @author tomcatProject.ez4sterben
* @date 2023/08/15
*/
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
response.write(request.getParam("aaa"));
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
}
}
請求測試
package com.tomcatServer.socket;
import com.tomcatServer.domain.HttpServletRequest;
import com.tomcatServer.domain.HttpServletResponse;
import com.tomcatServer.utils.ScanUtil;
import com.tomcatServer.utils.ServletUtil;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
/**
* 套接字存儲
*
* @author ez4sterben
* @date 2023/08/15
*/
public class SocketStore {
private static ServerSocket socket;
public static void connect(Integer port) throws IOException {
socket = new ServerSocket(port);
}
public static void close() throws IOException {
socket.close();
}
public static ServerSocket getSocket() {
return socket;
}
/**
* 處理請求
*
* @throws IOException ioexception
*/
public static void handleRequest(Socket accept) throws IOException {
// 獲取輸入輸出流
BufferedReader in = new BufferedReader(new InputStreamReader(accept.getInputStream()));
PrintWriter out = new PrintWriter(accept.getOutputStream(), true);
// 定義字符串接收Http協(xié)議內(nèi)容
String inputLine;
StringBuilder requestData = new StringBuilder();
// 讀取數(shù)據(jù)
while ((inputLine = in.readLine()) != null && !inputLine.isEmpty()) {
requestData.append(inputLine).append("\r\n");
}
System.out.println(requestData);
if (!requestData.toString().trim().equals("")){
handleGetAndPostReuqest(in, out, String.valueOf(requestData));
}
// 關(guān)閉資源
accept.close();
}
/**
* 處理post請求
*
* @param in 在
* @param requestData 請求數(shù)據(jù)
* @throws IOException ioexception
*/
private static void handleGetAndPostReuqest(BufferedReader in,PrintWriter out, String requestData) throws IOException {
// 解析request param
String url = requestData.split(" ")[1];
String[] urlContent = url.split("\\?");
String requestPath = urlContent[0];
String params = urlContent[1];
String[] paramsKeyValue = params.split("=");
// 設(shè)置請求參數(shù)
HttpServletRequest request = new HttpServletRequest();
Map<String, String> paramsMap = request.getParams();
for (int i = 0; i < paramsKeyValue.length; i += 2) {
paramsMap.put(paramsKeyValue[i],paramsKeyValue[i+1]);
}
if (requestData.contains("GET")){
// 設(shè)置響應(yīng)內(nèi)容
HttpServletResponse response = new HttpServletResponse(out);
ServletUtil.invokeGet(requestPath,request,response);
}
}
}
訪問http://localhost:8080/test?aaa=123
因為servlet中的操作是返回參數(shù),所以結(jié)果應(yīng)該為123
response.write(request.getParam("aaa"));
下一篇將會實現(xiàn)對html頁面的解析文章來源:http://www.zghlxwxcb.cn/news/detail-654846.html
【仿寫tomcat】五、響應(yīng)靜態(tài)資源(訪問html頁面)、路由支持以及多線程改進文章來源地址http://www.zghlxwxcb.cn/news/detail-654846.html
到了這里,關(guān)于【仿寫tomcat】四、解析http請求信息,響應(yīng)給前端,HttpServletRequest、HttpServletResponse的簡單實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!