初始化提交

1.请求支持postBody、post、get三种方式
2.支持网络速率、延迟、流量统计
This commit is contained in:
newpanjing
2017-03-14 15:32:26 +08:00
commit cd7e4c79c1
15 changed files with 1455 additions and 0 deletions
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
@@ -0,0 +1,5 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7
@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
+63
View File
@@ -0,0 +1,63 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wezoz.nat</groupId>
<artifactId>wezoz-nat-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>wezoz-nat-client</name>
<url>https://www.wezoz.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.compilerVersion>1.7</maven.compiler.compilerVersion>
</properties>
<dependencies>
<dependency>
<groupId>io.socket</groupId>
<artifactId>socket.io-client</artifactId>
<version>0.8.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,35 @@
package com.wezoz.nat;
public interface CallListener {
/**
* 状态改变
*
* @param info
*/
public void statusCall(String info);
/**
* 事件回调
*
* @param info
*/
public void eventCall(String info);
/**
* 流量统计
*
* @param traffic
*/
public void trafficCall(long traffic);
public void speedCall(long speed);
/**
* 关闭
*/
public void onClose();
public void ping(long ms);
}
@@ -0,0 +1,318 @@
package com.wezoz.nat;
import java.sql.Time;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.log4j.Logger;
import org.json.JSONException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wezoz.nat.form.MainForm;
import com.wezoz.nat.utils.HttpClientUtils;
import io.socket.client.IO;
import io.socket.client.IO.Options;
import io.socket.client.Socket;
public class LocalServer {
private static final String HTTP_REQUEST = "httpRequest";
private static final String HTTP_RESPONSE = "httpResponse";
private static final String BIND_DOMAIN = "bindDomain";
private static final String BIND_DOMAIN_NOTICE = "bindDomainNotice";
private static final String PING = "clientPing";
private static final String PING_NOTICE = "clientPingNotice";
private Logger logger = Logger.getLogger(getClass());
private Socket socket;
private String server;
private String forward;
private String domain;
private long traffic = 0;// 流量统计
private long speed = 0;// 实时网速统计
public void setDomain(String domain) {
this.domain = domain;
}
public void setForward(String forward) {
this.forward = forward;
}
public void setServer(String server) {
this.server = server;
}
private CallListener callListener;
public void setCallListener(CallListener callListener) {
this.callListener = callListener;
}
public void ping() {
if (socket == null) {
return;
}
socket.emit(PING, System.currentTimeMillis());
}
public void bindDomain() {
socket.emit(BIND_DOMAIN, domain);
}
public void start() throws Exception {
Options opts = new Options();
opts.transports = new String[] { "websocket", "polling" };
socket = IO.socket(server, opts);
Map<String, String> eventMapper = new HashMap<String, String>();
eventMapper.put(Socket.EVENT_DISCONNECT, "断开连接");
eventMapper.put(Socket.EVENT_ERROR, "断开错误");
eventMapper.put(Socket.EVENT_CONNECTING, "正在连接服务器");
eventMapper.put(Socket.EVENT_CONNECT_TIMEOUT, "连接服务器超时");
eventMapper.put(Socket.EVENT_RECONNECTING, "自动重连服务器");
eventMapper.put(Socket.EVENT_RECONNECT, "准备重连服务器");
eventMapper.put(Socket.EVENT_CONNECT, "连接服务器成功");
eventMapper.put(HTTP_REQUEST, null);
eventMapper.put(BIND_DOMAIN_NOTICE, null);
eventMapper.put(PING_NOTICE, null);
Set<String> keys = eventMapper.keySet();
// 注册事件和提示信息
for (String k : keys) {
SocketListener socketListener = new SocketListener() {
@Override
public void eventCall(String eventName, String message, Object... args) {
if (null != message) {
callListener.eventCall("[" + eventName + "]" + message);
}
switch (eventName) {
case Socket.EVENT_CONNECT:
callListener.statusCall("连接服务器成功");
LocalServer.this.bindDomain();
LocalServer.this.ping();
break;
case HTTP_REQUEST:
handlerRequest(args);
break;
case BIND_DOMAIN_NOTICE:
handlerBindDomain(args);
break;
case PING_NOTICE:
handlerPing(args);
break;
default:
break;
}
}
};
socketListener.setEventName(k);
socketListener.setMessage(eventMapper.get(k));
socket.on(k, socketListener);
}
socket.connect();
// 注册回调事件,实时统计网络速率
TimerTask task = new TimerTask() {
@Override
public void run() {
long temp = speed;
speed = 0;
callListener.speedCall(temp);
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, 0, 1000);
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
ping();
}
}, 0, 10000);
}
private void handlerPing(Object[] args) {
long time = (long) args[0];
long ms = System.currentTimeMillis() - time;
callListener.ping(ms);
}
private void handlerBindDomain(Object... args) {
try {
org.json.JSONObject jsonObject = (org.json.JSONObject) args[0];
int code = jsonObject.getInt("code");
String msg = jsonObject.getString("msg");
if (code == 1000) {
// 弹出地址
} else {
// 断开链接
socket.close();
callListener.onClose();
}
callListener.eventCall("[绑定域名]:" + msg);
} catch (Exception e) {
logger.error(e);
}
}
/**
* 处理远程的http请求
*
* @param args
*/
private void handlerRequest(Object... args) {
org.json.JSONObject object = (org.json.JSONObject) args[0];
JSONObject request = JSON.parseObject(object.toString());
String url = request.getString("url");
Map<String, Object> headers = request.getJSONObject("headers");
headers.remove("content-length");
String method = request.getString("method");
String eventName = request.getString("eventName");
Map<String, Object> params = request.getJSONObject("params");
String reqUrl = forward + url;
logger.info("收到请求: methon=" + method + " url=" + reqUrl);
if (callListener != null) {
callListener.eventCall("[远程请求]: methon=" + method + " url=" + reqUrl + " params:" + params + " headers:" + headers);
}
Response response = null;
// 发送请求
// 替换host
Set<String> keys = headers.keySet();
if ("POST".equals(method.toUpperCase())) {
// 查看是否是json或者xml请求一类
String encoding = "utf-8";
String contentType = null;
if (headers.get("content-type") != null) {
contentType = headers.get("content-type").toString();
String[] array = contentType.split(";");
contentType = array[0];
if (array.length > 1) {
String[] charsets = array[1].split("=");
if (charsets.length > 1) {
encoding = charsets[1];
}
}
}
HttpPost post = new HttpPost(reqUrl);
for (String k : keys) {
post.addHeader(k, String.valueOf(headers.get(k)));
}
try {
// 默认类型application/x-www-form-urlencoded
if (contentType == null) {
contentType = "application/x-www-form-urlencoded";
}
// 兼容普通post和json/xml post
if (contentType.equals("application/x-www-form-urlencoded")) {
response = HttpClientUtils.post(post, params);
}else {
//其他的全部postBody
response = HttpClientUtils.postBody(post, request.getString("params"), encoding);
}
} catch (Exception e) {
response = new Response();
response.setStatusCode(500);
response.setStatusMessage("本地服务器报错:" + e.getMessage());
}
} else if ("GET".equals(method.toUpperCase())) {
HttpGet get = new HttpGet(reqUrl);
for (String k : keys) {
get.addHeader(k, String.valueOf(headers.get(k)));
}
try {
response = HttpClientUtils.get(get);
} catch (Exception e) {
response = new Response();
response.setStatusCode(500);
response.setStatusMessage("本地服务器报错:" + e.getMessage());
}
} else {
// 提示请求不支持
response = new Response();
response.setStatusCode(500);
response.setEncoding("utf-8");
response.setStatusMessage(method + "请求类型暂时不支持!");
}
org.json.JSONObject jsonObject = new org.json.JSONObject();
try {
// 处理重定向
if (response.getStatusCode() == 302 || response.getStatusCode() == 307 || response.getStatusCode() == 303) {
// 处理地址
String localtion = response.getHeaders().get("Location");
localtion.replace(server, domain);
response.getHeaders().put("Location", localtion);
}
byte[] bytes = (byte[]) response.getBody();
long length = bytes.length;
this.traffic += length;
this.speed += length;
jsonObject.put("body", response.getBody());
jsonObject.put("headers", response.getHeaders());
jsonObject.put("statusCode", response.getStatusCode());
jsonObject.put("encoding", response.getEncoding());
jsonObject.put("statusMessage", response.getStatusMessage());
jsonObject.put("eventName", eventName);
} catch (JSONException e) {
e.printStackTrace();
}
logger.info("请求响应:" + response);
if (callListener != null) {
callListener.eventCall("[目标响应]:" + response);
}
if (socket == null) {
callListener.eventCall("[服务关闭] The service has been closed.");
return;
}
socket.emit(HTTP_RESPONSE, jsonObject);
// 通知界面显示流量
callListener.trafficCall(this.traffic);
}
public void stop() {
if (socket != null) {
socket.close();
socket = null;
}
callListener.ping(0l);
}
public static void main(String[] args) throws Exception {
new MainForm().setVisible(true);
}
}
@@ -0,0 +1,65 @@
package com.wezoz.nat;
import java.io.Serializable;
import java.util.Map;
public class Response implements Serializable{
private static final long serialVersionUID = 5431808741731247591L;
private int statusCode = 200;// 状态码
private String statusMessage = "ok";// 状态消息
private Map<String, String> headers;// 请求头
private String encoding;// 编码
private Object body;// 响应内容
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public String getStatusMessage() {
return statusMessage;
}
public void setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
}
public Map<String, String> getHeaders() {
return headers;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public Object getBody() {
return body;
}
public void setBody(Object body) {
this.body = body;
}
@Override
public String toString() {
return "Response [statusCode=" + statusCode + ", statusMessage=" + statusMessage + ", headers=" + headers + ", encoding=" + encoding + ", body={}]";
}
}
@@ -0,0 +1,40 @@
package com.wezoz.nat;
import io.socket.emitter.Emitter.Listener;
public abstract class SocketListener implements Listener {
private String eventName;
private String message;
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public String getEventName() {
return eventName;
}
@Override
public void call(Object... args) {
this.eventCall(this.getEventName(),this.getMessage(), args);
}
/**
* 回调事件
*
* @param eventName
* @param args
*/
public abstract void eventCall(String eventName,String message, Object... args);
}
@@ -0,0 +1,29 @@
package com.wezoz.nat.form;
import java.awt.Color;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class BaseForm extends JFrame {
private static final long serialVersionUID = -8446051052250946428L;
public BaseForm() {
getContentPane().setLayout(null);
getContentPane().setBackground(new Color(248, 251, 253));
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
super.windowClosing(e);
}
});
ImageIcon imageIcon = new ImageIcon(getClass().getResource("/logo.png"));
this.setIconImage(imageIcon.getImage());
}
}
@@ -0,0 +1,80 @@
package com.wezoz.nat.form;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import javax.swing.JButton;
import javax.swing.JTextField;
public class LoginForm extends BaseForm {
private static final long serialVersionUID = -8577615925651575124L;
private JTextField txtUsername;
private JTextField txtPassword;
public LoginForm() {
setResizable(false);
txtUsername = new JTextField();
txtUsername.setForeground(new Color(104, 104, 104));
txtUsername.setBounds(69, 66, 235, 41);
getContentPane().add(txtUsername);
txtUsername.setColumns(10);
txtPassword = new JTextField();
txtPassword.setToolTipText("密码");
txtPassword.setColumns(10);
txtPassword.setForeground(new Color(104, 104, 104));
txtPassword.setBounds(69, 122, 235, 41);
getContentPane().add(txtPassword);
JButton btnLogin = new JButton("登录");
btnLogin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
new MainForm().setVisible(true);
}
});
btnLogin.setBounds(187, 185, 117, 47);
getContentPane().add(btnLogin);
JButton btnReg = new JButton("注册");
btnReg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (java.awt.Desktop.isDesktopSupported()) {
try {
// 创建一个URI实例
URI uri = URI.create("https://www.wezoz.com/register/");
// 获取当前系统桌面扩展
java.awt.Desktop dp = java.awt.Desktop.getDesktop();
// 判断系统桌面是否支持要执行的功能
if (dp.isSupported(java.awt.Desktop.Action.BROWSE)) {
// 获取系统默认浏览器打开链接
dp.browse(uri);
}
} catch (NullPointerException e1) {
// 此为uri为空时抛出异常
} catch (IOException e2) {
// 此为无法获取系统默认浏览器
}
}
}
});
btnReg.setBounds(69, 185, 117, 47);
getContentPane().add(btnReg);
this.setSize(400, 300);
this.setLocationRelativeTo(null);
this.setTitle("Wezoz NAT 登录");
}
public static void main(String[] args) {
new LoginForm().setVisible(true);
}
}
@@ -0,0 +1,247 @@
package com.wezoz.nat.form;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import com.wezoz.nat.CallListener;
import com.wezoz.nat.LocalServer;
public class MainForm extends BaseForm {
private static final long serialVersionUID = -8577615925651575124L;
private JTextField txtHost;
private JTextArea txtConsole;
private JButton btnAction;
private JLabel lblStatus;
private LocalServer server;
private JPanel panelSetting;
private JScrollPane panelConsole;
private JLabel label_1;
private JTextField txtDomain;
private JLabel lblwezozcom;
private JLabel lablTraffic;
private JLabel label_3;
private JLabel lblSpeed;
private JLabel lblPing;
public MainForm() {
setTitle("Wezoz NAT");
this.setSize(546, 432);
setLocationRelativeTo(null);
JLabel label = new JLabel("状态:");
label.setBounds(20, 27, 61, 16);
getContentPane().add(label);
lblStatus = new JLabel("服务停止");
lblStatus.setBounds(60, 27, 280, 16);
getContentPane().add(lblStatus);
btnAction = new JButton("启动服务");
btnAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (btnAction.getText().equals("启动服务")) {
try {
String host = txtHost.getText();
server = new LocalServer();
server.setServer("http://wezoz.com:3001");
server.setForward(host);
server.setDomain(txtDomain.getText());
server.setCallListener(new CallListener() {
@Override
public void statusCall(String info) {
lblStatus.setText(info);
}
@Override
public void eventCall(String info) {
txtConsole.append(info + "\n");
}
@Override
public void onClose() {
server.stop();
lblStatus.setText("服务停止");
btnAction.setText("启动服务");
}
@Override
public void trafficCall(long traffic) {
lablTraffic.setText(formatNumber(traffic));
}
@Override
public void speedCall(long speed) {
lblSpeed.setText(formatNumber(speed)+"/s");
}
@Override
public void ping(long ms) {
lblPing.setText(ms+"ms");
}
});
server.start();
btnAction.setText("停止服务");
} catch (Exception ex) {
lblStatus.setText("启动失败!请检查地址是否正确");
}
} else {
server.stop();
lblStatus.setText("服务停止");
btnAction.setText("启动服务");
}
}
});
btnAction.setBounds(339, 22, 117, 29);
getContentPane().add(btnAction);
panelSetting = new JPanel();
panelSetting.setBackground(new Color(248, 251, 253));
panelSetting.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null), "\u7F51\u7EDC\u53C2\u6570", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
panelSetting.setBounds(19, 55, 506, 119);
getContentPane().add(panelSetting);
panelSetting.setLayout(null);
JLabel lblip = new JLabel("转发地址:");
lblip.setBounds(18, 64, 65, 16);
panelSetting.add(lblip);
txtHost = new JTextField();
txtHost.setText("http://127.0.0.1:8080");
txtHost.setBounds(82, 59, 331, 26);
panelSetting.add(txtHost);
txtHost.setColumns(10);
label_1 = new JLabel("绑定域名:");
label_1.setBounds(18, 30, 65, 16);
panelSetting.add(label_1);
txtDomain = new JTextField();
txtDomain.setColumns(10);
txtDomain.setBounds(82, 25, 108, 26);
panelSetting.add(txtDomain);
lblwezozcom = new JLabel(".wezoz.com");
lblwezozcom.setBounds(189, 30, 90, 16);
panelSetting.add(lblwezozcom);
JLabel label_2 = new JLabel("流出流量:");
label_2.setBounds(18, 92, 65, 16);
panelSetting.add(label_2);
lablTraffic = new JLabel("0KB");
lablTraffic.setBounds(82, 92, 96, 16);
panelSetting.add(lablTraffic);
label_3 = new JLabel("速度:");
label_3.setBounds(162, 92, 39, 16);
panelSetting.add(label_3);
lblSpeed = new JLabel("0KB");
lblSpeed.setBounds(199, 92, 73, 16);
panelSetting.add(lblSpeed);
JLabel label_4 = new JLabel("延迟:");
label_4.setBounds(305, 92, 39, 16);
panelSetting.add(label_4);
lblPing = new JLabel("0ms");
lblPing.setBounds(342, 92, 123, 16);
panelSetting.add(lblPing);
txtConsole = new JTextArea() {
/**
*
*/
private static final long serialVersionUID = 8749801166570350982L;
@Override
public void append(String str) {
this.setCaretPosition(this.getDocument().getLength());
str = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " - " + str;
if (this.getText().length() > 100000) {
this.setText("");
}
super.append(str);
}
};
txtConsole.setText("准备就绪\n");
txtConsole.setBounds(19, 181, 437, 129);
panelConsole = new JScrollPane(txtConsole, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
panelConsole.setLocation(20, 210);
panelConsole.setSize(431, 150);
getContentPane().add(panelConsole);
this.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
change();
super.componentResized(e);
}
});
change();
}
private String formatNumber(long traffic) {
String text = null;
DecimalFormat format = new DecimalFormat("#.##");
Double value = traffic * 0.0001221d;
if (value <= 1024) {
text = format.format(value) + "KB";
} else if (value / 1024 > 1) {
text = format.format((value / 1024)) + "MB";
} else if (value / 1024 / 1024 > 1) {
text = format.format((value / 1024 / 1024)) + "GB";
} else if (value / 1024 / 1024 / 1024 > 1) {
text = format.format((value / 1024 / 1024 / 1024)) + "TB";
}
return text;
}
private void change() {
int width = MainForm.this.getWidth();
int height = MainForm.this.getHeight();
int wv = width - 40;
panelSetting.setSize(wv, panelSetting.getHeight());
panelConsole.setSize(wv, height - panelConsole.getY() - 40);
btnAction.setLocation(width - 20 - btnAction.getWidth(), btnAction.getY());
}
public static void main(String[] args) {
new MainForm().setVisible(true);
}
}
@@ -0,0 +1,455 @@
package com.wezoz.nat.utils;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPOutputStream;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
import com.wezoz.nat.Response;
/**
* http请求工具 httpclient4.5
*
* @author panjing
* @project wootop-common
* @date 2016年4月19日 上午11:20:43
*/
@SuppressWarnings("deprecation")
public class HttpClientUtils {
private static Log log = LogFactory.getLog(HttpClientUtils.class);
public final static String DEFAULT_ENCODING = "UTF-8";
public final static String CONTENT_TYPE = "Content-Type";
public final static String TEXT_HTML = "text/html";
public final static int STATUS_CODE_SUCCESS = 200;
private static CloseableHttpClient httpClient;
private static PoolingHttpClientConnectionManager connMgr;
private static RequestConfig requestConfig;
private static final int MAX_TIMEOUT = 7000;
static {
// 设置连接池
connMgr = new PoolingHttpClientConnectionManager();
// 设置连接池大小
connMgr.setMaxTotal(100);
connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());
RequestConfig.Builder configBuilder = RequestConfig.custom();
// 设置连接超时
configBuilder.setConnectTimeout(MAX_TIMEOUT);
// 设置读取超时
configBuilder.setSocketTimeout(MAX_TIMEOUT);
// 设置从连接池获取连接实例的超时
configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
// 在提交请求之前 测试连接是否可用
configBuilder.setStaleConnectionCheckEnabled(true);
requestConfig = configBuilder.build();
}
public static CloseableHttpClient getClient() {
if (httpClient == null) {
//不重定向处理
RequestConfig config = RequestConfig.custom().setConnectTimeout(100000).setConnectionRequestTimeout(100000).setSocketTimeout(100000).setRedirectsEnabled(false).build();
httpClient = HttpClients.custom().setDefaultRequestConfig(config).build();
}
return httpClient;
}
/**
* get请求
*
* @param url
* @return
*/
public static Response get(String url) {
HttpGet httpGet = new HttpGet(url);
return get(httpGet);
}
/**
* get请求
*
* @param httpGet
* @return
*/
public static Response get(HttpGet httpGet) {
Response response = new Response();
try {
CloseableHttpResponse res = getClient().execute(httpGet);
response = getContent(res);
} catch (SocketTimeoutException e) {
log.error("Read timed out:" + httpGet.getURI());
response.setStatusCode(502);
response.setStatusMessage("读取超时");
} catch (Exception e) {
response.setStatusCode(500);
response.setStatusMessage("请求本地服务器出错");
log.error(e);
}
return response;
}
/**
* post请求
*
* @param url
* @param params
* @return
*/
public static Response post(String url, Map<String, Object> params) {
HttpPost httpPost = new HttpPost(url);
return post(httpPost, params);
}
public static Response postSSL(String url, Map<String, Object> params) {
HttpPost httpPost = new HttpPost(url);
return postSSL(httpPost, params);
}
/**
* post请求
*
* @param httpPost
* @param params
* @return
*/
public static Response post(HttpPost httpPost, Map<String, Object> params) {
Response res = null;
try {
if (params != null) {
List<BasicNameValuePair> basicNameValuePairs = new ArrayList<BasicNameValuePair>();
Set<String> keySet = params.keySet();
for (String key : keySet) {
Object obj = params.get(key);
String value = null;
if (obj != null) {
value = String.valueOf(obj);
}
basicNameValuePairs.add(new BasicNameValuePair(key, value));
}
HttpEntity httpEntity = new UrlEncodedFormEntity(basicNameValuePairs, DEFAULT_ENCODING);
httpPost.setEntity(httpEntity);
}
CloseableHttpResponse response = getClient().execute(httpPost);
res = getContent(response);
} catch (Exception e) {
e.printStackTrace();
log.error(e);
}
return res;
}
public static Response postBody(HttpPost httpPost, String body,String encoding) {
Response res = null;
try {
httpPost.setEntity(new StringEntity(body, encoding));
CloseableHttpResponse response = getClient().execute(httpPost);
res = getContent(response);
} catch (Exception e) {
e.printStackTrace();
log.error(e);
}
return res;
}
public static Response gzipPost(String url, Map<String, Object> params) {
HttpPost httpPost = new HttpPost(url);
return gzipPost(httpPost, params);
}
public static Response gzipPost(HttpPost httpPost, Map<String, Object> params) {
Response res = null;
try {
// httpPost.addHeader("User-Agent", DEFAULT_USER_AGENT);
httpPost.addHeader("Content-Encoding", "gzip");
if (params != null) {
List<BasicNameValuePair> basicNameValuePairs = new ArrayList<BasicNameValuePair>();
Set<String> keySet = params.keySet();
for (String key : keySet) {
Object obj = params.get(key);
String value = null;
if (obj != null) {
value = String.valueOf(obj);
}
basicNameValuePairs.add(new BasicNameValuePair(key, value));
}
// HttpEntity httpEntity = new
// UrlEncodedFormEntity(basicNameValuePairs, DEFAULT_ENCODING);
String str = JSON.toJSONString(params);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gos = new GZIPOutputStream(baos);
gos.write(str.getBytes("utf-8"));
gos.flush();
byte[] bs = baos.toByteArray();
HttpEntity httpEntity = new ByteArrayEntity(bs);
httpPost.setEntity(httpEntity);
}
CloseableHttpResponse response = getClient().execute(httpPost);
res = getContent(response);
} catch (Exception e) {
e.printStackTrace();
log.error(e);
}
return res;
}
public static Response postSSL(HttpPost httpPost, Map<String, Object> params) {
Response res = null;
try {
// httpPost.addHeader("User-Agent", DEFAULT_USER_AGENT);
List<BasicNameValuePair> basicNameValuePairs = new ArrayList<BasicNameValuePair>();
Set<String> keySet = params.keySet();
for (String key : keySet) {
Object obj = params.get(key);
String value = null;
if (obj != null) {
value = String.valueOf(obj);
}
basicNameValuePairs.add(new BasicNameValuePair(key, value));
}
HttpEntity httpEntity = new UrlEncodedFormEntity(basicNameValuePairs, DEFAULT_ENCODING);
httpPost.setEntity(httpEntity);
URI uri = httpPost.getURI();
new SSLHttpClient().registerSSL(uri.getHost(), "https", uri.getPort(), uri.getScheme());
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()).setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
CloseableHttpResponse response = httpClient.execute(httpPost);
res = getContent(response);
} catch (Exception e) {
e.printStackTrace();
log.error(e);
}
return res;
}
private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
SSLConnectionSocketFactory sslsf = null;
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
@Override
public void verify(String host, SSLSocket ssl) throws IOException {
}
@Override
public void verify(String host, X509Certificate cert) throws SSLException {
}
@Override
public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
}
});
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return sslsf;
}
// 功能: postBody形式发送数据
// @param urlPath 对方地址
// @param json 要传送的数据
// @return
// @throws Exception
public static String postBody(String urlPath, String data) throws Exception {
// Configure and open a connection to the site you will send the
// request
URL url = new URL(urlPath);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// 设置doOutput属性为true表示将使用此urlConnection写入数据
urlConnection.setDoOutput(true);
// 定义待写入数据的内容类型,我们设置为application/x-www-form-urlencoded类型
urlConnection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 得到请求的输出流对象
OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());
// 把数据写入请求的Body
out.write(data);
out.flush();
out.close();
// 从服务器读取响应
InputStream inputStream = urlConnection.getInputStream();
String encoding = urlConnection.getContentEncoding();
String body = IOUtils.toString(inputStream, encoding);
if (urlConnection.getResponseCode() != 200) {
throw new Exception(body);
}
return body;
}
public static String getEncoding(CloseableHttpResponse response) {
String encoding = null;
Header[] headers = response.getHeaders(CONTENT_TYPE);
if (headers != null && headers.length > 0) {
Header header = headers[0];
String value = header.getValue();
value = value.replaceAll(" ", "");
value = value.toLowerCase();
int index = 0;
if ((index = value.lastIndexOf("charset")) != -1) {
String[] array = value.substring(index).split("=");
if (array.length > 1) {
encoding = array[1];
}
}
}
return encoding;
}
/**
* 获取响应内容
*
* @param response
* @return
* @throws ParseException
* @throws IOException
*/
public static Response getContent(CloseableHttpResponse response) throws ParseException, IOException {
Response res = new Response();
HttpEntity entity = response.getEntity();
if (entity == null) {
return res;
}
byte[] bytes = readBytes(entity.getContent());
String encoding = getEncoding(response);
if (encoding == null) {
encoding = "utf-8";
}
res.setBody(bytes);
res.setEncoding(encoding);
res.setStatusCode(response.getStatusLine().getStatusCode());
Map<String, String> headersMap = new HashMap<String, String>();
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
headersMap.put(header.getName(), header.getValue());
}
res.setHeaders(headersMap);
// content = new String(bytes, encoding);
EntityUtils.consume(response.getEntity());
response.close();
return res;
}
/**
* 将流读取为字节数组
*
* @param in
* @return
* @throws IOException
*/
public static byte[] readBytes(InputStream in) throws IOException {
BufferedInputStream bufin = new BufferedInputStream(in);
int buffSize = 1024;
ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
byte[] temp = new byte[buffSize];
int size = 0;
while ((size = bufin.read(temp)) != -1) {
out.write(temp, 0, size);
}
bufin.close();
byte[] content = out.toByteArray();
return content;
}
public static void main(String[] args) {
System.out.println(get("http://localhost:8080/wootop-doctor/"));
}
}
@@ -0,0 +1,89 @@
package com.wezoz.nat.utils;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
@SuppressWarnings("deprecation")
public class SSLHttpClient {
/**
* 注册SSL连接
* @param hostname 请求的主机名(IP或者域名)
* @param protocol 请求协议名称(TLS-安全传输层协议)
* @param port 端口号
* @param scheme 协议名称
* @return HttpClient实例
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public CloseableHttpClient registerSSL(String hostname,String protocol,int port,String scheme)throws NoSuchAlgorithmException, KeyManagementException {
//创建一个默认的HttpClient
CloseableHttpClient httpclient = HttpClients.createDefault();
//创建SSL上下文实例
SSLContext ctx = SSLContext.getInstance(protocol);
//服务端证书验证
X509TrustManager tm = new X509TrustManager() {
/**
* 验证客户端证书
*/
@Override
public void checkClientTrusted(X509Certificate[] chain,String authType)
throws java.security.cert.CertificateException {
//这里跳过客户端证书 验证
}
/**
* 验证服务端证书
* @param chain 证书链
* @param authType 使用的密钥交换算法,当使用来自服务器的密钥时authType为RSA
*/
@Override
public void checkServerTrusted(X509Certificate[] chain,String authType)
throws java.security.cert.CertificateException {
if (chain == null || chain.length == 0)
throw new IllegalArgumentException("null or zero-length certificate chain");
if (authType == null || authType.length() == 0)
throw new IllegalArgumentException("null or zero-length authentication type");
boolean br = false;
Principal principal = null;
for (X509Certificate x509Certificate : chain) {
principal = x509Certificate.getSubjectX500Principal();
if (principal != null) {
br = true;
return;
}
}
if (!br) {
throw new CertificateException("服务端证书验证失败!");
}
}
/**
* 返回CA发行的证书
*/
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
//初始化SSL上下文
ctx.init(null, new TrustManager[]{tm}, new java.security.SecureRandom());
//创建SSL连接
SSLSocketFactory socketFactory = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme sch = new Scheme(scheme, port, socketFactory);
//注册SSL连接
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
return httpclient;
}
}
+23
View File
@@ -0,0 +1,23 @@
log4j.rootLogger=INFO,ERROR
log4j.appender=org.apache.log4j.RollingFileAppender
log4j.appender.File=wezoz-nat.log
log4j.appender.MaxFileSize=10MB
log4j.appender.Threshold=ALL
log4j.appender.layout=org.apache.log4j.PatternLayout
log4j.appender.layout.ConversionPattern=-%t %d{yyyy-MM-dd HH\:mm\:ss,SSS} -%p -%l -%m %n
log4j.appender.BufferSize=8192
log4j.appender.INFO=org.apache.log4j.ConsoleAppender
log4j.appender.INFO.Target=System.out
log4j.appender.INFO.layout=org.apache.log4j.PatternLayout
log4j.appender.INFO.layout.ConversionPattern=-%t %d{yyyy-MM-dd HH\:mm\:ss,SSS} -%p -%l -%m %n
log4j.appender.ERROR=org.apache.log4j.ConsoleAppender
log4j.appender.ERROR.layout=org.apache.log4j.PatternLayout
log4j.appender.ERROR.Target=System.out
log4j.appender.ERROR.layout=org.apache.log4j.PatternLayout
log4j.appender.ERROR.layout.ConversionPattern=-%t %d{yyyy-MM-dd HH\:mm\:ss,SSS} -%p -%l -%m %n
#log4j.logger.org.apache.http=OFF
Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB