HttpServer的简单实现_Java
2016-12-07 09:10
120 查看
最近项目开发中需要向第三方服务发送Http请求并接收返回消息,本来考虑使用SoapUI工具来模拟,但由于交互的复杂性(服务端每次返回的数据不一样,且服务端需要在响应请求后的一段时间后要主动请求客户端提供的接口,请求内容与上一次响应有相)无法使用SoapUI来实现(我也不是非常会用,可能SoapUI可以实现)。
下面记录下核心的代码,以供后续参考。
HttpServer.java -- 程序入口:起动服务,接收客户端请求,根据URL分发请求到相应的servlet进行处理。
Servlet.java -- Servlet接口
ServletResponse.java -- 用于封装输出IO流,并提供响应接口
Log.java --用于打印日志消息
server.conf 配置文件
servlet.conf 配置文件 --配置了URL对应的处理类
下面记录下核心的代码,以供后续参考。
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.IndexServletHelloWordServlet.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() { } }
相关文章推荐
- 使用Java实现对dbf文件的简单读写
- 基于Java实现简单Http服务器之一
- 用java实现简单url负载均衡以及容错
- 在java中实现调用简单的c程序
- 由Java实现简单的文本编辑器
- http断点续传简单实现(java)
- 一个简单的冒泡排序和快速排序算法java实现
- 基于Java实现简单Http服务器之一
- JSP应用 java反射简单实现
- 用Java简单实现文件分割与合并
- 用java实现简单的email正则表达式判断
- 用java实现简单的多线程下载
- 一个简单的用JAVA实现的屏幕抓图(源代码)
- 用java实现简单的网络通信,相当于一个最简单的控制台qq(附代码) 推荐
- 使用异或进行简单的密码加密(JAVA实现)
- 今天的问题:一个简单的例子,请帮我解开“接口实现Java‘隐藏实现细目’”的迷惑。
- 用Java简单实现文件分割与合并
- 用Java实现的字符串简单加密
- http断点续传简单实现(java)
- Java程序国际化的简单实现