1 package my.tomcat2;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStreamReader;
6 import java.io.UnsupportedEncodingException;
7 import java.net.Socket;
8 import java.net.URLDecoder;
9 import java.util.ArrayList;
10 import java.util.HashMap;
11 import java.util.List;
12 import java.util.Map;
13
14 /**
15 * 用来接收客户端发来的头信息,并且解析头信息的第一句,也就是 method 是 Get 还是 POST, URL, param(参数)
16 */
17 public class Request {
18 private static final String CRLF = "\r\n";
19 //将参数存入 Map 中去,因为有可能会有要读取 CheckBox 复选框的参数值,他们属于同一个 name,所以要将他们存入到一个 List 中去
20 private Map<String, List<String>> paramMap;
21 //读取客户端的 头信息
22 private BufferedReader bw;
23 //将读取到的头信息append到一个StringBuilder中
24 private StringBuilder requestInfo;
25 //URL
26 private String url;
27 //Get 或者 POST
28 private String method;
29 //参数
30 private String param = "";
31
32 //初始化 字段
33 public Request() {
34 paramMap = new HashMap<>();
35 }
36
37 public Request(Socket client) {
38 try {
39 paramMap = new HashMap<>();
40 bw = new BufferedReader(new InputStreamReader(client.getInputStream()));
41 requestInfo = new StringBuilder();
42 String msg;
43 //这里有两个问题,线程是会循环的,所以会读到什么还请自己动手 BUG 一番,第一次循环最后会读到“”,第二次会首先读到 null
44 String hi = bw.readLine();
45 while (hi != null && !((msg = hi).equals(""))) {
46 hi = bw.readLine();
47 requestInfo.append(msg).append(CRLF);
48 }
49 } catch (IOException e) {
50 CloseUtil.closeSocket(client);
51 }
52 //将读到的 头信息 解析
53 if(!(requestInfo.toString().equals(""))) {
54 parseRequestInfo(requestInfo.toString());
55 }
56 }
57
58 //将所有 substring()获得的字符串调用 trim(),去掉空白字符,不然会出问题
59 public void parseRequestInfo(String info) {
60 String firstInfo = info.substring(0, info.indexOf(CRLF)).trim();
61 method = firstInfo.substring(0, firstInfo.indexOf("/")).trim();
62 String shortInfo = firstInfo.substring(firstInfo.indexOf("/"), firstInfo.indexOf("HTTP/")).trim();
63
64 if (method.equalsIgnoreCase("get")) {
65 if (shortInfo.contains("?")) {
66 String[] str = shortInfo.split("[?]");
67 this.url = str[0];
68 this.param = str[1];
69 } else {
70 this.url = shortInfo;
71 }
72 } else if (method.equalsIgnoreCase("post")) {
73 this.url = shortInfo;
74 this.param = info.substring(info.lastIndexOf(CRLF)).trim();
75 }
76
77 if (param.equals("")) {
78 return;
79 }
80 parseParam(param);
81 }
82
83 //解析 参数
84 public void parseParam(String param) {
85 String[] values = param.split("&");
86 String[][] pair = new String[values.length][2];
87
88 for (int i = 0; i < pair.length; i++) {
89 String[] str = values[i].split("=");
90 for (int j = 0; j < 2; j++) {
91 if (1 == str.length) {
92 pair[i][j] = str[j];
93 pair[i][j + 1] = null;
94 break;
95 } else {
96 pair[i][j] = str[j];
97 }
98 }
99 }
100
101 storeParam(pair);
102 }
103
104 //将解析完的参数,存入到 Map 中去
105 public void storeParam(String[][] pair) {
106 for (int i = 0; i < pair.length; i++) {
107 if (paramMap.containsKey(pair[i][0])) {
108 paramMap.get(pair[i][0]).add(decode(pair[i][1], "utf8"));
109 }else{
110 paramMap.put(pair[i][0], new ArrayList<>());
111 paramMap.get(pair[i][0]).add(decode(pair[i][1], "utf8"));
112 }
113 }
114 }
115
116 //获取多个参数,例如复选框之类的
117 public String[] getParams(String key){
118 if(paramMap.containsKey(key)){
119 return paramMap.get(key).toArray(new String[0]);
120 }else {
121 return null;
122 }
123 }
124
125 //这个是我用来在页面上显示复选框的多个属性值的,暂且搁浅
126 public String splitParams(String key){
127 String[] str = getParams(key);
128 StringBuilder sb = new StringBuilder();
129 for(String temp : str){
130 sb.append(temp);
131 }
132 return sb.toString();
133 }
134 //这里如果是没有get参数的话,是会返回null, getParams(key)[0] 也就是 null[0],当然会报错。应该是getParams(key),这个问题缠绕了我一些时间。。。
135 public String getParam(String key){
136 // return getParams(key)[0] == null ? "null" : getParams(key)[0];
137 return getParams(key) == null ? "null" : getParams(key)[0];
138 }
139
140 //解决中文参数,如果没有这个方法的话,你的参数值为中文的话,在页面上显示的是乱码
141 public String decode(String value, String code) {
142 try {
143 return URLDecoder.decode(value, code);
144 } catch (UnsupportedEncodingException e) {
145 e.printStackTrace();
146 }
147 return null;
148 }
149
150 //获取URL
151 public String getUrl(){
152 return this.url;
153 }
154 }