最近公司将原有的http协议接口,更改为了可支持https的双向接口,在查阅资料同时,将解决过程与大家分享。
使用的框架是Struts2,如有变动可自行修改相应代码。
首先,我们看看httpClient是个什么东西,它有什么作用,它能干嘛,它地基本用法?
基本使用详情①(转载):http://blog.csdn.net/wangpeng047/article/details/19624529
基本使用详情②(转载):http://blog.csdn.net/5iasp/article/details/8638800
--以上 基本可以让你对httpClient有个基本了解,也可以有个基本的使用。
httpClient是一个用于调用http协议的插件,要使用此插件需使用以下jar包:
commons-beanutils-1.8.0.jar
commons-codec.jar
commons-collections-3.2.jar
commons-lang-2.4.jar
commons-lang3-3.1.jar
commons-logging-1.1.1.jar
ezmorph-1.0.4.jar
httpclient-4.1.3.jar
httpclient-cache-4.1.3.jar
httpcore-4.1.4.jar
httpmime-4.1.3.jar
json-lib-2.4-jdk15.jar
以上jar下载地址:
http://download.csdn.net/detail/dcb_ripple/9477012
简单的的httpClient 使用,
1.httpClient 简单使用HttpPost调用http接口
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/**
* 使用httpPost http登陆接口(无http摘要认证)
*/
public static void testHttpClient(){
//1.创建httpClient对象 (使用https协议,需要略过ssl验证,这里使用MySSLSocketFactory)
HttpClient httpclient = new DefaultHttpClient();
//url https地址
String url ="http://192.168.10.215:8080/tnserver/property_manager/login";
try {
//2.创建列参数(httpPost使用)
HttpPost httppost = new HttpPost(url);
List<NameValuePair> list = new ArrayList<NameValuePair>();
//将用户名与密码作为参数写入(username,password这两个参数是 根据你的接口协议而定)
list.add(new BasicNameValuePair("username","admin"));
list.add(new BasicNameValuePair("password","123456"));
//3.写入请求头
httppost.addHeader("Content-type", "application/x-www-form-urlencoded");
//4.将参数写入到httpost中,并设置编码格式为UTF-8
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,"UTF-8");
httppost.setEntity(entity);
//5.执行
HttpResponse post= httpclient.execute(httppost);
//6.执行完毕,判断返回code码,200为正常
if (post.getStatusLine().getStatusCode() == 200) {
//7.获取返回json格式数据 注意,这里不能直接转java.lang.String进行强转,
String conResult = EntityUtils.toString(post.getEntity());
//8.处理返回数据....(完)
JSONObject sobj = new JSONObject();
sobj = JSONObject.fromObject(conResult);
System.out.println(sobj);
} else {
System.out.println("失败....");
}
}catch(Exception e){
e.printStackTrace();
}
}
</pre><p></p><pre>
以上这个例子很中规中矩,没有太多特殊处理的地方。
那如果想象一下,要传入的参数是一个JSON格式的数据呢?
例如在登陆时将用户名与密码已json格式传入,
格式如下:
{
"username":"admin",
"password":"admin"
}
====那这个时候如果再采用List<NameValuePair> list = new ArrayList<NameValuePair>();list.add(new BasicNameValuePair("username","xxxx"));list.add(new BasicNameValuePair("password","xxxxx"));
的方式传参肯定是有问题的,因为它采用key/value的方式传值方式,与action中 ”getRequest().getParameter(“xxx”) “ 是一个道理
那么这个时候该怎么进行参数的传递呢?--看下面
2.httpClient 简单使用HttpPost 参数类型为JSON格式时
/**
* 使用httpPost 参数为JSON格式时(无http摘要认证)
*/
public static void testHttpClient1(){
HttpClient httpclient = new DefaultHttpClient();
String url ="http://192.168.10.215:8080/tnserver/property_manager/login";
try {
HttpPost httppost = new HttpPost(url);
httppost.addHeader("Content-type", "application/x-www-form-urlencoded");
//此处略有不同的是,它是直接将JSON格式数据写如到httppost.setEntity实体中
//并采用了StringEntity工具类,来进行转换。。。。
JSONObject json = new JSONObject();
json.put("username", "admin@qq.com");
json.put("password", "123456");
StringEntity entity = new StringEntity(json.toString(),"UTF-8");
httppost.setEntity(entity);
HttpResponse post= httpclient.execute(httppost);
if (post.getStatusLine().getStatusCode() == 200) {
String conResult = EntityUtils.toString(post.getEntity());
JSONObject sobj = new JSONObject();
sobj = JSONObject.fromObject(conResult);
System.out.println(sobj);
} else {
System.out.println("失败....");
}
}catch(Exception e){
e.printStackTrace();
}finally{
}
}
通过上面StringEntity entity 类的处理就可以实现传输JSON格式参数了。
是不是很简单,快试一试就知道了,上面的代码只需要Copy到自己的Main方法中就可以测试。。。。。
不过要注意测试之前请先弄清楚你的htpp接口根据接口进行相应更改
===========================================================
以上两个例子只可基于http协议,且服务器中没有设置身份认证的情况下。。。
服务器中有账户认证处理
具体如下:
public static void testHttpClient2(){
HttpClient httpclient = new DefaultHttpClient();
String url ="http://xxxxx:xxxxx/tnserver/property_manager/login";
try {
HttpPost httppost = new HttpPost(url);
//==========http认证过程===================== 如无需采用https协议进行调用,可忽略https认证过程
//注:此方法只用于import org.apache.http.client.HttpClient; 新版本的认证
//旧版本:import org.apache.commons.httpclient 认证方法如下:
//Credentials defaultcreds = new UsernamePasswordCredentials("userxxx","pwdxxx");
//httpClient.getState().setCredentials(AuthScope.ANY, defaultcreds);
//注意。 旧版本的认证方式导入的包是 带 org.apache.commons.xxxx
//创建https认证对象
CredentialsProvider credsProvider = new BasicCredentialsProvider();
//写入认证的用户名与密码
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("xxx", "xxx");
//创建验证
credsProvider.setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
creds);
//将认证写入到httpClient中
((DefaultHttpClient)httpclient).setCredentialsProvider(credsProvider);
//=========Https认证===end=============================
httppost.addHeader("Content-type", "application/x-www-form-urlencoded");
JSONObject json = new JSONObject();
json.put("username", "xxxx");
json.put("password", "xxxxx");
StringEntity entity = new StringEntity(json.toString());
httppost.setEntity(entity);
HttpResponse post= httpclient.execute(httppost);
if (post.getStatusLine().getStatusCode() == 200) {
String conResult = EntityUtils.toString(post.getEntity());
JSONObject sobj = new JSONObject();
sobj = JSONObject.fromObject(conResult);
System.out.println(sobj);
} else {
System.out.println("失败....");
}
}catch(Exception e){
e.printStackTrace();
}finally{
}
}
这个认证账户密码是在http服务器中设置,所以别说不知账户密码是什么,直接问接口提供方。
前提是对方告诉你这是一个基于http协议的接口,并且会有认证过程。
好,上面说了又一种旧版本的认证方式,这里直接附上 (注意这里的调用方式不一样,旧版本没有httpPost 而是PostMethod。。详情请百度。)
http://www.cnblogs.com/davidwang456/p/4062233.html
HTTPS如果略过证书认证过程
那又如果使用是基于HTTPS的呢?
HTTPS与HTTP有很大区别,它相比HTTP协议更安全,更高效。
HTTP与HTTP区别:http://blog.csdn.net/angussl/article/details/5557738
-正题:如何在调用时略过HTTPS 证书SSL认证过程
在调用https协议的的接口时都会遇到一个问题,那就是SSL证书怎么破,难道真的在本地安装?貌似有点不好弄,说实话我也不会.....
所以我们肯定是希望有这么一个东西,那就是可以在使用的时候忽略SSL认证的问题,那么这样我们就不必为SSL而苦恼。
代码:
package com.httpclicent;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
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.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
/**
* https SSL证书避免认证问题 (注意此处同样是新版本的SSL避免方式)
* @author yzs
*
*/
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
/**
*
* @param truststore
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws KeyStoreException
* @throws UnrecoverableKeyException
*/
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
/**
* 在使用时直接调用它即可,,,, 直接得略过https的ssl验证过程
* @return
*/
public static HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
}
=============================说明:此类是从别处找到,并非自己写出来的
有了这个Class一切都将不是问题,无需太大改动,只需要在创建HttpClicent时 使用 类中的getNewHttpClient即可
如下:
//1.创建httpClient对象 (使用https协议,需要略过ssl验证,这里使用MySSLSocketFactory)
HttpClient httpclient = MySSLSocketFactory.getNewHttpClient();
代码:
public static void testHttpClient3(){
//1.创建httpClient对象 (使用https协议,需要略过ssl验证,这里使用MySSLSocketFactory)
HttpClient httpclient = MySSLSocketFactory.getNewHttpClient();
<span style="white-space:pre"> </span>//http默认端口号是80 https为443
String url ="http://xxxx:443/tnserver/property_manager/login";
try {
HttpPost httppost = new HttpPost(url);
//==========https认证过程===================== 如无需采用https协议进行调用,客户了https认证过程
//注:此方法只用于import org.apache.http.client.HttpClient; 新版本的认证
//创建https认证对象
CredentialsProvider credsProvider = new BasicCredentialsProvider();
//写入认证的用户名与密码
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("xxx", "xxx");
//创建验证
credsProvider.setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
creds);
//将认证写入到httpClient中
((DefaultHttpClient)httpclient).setCredentialsProvider(credsProvider);
//=========Https认证===end=============================
httppost.addHeader("Content-type", "application/x-www-form-urlencoded");
JSONObject json = new JSONObject();
json.put("username", "xxx");
json.put("password", "xxx");
StringEntity entity = new StringEntity(json.toString());
httppost.setEntity(entity);
HttpResponse post= httpclient.execute(httppost);
if (post.getStatusLine().getStatusCode() == 200) {
String conResult = EntityUtils.toString(post.getEntity());
JSONObject sobj = new JSONObject();
sobj = JSONObject.fromObject(conResult);
System.out.println(sobj);
} else {
System.out.println("失败....");
}
}catch(Exception e){
e.printStackTrace();
}finally{
}
}
ok,有以上代码基本可以实现大部分http与https接口的调用了。。。。
附上一个自己项目中实际使用的实例
需求:
代码实现Action:
package cn.thinknet.action;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import cn.thinknet.bean.UserManage;
import cn.thinknet.util.MySSLSocketFactory;
public class UserManageAction extends BaseAction{
private String msg;
private List<UserManage> userManageList;
private JSONArray resultJa;
private String ids;
private JSONObject result;
private UserManage userManage;
public String login(){
//1.创建httpClient对象 (使用https协议,需要略过ssl验证,这里使用MySSLSocketFactory)
//注:如无需使用https协议进行调用,则代码创建处理如下
// HttpClient httpclient1 = new DefaultHttpClient();
HttpClient httpclient = MySSLSocketFactory.getNewHttpClient();
//url https地址
String url ="https://192.168.10.216:443/tnserver/property_manager/login";
try {
//2.创建列参数(httpPost使用)
List<NameValuePair> list = new ArrayList<NameValuePair>();
//将用户名与密码作为参数写入(username,password这两个参数是 根据你的接口协议而定)
list.add(new BasicNameValuePair("username","admin@163.com"));
list.add(new BasicNameValuePair("password","123456"));
//3.创建http对象
HttpPost httppost = new HttpPost(url);
//==========https认证过程===================== 如无需采用https协议进行调用,客户了https认证过程
//注:此方法只用于import org.apache.http.client.HttpClient; 新版本的认证
//旧版本:import org.apache.commons.httpclient 认证方法如下:
//Credentials defaultcreds = new UsernamePasswordCredentials("userxxx","pwdxxx");
//httpClient.getState().setCredentials(AuthScope.ANY, defaultcreds);
//注意。 旧版本的认证方式导入的包是 带 org.apache.commons.xxxx
//创建https认证对象
CredentialsProvider credsProvider = new BasicCredentialsProvider();
//写入认证的用户名与密码
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("admin", "123");
//创建验证
credsProvider.setCredentials(
new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
creds);
//将认证写入到httpClient中
((DefaultHttpClient)httpclient).setCredentialsProvider(credsProvider);
//============end=============================
httppost.addHeader("Content-type", "application/x-www-form-urlencoded");
//4.将参数写入到httpost中,并设置编码格式为UTF-8
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,"UTF-8");
httppost.setEntity(entity);
//5.执行
HttpResponse post= httpclient.execute(httppost);
//6.执行完毕,判断返回code码,200为正常
if (post.getStatusLine().getStatusCode() == 200) {
//7.获取返回json格式数据 注意,这里不能直接转java.lang.String进行强转,
String conResult = EntityUtils.toString(post.getEntity());
//8.处理返回数据....(完)
JSONObject sobj = new JSONObject();
sobj = JSONObject.fromObject(conResult);
System.out.println(sobj);
} else {
System.out.println("失败....");
}
}catch(Exception e){
e.printStackTrace();
}finally{
}
return "success1";
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public JSONArray getResultJa() {
return resultJa;
}
public void setResultJa(JSONArray resultJa) {
this.resultJa = resultJa;
}
public JSONObject getResult() {
return result;
}
public void setResult(JSONObject result) {
this.result = result;
}
public String getIds() {
return ids;
}
public void setIds(String ids) {
this.ids = ids;
}
public UserManage getUserManage() {
return userManage;
}
public void setUserManage(UserManage userManage) {
this.userManage = userManage;
}
public List<UserManage> getUserManageList() {
return userManageList;
}
public void setUserManageList(List<UserManage> userManageList) {
this.userManageList = userManageList;
}
}
返回结果:
======
完成!!! 没了,就这么多啦~~~
本人目前也是属于java两年新人,勿喷~~
最后附上简单Dome:
http://download.csdn.net/detail/dcb_ripple/9477041