一个java web客户端,适合从服务器到服务器的通信
在实际应用中,web应用一般是基于b/s,如果是基于c/s呢?比如从web服务器到另一个web服务器之间的通信,在b/s模式下,浏览器帮我们处理了通信细节,比如发送和接收请求,而从服务器到服务器通信,自己得构建一个客户端,当然,套接字是可行的选择,不过要写出满足http协议的套接字,需要做很多事情。利用jdk提供的HttpURLConnection,我们做一个简单的封装,就可以实现自己的HttpClient,而无需使用apache HttpClient那个庞然大物了。不废话上代码。其中要使用到的json包,在本人共享云盘中可以下载。java代码分享:http://pan.baidu.com/s/1hszGxV2
HttpClient.java
1 /** 2 * 3 */ 4 package com.jjh.common; 5 6 import java.io.ByteArrayInputStream; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.OutputStream; 10 import java.lang.reflect.ParameterizedType; 11 import java.lang.reflect.Type; 12 import java.net.HttpURLConnection; 13 import java.net.URL; 14 import java.nio.charset.Charset; 15 import java.nio.charset.StandardCharsets; 16 import java.util.Objects; 17 18 import javax.activation.MimeType; 19 import javax.activation.MimeTypeParseException; 20 import javax.xml.bind.JAXB; 21 22 import org.json.JSONArray; 23 import org.json.JSONException; 24 import org.json.JSONObject; 25 26 /** 27 * @author Administrator 28 * 29 */ 30 public abstract class HttpClient<S, R> { 31 /** 32 * @author Administrator 33 * 34 */ 35 public static enum Response { 36 SUCCESS(200, "OK"), PAGE_NOT_FOUND(404, "页面没找到"), ERROR(500, "服务器内部错误"); 37 38 private final int responseCode; 39 private final String responseMessage; 40 41 /** 42 * @param responseCode 43 * @param responseMessage 44 */ 45 private Response(int responseCode, String responseMessage) { 46 this.responseCode = responseCode; 47 this.responseMessage = responseMessage; 48 } 49 50 /** 51 * @return the responseCode 52 */ 53 public int getResponseCode() { 54 return responseCode; 55 } 56 57 /** 58 * @return the responseMessage 59 */ 60 public String getResponseMessage() { 61 return responseMessage; 62 } 63 64 public static Response getResponse(int responseCode) { 65 switch (responseCode) { 66 case 200: 67 return SUCCESS; 68 case 404: 69 return PAGE_NOT_FOUND; 70 case 500: 71 return ERROR; 72 } 73 return null; 74 } 75 76 } 77 78 private HttpURLConnection conn; 79 private MimeType mimeType; 80 private Class<S> SType; 81 private Class<R> RType; 82 83 /** 84 * @param mimeType 85 */ 86 @SuppressWarnings("unchecked") 87 public HttpClient(MimeType mimeType) { 88 super(); 89 this.mimeType = mimeType; 90 Type type=getClass().getGenericSuperclass(); 91 ParameterizedType pt = (ParameterizedType) type; 92 SType=(Class<S>)pt.getActualTypeArguments()[0]; 93 RType=(Class<R>)pt.getActualTypeArguments()[1]; 94 } 95 96 /** 97 * @throws MimeTypeParseException 98 * 99 */ 100 public HttpClient() throws MimeTypeParseException{ 101 // TODO Auto-generated constructor stub 102 this(new MimeType("application/x-www-form-urlencoded;charset=utf-8")); 103 } 104 105 protected S onReady() { 106 return null; 107 } 108 109 abstract protected void onComplete(R response); 110 111 protected void onError(Response response) { 112 System.err.println(response.getResponseCode() + "," + response.getResponseMessage()); 113 } 114 115 public Runnable get(String uri) throws IOException { 116 S data=onReady(); 117 // 先发送数据 118 if (Objects.nonNull(data)) { 119 if(SType!=String.class) 120 throw new IOException("'"+data+"'必须是字符串"); 121 int index=uri.lastIndexOf("?"); 122 //后面没有? 123 if(index==-1) 124 uri+="?"+data; 125 //后面有? 126 else if(index==uri.length()-1) 127 uri+=data; 128 //后面有查询字符串,类似于:?name=jjh 129 else 130 uri+="&"+data; 131 } 132 conn = (HttpURLConnection) new URL(uri).openConnection(); 133 conn.setUseCaches(false); 134 conn.setConnectTimeout(3000); 135 conn.setReadTimeout(3000); 136 conn.setRequestProperty("Content-Type", mimeType.toString()); 137 138 conn.setRequestMethod("GET"); 139 conn.setDoInput(true); 140 conn.setDoOutput(false); 141 conn.connect(); 142 143 // 可以处理连接失败的信息(忽略) 144 // 处理发送和接收 145 // 返回一个Runnable 146 return () -> { 147 try { 148 // 后处理响应 149 read(); 150 } catch (Exception e) { 151 e.printStackTrace(); 152 } 153 }; 154 } 155 156 public Runnable post(String uri) throws IOException { 157 conn = (HttpURLConnection) new URL(uri).openConnection(); 158 conn.setUseCaches(false); 159 conn.setConnectTimeout(3000); 160 conn.setReadTimeout(3000); 161 conn.setRequestProperty("Content-Type", mimeType.toString()); 162 163 conn.setRequestMethod("POST"); 164 conn.setDoInput(true); 165 conn.setDoOutput(true); 166 conn.connect(); 167 168 // 可以处理连接失败的信息(忽略) 169 // 处理发送和接收 170 // 返回一个Runnable 171 return () -> { 172 try { 173 // 先发送数据 174 write(); 175 // 后处理响应 176 read(); 177 } catch (Exception e) { 178 e.printStackTrace(); 179 } 180 }; 181 } 182 183 private void read() throws IOException, JSONException { 184 // TODO Auto-generated method stub 185 int responseCode = conn.getResponseCode(); 186 Response response = Response.getResponse(responseCode); 187 switch (response) { 188 case SUCCESS: 189 onComplete(success()); 190 break; 191 default: 192 onError(response); 193 } 194 } 195 196 @SuppressWarnings("unchecked") 197 private R success() throws IOException, JSONException { 198 // TODO Auto-generated method stub 199 InputStream in = conn.getInputStream(); 200 R result = null; 201 byte[] ret = Files.read(in); 202 in.close(); 203 if (RType == JSONObject.class) { 204 result = (R) new JSONObject(new String(ret, Charset.forName("UTF-8"))); 205 } else if (RType == JSONArray.class) { 206 result = (R) new JSONArray(new String(ret, Charset.forName("UTF-8"))); 207 } else if (RType == String.class) { 208 result = (R) new String(ret, Charset.forName("UTF-8")); 209 } else if (RType == byte[].class) { 210 result = (R)ret; 211 } else { 212 result = JAXB.unmarshal(new ByteArrayInputStream(ret), RType); 213 } 214 return result; 215 } 216 217 private void write() throws IOException { 218 // TODO Auto-generated method stub 219 S data = onReady(); 220 OutputStream out = conn.getOutputStream(); 221 if (SType == JSONObject.class || SType == JSONArray.class) { 222 out.write(data.toString().getBytes(StandardCharsets.UTF_8)); 223 } else if (SType == String.class) { 224 String s = (String) data; 225 out.write(s.getBytes(StandardCharsets.UTF_8)); 226 } else if (SType == byte[].class) { 227 byte[] s = (byte[]) data; 228 out.write(s); 229 } else { 230 JAXB.marshal(data, out); 231 } 232 out.flush(); 233 out.close(); 234 } 235 236 public static void main(String[] args) throws IOException, MimeTypeParseException { 237 Runnable r=new HttpClient<String, String>(){ 238 239 @Override 240 protected void onComplete(String response) { 241 // TODO Auto-generated method stub 242 System.out.println(response); 243 } 244 245 /* (non-Javadoc) 246 * @see com.jjh.common.HttpClient#onReady() 247 248 @Override 249 protected String onReady() { 250 // TODO Auto-generated method stub 251 return "username=张三&password=123456"; 252 }*/ 253 254 255 256 }.get("https://www.baidu.com/"); 257 r.run(); 258 } 259 260 }
main方法中是测试,代码注释很少,想了解的加我qq:412383550