您的位置:首页 > 理论基础 > 计算机网络

HttpServer的简单实现_Java

2016-12-07 09:10 120 查看
最近项目开发中需要向第三方服务发送Http请求并接收返回消息,本来考虑使用SoapUI工具来模拟,但由于交互的复杂性(服务端每次返回的数据不一样,且服务端需要在响应请求后的一段时间后要主动请求客户端提供的接口,请求内容与上一次响应有相)无法使用SoapUI来实现(我也不是非常会用,可能SoapUI可以实现)。

下面记录下核心的代码,以供后续参考。

HttpServer.java -- 程序入口:起动服务,接收客户端请求,根据URL分发请求到相应的servlet进行处理。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import com.mocker.httpserver.servlet.Error404Servlet;
import com.mocker.httpserver.servlet.Error500Servlet;

public class HttpServer {
private static Properties conf;
private static ServerSocket serverSocket = null;
private static Map<String, String> servletMap = new HashMap<String, String>();

public static void main(String[] args) throws Exception {
// 初始化
init();

// 创建并起动服务端Socket
int port = Integer.parseInt(conf.getProperty("server_port"));
serverSocket = new ServerSocket(port);
System.out.println("HTTPServer startup OK on [" + port + "]\n");

// 开始接收客户端请求
startAccept();
}

/**
* 初始化
*/
private static void init() {
conf = new Properties();
try {
conf.load(new FileInputStream(new File("D:/server.conf")));

String servletPath = conf.getProperty("servlet_conf_path");
BufferedReader servletRead = new BufferedReader(new FileReader(servletPath));
String line = null;
String[] servlet;
while ((line = servletRead.readLine()) != null) {
servlet = line.split("=", 2);
servletMap.put(servlet[0].trim(), servlet[1].trim());
}
servletRead.close();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 接收客户端请求
*
* @throws IOException
*/
private static void startAccept() throws IOException {
while (true) {
Socket client = serverSocket.accept();
new Thread(new Processor(client)).start();
}
}

/**
* 处理器,用于处理客户端请求
*
* @author Brook
*
*/
private static class Processor implements Runnable {
private Socket client = null;

public Processor(Socket client) {
this.client = client;
}

@Override
public void run() {
try {
Log.log("Receive message from " + client.getInetAddress().getHostAddress());
ServletRequest request = new ServletRequest(client.getInputStream());

c647
ServletResponse response = new ServletResponse(client.getOutputStream());

Log.log("<----<----<----[Receive]<----<----<----\n" + request.getRequest());

String classPath = servletMap.get(request.getUrl());
Servlet servlet = null;
if (classPath != null) {
try {
servlet = (Servlet) HttpServer.class.getClassLoader().loadClass(classPath).newInstance();
} catch (Exception e) {
Log.log("Encounter an exception: " + e);
servlet = new Error500Servlet();
}
} else {
Log.log("Not found the path: " + request.getUrl());
servlet = new Error404Servlet();
}

servlet.init();
servlet.process(request, response);
servlet.destroy();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (client != null) {
try {
client.close();
} catch (IOException e) {
}
}
}
}
}

public static String getConf(String key) {
return conf.getProperty(key);
}

}


Servlet.java -- Servlet接口

public interface Servlet {
/**
* 初始化
*/
public void init();

/**
* 处理
*
* @param req
* @param res
* @throws Exception
*/
public void process(ServletRequest req, ServletResponse res) throws Exception;

/**
* 注销
*/
public void destroy();
}
ServletRequest.java -- 用于封装输入IO流,并解析客户端请求
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class ServletRequest {
private String request;
private InputStream socketIn;

private String type; // GET or POST
private String url;
private Map<String, String> params;
private String body;
private Map<String, String> heads = new HashMap<String, String>();

public ServletRequest(InputStream socketIn) throws IOException {
this.socketIn = socketIn;
this.request = _getRequest();
this.parse();
}

/**
* 接收请求消息
*
* @return
* @throws IOException
*/
private String _getRequest() throws IOException {
// 这里只获取了1024个字节,实际请求可能超出,需要使用while循环获取
 byte[] requestBuff = new byte[1024];
int len = socketIn.read(requestBuff);
return new String(requestBuff, 0, len);
}

/**
* 解析请求消息
*/
private void parse() {
String[] requestArray = request.split("\\r\\n\\r\\n", 2);
if (requestArray.length == 2) {
body = requestArray[1];
}
String[] headLines = requestArray[0].split("\\r\\n");
for (String headLine : headLines) {
if (headLine.indexOf(":") != -1) {
String[] headArray = headLine.split(": ", 2);
heads.put(headArray[0], headArray[1]);
}
}

String firstLine = request.substring(0, request.indexOf("\r\n"));
String[] parts = firstLine.split(" ");

type = parts[0];
String[] urlArray = parts[1].split("\\?");
url = urlArray[0];
if (urlArray.length == 2 && urlArray[1].length() > 1) {
String[] paramGroupArray = urlArray[1].split("&");
for (String paramGroup : paramGroupArray) {
String[] paramArray = paramGroup.split("=");
params.put(paramArray[0], paramArray.length == 2 ? paramArray[1] : "");
}
}
}

// ... get(), set()

}


ServletResponse.java -- 用于封装输出IO流,并提供响应接口

import java.io.IOException;
import java.io.OutputStream;

public class ServletResponse {
private OutputStream outputStream;

public ServletResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}

public String buildHeader(String statusCode, String contentType) {
StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 " + statusCode + " OK\r\n");
sb.append("Content-Type:" + contentType + "\r\n");
sb.append("\r\n");

return sb.toString();
}

public void write(String res) throws IOException {
Log.log("---->---->---->[Response]---->---->---->\n" + res);
outputStream.write(res.getBytes());
}

}


Log.java --用于打印日志消息

class Log {

private static Boolean print = null;;

static void log(String message) {
if (print == null) {
print = Boolean.valueOf(HttpServer.getConf("console_print"));
}

if (print) {
System.out.println(message);
}
}
}


server.conf 配置文件

# 服务器端口
server_port=8181

# 是否打印数据到控制台
console_print=true

servlet_conf_path = ./servlet.conf


servlet.conf 配置文件 --配置了URL对应的处理类

/helloWord = com.mocker.httpserver.servlet.HelloWordServlet
/index = com.mocker.httpserver.servlet.IndexServlet
HelloWordServlet.java --示例Servlet

import com.mocker.httpserver.Servlet;
import com.mocker.httpserver.ServletRequest;
import com.mocker.httpserver.ServletResponse;

public class HelloWordServlet implements Servlet {

@Override
public void init() {

}

@Override
public void process(ServletRequest req, ServletResponse res) throws Exception {
String header = res.buildHeader("200", "text/html");
res.write(header + "<html><body><p>HelloWord</p></body></html>");
}

@Override
public void destroy() {
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HttpServer servlet Java