用Java创建简单Web服务器 (1) - HTTP服务器
使用Java SDK创建一个简单的Http服务器并处理GET/POST请求
引言
本技巧介绍了一个简单的HTTP服务器类,您可以将其合并到您自己的项目中,它可以在本地工作或处理有限的并发请求。
背景
Http服务器绑定到一个IP地址和端口号,并监听传入的请求,然后向客户端返回响应。 简单的http服务器可以灵活地添加到复杂项目中,用于渲染HTML元素或充当后端服务器,甚至可以部署在客户端以驱动特定设备。 如果您正在寻找一个解决方案来创建一个简单的HTTP服务器,该服务器可以轻松嵌入到您的项目中并处理有限的Web请求,那么本技巧可以满足您的需求。
这是Http服务器实现的结构
Using the Code
自Java 1.6起,J2EE SDK中包含了一个内置的HTTP服务器。 可以在以下位置下载
可以使用四个步骤将一个简单的HTTP服务器添加到Java程序中
- 构造一个HTTP服务器对象
- 将一个或多个HTTP处理程序对象附加到HTTP服务器对象
- 实现HTTP处理程序以处理
GET
/POST
请求并生成响应 - 启动HTTP服务器
1. 创建一个http服务器
HttpServer
类提供了一个简单的高级Http服务器API,可用于构建嵌入式HTTP服务器。
int port = 9000;
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
System.out.println("server started at " + port);
server.createContext("/", new RootHandler());
server.createContext("/echoHeader", new EchoHeaderHandler());
server.createContext("/echoGet", new EchoGetHandler());
server.createContext("/echoPost", new EchoPostHandler());
server.setExecutor(null);
server.start();
2. 创建http处理程序
Http处理程序与http服务器关联以处理请求。 每个HttpHandler
都注册一个上下文路径,该路径表示此服务器上的服务位置。 对已定义的URI路径的请求将映射到正确的http处理程序。 找不到处理程序的任何请求都将使用404响应拒绝。
创建根处理程序以显示服务器状态
public class RootHandler implements HttpHandler {
@Override
public void handle(HttpExchange he) throws IOException {
String response = "<h1>Server start success
if you see this message</h1>" + "<h1>Port: " + port + "</h1>";
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
声明echoHeader
处理程序以显示请求标头信息
public class EchoHeaderHandler implements HttpHandler {
@Override
public void handle(HttpExchange he) throws IOException {
Headers headers = he.getRequestHeaders();
Set<Map.Entry<String, List<String>>> entries = headers.entrySet();
String response = "";
for (Map.Entry<String, List<String>> entry : entries)
response += entry.toString() + "\n";
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.toString().getBytes());
os.close();
}}
3. 处理Get和Post请求
客户端和服务器之间通过HTTP协议进行请求-响应有两种常用方法
GET
- 从指定资源请求数据POST
- 提交要处理的数据到已识别的资源
在这里,您创建两个处理程序分别处理GET
/POST
方法。
声明echoGet
处理程序以处理Get
请求
public class EchoGetHandler implements HttpHandler {
@Override
public void handle(HttpExchange he) throws IOException {
// parse request
Map<String, Object> parameters = new HashMap<String, Object>();
URI requestedUri = he.getRequestURI();
String query = requestedUri.getRawQuery();
parseQuery(query, parameters);
// send response
String response = "";
for (String key : parameters.keySet())
response += key + " = " + parameters.get(key) + "\n";
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.toString().getBytes());
s.close();
}
}
声明echoPost
处理程序以处理Post
请求
public class EchoPostHandler implements HttpHandler {
@Override
public void handle(HttpExchange he) throws IOException {
// parse request
Map<String, Object> parameters = new HashMap<String, Object>();
InputStreamReader isr = new InputStreamReader(he.getRequestBody(), "utf-8");
BufferedReader br = new BufferedReader(isr);
String query = br.readLine();
parseQuery(query, parameters);
// send response
String response = "";
for (String key : parameters.keySet())
response += key + " = " + parameters.get(key) + "\n";
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.toString().getBytes());
os.close();
}
}
在这里,您声明一个static parseQuery()
方法来解析请求参数
public static void parseQuery(String query, Map<String,
Object> parameters) throws UnsupportedEncodingException {
if (query != null) {
String pairs[] = query.split("[&]");
for (String pair : pairs) {
String param[] = pair.split("[=]");
String key = null;
String value = null;
if (param.length > 0) {
key = URLDecoder.decode(param[0],
System.getProperty("file.encoding"));
}
if (param.length > 1) {
value = URLDecoder.decode(param[1],
System.getProperty("file.encoding"));
}
if (parameters.containsKey(key)) {
Object obj = parameters.get(key);
if (obj instanceof List<?>) {
List<String> values = (List<String>) obj;
values.add(value);
} else if (obj instanceof String) {
List<String> values = new ArrayList<String>();
values.add((String) obj);
values.add(value);
parameters.put(key, values);
}
} else {
parameters.put(key, value);
}
}
}
}
4. 测试http服务器
/ 显示服务器状态,由RootHandler
处理
/echoHeader
显示标头信息,由EchoHeaderHandler
处理。
/echoGet
由EchoGetHandler
处理
/echoPost
由EchoPostHandler
处理。
历史
- 2015年10月15日:发布初始版本
- 2015年10月19日:添加服务器测试
- 2015年10月23日:更新源代码