基于 httpserver 类实现的简易 http 服务器
一、前言
利用 Java 的 com.sun.net
包下的 http 类,实现的简易 http 服务器。全部代码已上传至 GitHub,链接在文末。
主要功能为:
1、只处理 GET 方式和 POST 方式的请求,其他的返回 501 Not Implemented
2、GET:1)如果请求路径为一个存在的 HTML 文件,返回 200 OK
和该 HTML 文件的全部内容。(对子目录下的文件同样也要能返回);2)如果请求路径为一个文件夹,且该文件夹内有 index.html 文件,返回 200 OK
和 index.html 文件的全部内容;3)如果请求的文件不存在,或者请求的路径下无 index.html 文件,返回 404 Not Found
。
3、POST:1)构造一个 HTTP 请求,包含两个键值对:Name:姓名 和 ID:学号,提交给 /Post_show
。服务器收到请求后返回 200 OK
且输出以 POST 方式发送的 Name 和 ID;2)其他情况如请求路径不为 Post_show
或键的名称不为 Name 和 ID,返回 404 Not Found
4、使用多线程处理,具体为线程池方式实现
5、支持长选项参数:1)–ip 设置服务器端的 IP 地址;2)–port 设置服务器端监听的端口号;3)–number-thread 线程数目。
二、功能展示
这里只贴 windows 环境下测试的结果了。
1、Idea 上运行
Run->Edit Configurations 设置参数
也可以不设置,默认值就是上图中的数
点击运行
这个“当前路径”设置的是:
private static final String WEB_ROOT = System.getProperty("user.dir")
+ File.separator + "webroot";
后文有解释。在 webroot 文件夹内存放了一些子文件夹和 HTML 文件等。
1.1、浏览器输入请求
浏览器中输入
127.0.0.1:8888/sub/02.jpg
便可请求到图片 D:\Study\Java\httpserver\webroot\sub\02.jpg
1.2、curl 命令请求
curl 现在是 win10 自带的了吧,不用安装直接能用。不过需要注意的是 windows 和 Linux 下的 curl 使用存在区别。
1.3、Postman 请求
Postman 是个很棒的工具!
2、命令行上 Java -jar 运行
参考 IDEA 打包 jar 包详尽流程打成 jar 包,放在 E 盘
此时将 webroot 和 httpserver.jar 放在同一目录下
请求方式和 1 中介绍过的类似
比较简单,看函数名称就知道在做啥。测试如下:
预览:
3.3、满足条件
private static void HandlePostRequest(HttpExchange httpExchange, String Name, String ID) throws Exception {
Headers responseHeaders = httpExchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
OutputStream responseBody = httpExchange.getResponseBody();
OutputStreamWriter writer = new OutputStreamWriter(responseBody, "UTF-8");
String response = "<html><title>" + httpExchange.getRequestMethod() + "</title><body bgcolor=ffffff>" + CRLF +
"Your Name: " + Name + CRLF +
"ID: " + ID + CRLF +
"<hr><em>HTTP Web Server</em>" + CRLF +
"</body></html>";
httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.getBytes("UTF-8").length);
writer.write(response);
writer.close();
responseBody.close();
}
和 3.2 差不多,就是返回内容有所更改
预览:
4、处理 Get 请求
4.1、判断何种方式请求
static class MyHandler implements HttpHandler {
@Override
public void handle(HttpExchange httpExchange) throws IOException {
String requestMethord = httpExchange.getRequestMethod();
try {
if (is404NotFound(httpExchange)) {
System.out.println(httpExchange.getRequestURI() + " does not exist!");
return;
}
} catch (Exception e) {
e.printStackTrace();
}
if (requestMethord.equalsIgnoreCase("GET")) {
HandleGetRequest(httpExchange);
} else if (requestMethord.equalsIgnoreCase("POST")) {
//
} else {
Headers responseHeaders = httpExchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/html;charset=utf-8");
OutputStream responseBody = httpExchange.getResponseBody();
OutputStreamWriter writer = new OutputStreamWriter(responseBody, "UTF-8");
String response = "<html><title>501 Not Implemented</title><body bgcolor=ffffff>" + CRLF +
"Not Implemented" + CRLF +
"<p>Does not implement this methord: " + requestMethord + CRLF +
"<hr><em>HTTP Web Server</em>" + CRLF +
"</body></html>";
httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_NOT_IMPLEMENTED, response.getBytes("UTF-8").length);
writer.write(response);
writer.close();
responseBody.close();
}
}
}
利用 getRequestMethod()函数得到是何种方式的请求。判断访问路径是否存在见 4.2。
如果访问路径存在,并且访问方式为 GET
,则调用函数 HandleGetRequest,见 4.3;若访问方式为 POST
,也可以调用相应的函数,但我在之前已经实现过了,这里就不填了;若访问方式为除了 GET
和 POST
以外的方式,则返回 501 Not IMPLEMENTED:
预览:
4.2、判断访问路径是否存在
private static boolean is404NotFound(HttpExchange httpExchange) throws Exception {
String requestURI = String.valueOf(httpExchange.getRequestURI());
File file = new File(WEB_ROOT, requestURI);
if (file.exists()) return false;
else {
System.out.println(file.getPath() + "does not exist!" + CRLF);
NotFoundResponse(httpExchange);
return true;
}
}
前文提到,WEB_ROOT 为获取的当前程序正在运行的路径,加上 requestURI 得到请求的文件,利用 exists()函数判断是否存在。若存在则返回 false,表示不是 404;若不存在则调用 3.2 中提过的函数 NotFoundResponse()。
将文件以字节流的形式发送出去。这里的缓冲区大小为 10240。
例: