BinCat V2-简单解析请求参数

V2版本我们需要支持请求参数解析以及简单的HTML页面渲染功能。

BinCatServerV2实现代码:

  1. package com.anbai.sec.server;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. import java.net.URLDecoder;
  6. import java.util.Map;
  7. import java.util.concurrent.ConcurrentHashMap;
  8. import java.util.logging.Logger;
  9. /**
  10. * ServerSocket Http 服务器示例
  11. */
  12. public class BinCatServerV2 {
  13. private static final Logger LOG = Logger.getLogger("info");
  14. public static void main(String[] args) {
  15. try {
  16. // 设置服务监听端口
  17. int port = 8080;
  18. // 设置服务名称
  19. String serverName = "BinCat-0.0.2";
  20. // 创建ServerSocket,监听本地端口
  21. ServerSocket ss = new ServerSocket(port);
  22. LOG.info(serverName + " 启动成功,监听端口: " + port);
  23. while (true) {
  24. // 等待客户端连接
  25. Socket socket = ss.accept();
  26. try {
  27. // 获取Socket输入流对象
  28. InputStream in = socket.getInputStream();
  29. // 获取Socket输出流对象
  30. OutputStream out = socket.getOutputStream();
  31. // 创建数据输出流对象
  32. DataInputStream dis = new DataInputStream(in);
  33. // 从Socket中读取一行数据,读取请求的URL
  34. String str = dis.readLine();
  35. if (str == null) {
  36. socket.close();
  37. continue;
  38. }
  39. // 切割请求Http协议信息
  40. String[] strs = str.split("\\s+");
  41. // 解析Http请求方法类型
  42. String method = strs[0];
  43. // 解析Http请求URL地址
  44. String url = strs[1];
  45. // 初始化Http请求URL地址
  46. String requestURL = url;
  47. // 初始化Http请求的QueryString
  48. String queryString;
  49. // 解析Http请求版本信息
  50. String httpVersion = strs[2];
  51. // 创建Header对象
  52. Map<String, String> header = new ConcurrentHashMap<String, String>();
  53. // 初始化请求参数数组
  54. Map<String, String> parameterMap = new ConcurrentHashMap<String, String>();
  55. // 解析GET请求参数
  56. if (url.contains("?")) {
  57. String[] parameterStrs = url.split("\\?");
  58. requestURL = parameterStrs[0];
  59. queryString = parameterStrs[1];
  60. // 按"&"切割GET请求的参数
  61. String[] parameters = queryString.split("&");
  62. // 解析GET请求参数
  63. for (String parameter : parameters) {
  64. String[] tmp = parameter.split("=", -1);
  65. if (tmp.length == 2) {
  66. parameterMap.put(tmp[0], URLDecoder.decode(tmp[1]));
  67. }
  68. }
  69. }
  70. // 解析请求头信息
  71. while (true) {
  72. // 按行读取Header头信息
  73. String line = dis.readLine();
  74. // 当读取到空行时停止解析Header
  75. if ("".equals(line)) {
  76. break;
  77. }
  78. // 切割Header的Key/Value
  79. String[] headers = line.split(":\\s*", -1);
  80. header.put(headers[0], headers[1]);
  81. }
  82. // 输出服务器返回信息
  83. StringBuffer msg = new StringBuffer();
  84. // 处理Http请求,当浏览器请求主页时返回服务器信息
  85. if ("/".equals(requestURL)) {
  86. out.write("HTTP/1.1 200 OK\n".getBytes());
  87. // 根据Http请求类型处理不同的请求
  88. if ("GET".equalsIgnoreCase(method)) {
  89. // 输出服务器处理结果
  90. msg.append("<html>\n" +
  91. "<head>\n" +
  92. " <title>Login Test</title>\n" +
  93. "</head>\n" +
  94. "<body>\n" +
  95. "<div style=\"margin: 30px;\">\n" +
  96. " <form action=\"/\" method=\"POST\">\n" +
  97. " Username:<input type=\"text\" name=\"username\" value=\"admin\"/><br/>\n" +
  98. " Password:<input type=\"text\" name=\"password\" value=\"'=0#\"/><br/>\n" +
  99. " <input type=\"submit\" value=\"Login\"/>\n" +
  100. " </form>\n" +
  101. "</div>\n" +
  102. "</body>\n" +
  103. "</html>");
  104. } else if ("POST".equalsIgnoreCase(method)) {
  105. String contentType = header.get("Content-Type");
  106. // 解析POST请求参数
  107. if ("application/x-www-form-urlencoded".equalsIgnoreCase(contentType)) {
  108. // 获取请求的主体长度
  109. int contentLength = Integer.parseInt(header.get("Content-Length"));
  110. // 创建一个和请求体一样大小的缓冲区
  111. byte[] bytes = new byte[contentLength];
  112. // 读取POST主体内容
  113. dis.read(bytes);
  114. // 解析POST请求内容
  115. String body = new String(bytes, "ISO8859-1");
  116. // 按"&"切割POST请求的参数
  117. String[] parameters = body.split("&");
  118. // 解析POST请求参数
  119. for (String parameter : parameters) {
  120. String[] tmp = parameter.split("=", -1);
  121. if (tmp.length == 2) {
  122. parameterMap.put(tmp[0], URLDecoder.decode(tmp[1]));
  123. }
  124. }
  125. // 定义SQL语句
  126. String sql = "select id,username,password from sys_user where username = '" +
  127. parameterMap.get("username") + "' and password = '" +
  128. parameterMap.get("password") + "'";
  129. msg.append("<font color='red'>JDBC 查询SQL:" + sql + "</font>\n");
  130. msg.append("<h3>请求头:</h3>\n");
  131. msg.append("<pre>\n");
  132. for (String key : header.keySet()) {
  133. msg.append(key + ": " + header.get(key) + "\n");
  134. }
  135. msg.append("<pre>\n");
  136. msg.append("<h3>请求参数:</h3>\n");
  137. // 循环遍历请求参数
  138. for (String key : parameterMap.keySet()) {
  139. msg.append(key + ": " + parameterMap.get(key) + "\n");
  140. }
  141. }
  142. }
  143. } else {
  144. out.write("HTTP/1.1 404 Not Found\n".getBytes());
  145. // 输出错误信息
  146. msg.append("404");
  147. }
  148. // 输出Web服务器信息
  149. out.write(("Server: " + serverName + "\n").getBytes());
  150. // 输出返回的消息类型
  151. out.write(("Content-Type: text/html; charset=UTF-8\n").getBytes());
  152. // 请求响应内容
  153. byte[] responseByte = msg.toString().getBytes();
  154. // 输出返回字节数
  155. out.write(("Content-Length: " + responseByte.length + "\n").getBytes());
  156. // 写入换行
  157. out.write("\n".getBytes());
  158. // 将读取到的数据写入到客户端Socket
  159. out.write(responseByte);
  160. in.close();
  161. out.close();
  162. } catch (IOException e) {
  163. LOG.info("处理客户端请求异常:" + e);
  164. } finally {
  165. socket.close();
  166. }
  167. }
  168. } catch (IOException e) {
  169. e.printStackTrace();
  170. }
  171. }
  172. }

请求参数解析测试

访问Web服务测试http://localhost:8080:

image-20200909214652771

提交登陆表单测试:

image-20200909214804184