1.拳头之Get/Post
拳头是最基本的一重武器,也是最重要的,好比练武之人必须先扎稳马步。
- HttpClient httpclient=new HttpClient();//创建一个客户端,类似打开一个浏览器
- GetMethod getMethod=new GetMethod("http://www.blablabla.com");//创建一个get方法,类似在浏览器地址栏中输入一个地址
- int statusCode=httpclient.executeMethod(getMethod);//回车——出拳!
- System.out.println("response=" + getMethod.getResponseBodyAsString());//察看拳头命中情况,可以获得的东西还有很多,比如head, cookies等等
- getMethod.releaseConnection();//释放,记得收拳哦
2.孔雀翎之支持https
如何支持https?
- static{
- Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
- Protocol.registerProtocol("https", easyhttps);
- }
在执行具体的http method之前,暗中将https协议注册一把,如孔雀翎暗藏玄机,毙敌于无形。记住,官方的binary发行版本没有ssl的contribute包,方法一是下载源代码版本来打造你的孔雀翎。
3.多情环之cookies
常道人老多情,其实是记忆太多,所以情之所至,正如cookies甜心,无论你走到那,总把你牵挂:
- HttpClient httpclient=new HttpClient();
- httpclient.getParams().setCookiePolicy(CookiePolicy.RFC_2109);//RFC_2109是支持较普遍的一个,还有其他cookie协议
- HttpState initialState = new HttpState();
- Cookie cookie=new Cookie();
- cookie.setDomain("www.balblabla.com");
- cookie.setPath("/");
- cookie.setName("多情环");
- cookie.setValue("多情即无情");
- initialState.addCookie(cookie);
- httpclient.setState(initialState);
- ...
4.离别钩之解构cookies
多情环的反面即离别钩,钩出,敌之身体某个部件即要与身体别离,端的是无情:
- ...//执行了某些get/post方法后
- Cookie[] cookies = httpclient.getState().getCookies();
- System.out.println("Present cookies: ");
- for (int i = 0; i < cookies.length; i++) {//循环结构零部件
- System.out.println(" - " + cookies[i].toExternalForm());
- System.out.println(" - domain=" + cookies[i].getDomain());
- System.out.println(" - path=" + cookies[i].getPath());
- ...
- }
5.霸王抢之post参数
枪,长兵器之王,诸多名将均使一杆或金或银命名的名枪,比如岳飞。post方法在提交参数对时,犹如灵蛇出洞:
- PostMethod postMethod = new PostMethod("http://www.saybot.com/postme");
- NameValuePair[] postData = new NameValuePair[2];
- postData[0] = new NameValuePair("武器", "枪");
- postData[1] = new NameValuePair("什么枪", "神枪");
- postMethod.addParameters(postData);
- ...//出枪吧
6.七星碧玉刀之支持代理(proxy)
代理,非常重要,尤其在局域网横行的年头,没有代理,你在公司上不了QQ,没有代理,google不了网页快照,代理之威,可比七星碧玉刀,无刀,在局域网和开发当中,一切白搭:
- HttpClient httpclient=new HttpClient();
- httpClient.getHostConfiguration().setProxy("192.168.0.1", 9527);
- httpClient.getParams().setAuthenticationPreemptive(true);//重要!!!告诉httpclient,使用抢先认证,否则你会收到“你没有资格”的恶果
- /*
- 这一步也至关重要,MyProxyCredentialsProvider实现了org.apache.commons.httpclient.auth.CredentialsProvider接口,
- 返回代理的credential(username/password)*/
- httpClient.getParams().setParameter(CredentialsProvider.PROVIDER, new MyProxyCredentialsProvider());
- httpClient.getState().setProxyCredentials(
- new AuthScope("192.168.0.1",
- AuthScope.ANY_PORT, //任意端口哦,可要小心
- AuthScope.ANY_REALM),//任意域哦,可要小心
- new UsernamePasswordCredentials("username",//proxy的用户名
- "password"));//proxy的密码
...
7.长生剑之天下第一
看httpclient的官方文档:jakarta.apache.org/commons/httpclient/userguide.html
看Hilton网友写的小葵花宝典笔记:www.cnjm.net/tech/article1155.html
通读后,你会有种拔剑四顾心茫然的高手感觉
利用HttpClient来获取JSON数据代码:
public static String getJsonData(String url, String data) throws Exception{
Integer statusCode = -1;
// Create HttpClient Object
DefaultHttpClient client = new DefaultHttpClient();
// Send data by post method in HTTP protocol,use HttpPost instead of
// PostMethod which was occurred in former version
HttpPost post = new HttpPost(url);
// Construct a string entity
StringEntity entity = new StringEntity(data,"UTF-8");
entity.setContentType("application/json;charset=UTF-8");
// Set XML entity
post.setEntity(entity);
// Set content type of request header
post.setHeader("accept", "application/json");
post.setHeader("Content-Type", "application/json;charset=UTF-8");
// Execute request and get the response
HttpResponse response = client.execute(post);
// Response Header - StatusLine - status code
statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
throw new HttpException("Http Status is error.");
}
HttpEntity entityRsp = response.getEntity();
StringBuffer result = new StringBuffer();
BufferedReader rd = new BufferedReader(new InputStreamReader(entityRsp
.getContent(), HTTP.UTF_8));
String tempLine = rd.readLine();
while (tempLine != null) {
result.append(tempLine);
tempLine = rd.readLine();
}
if (entityRsp != null) {
entityRsp.consumeContent();
}
return result.toString();
}
项目中与对方进行数据交互时,对方提供了一套夸域json方式传递数据,并给出了一个js示例
- $.getJSON(
- "http://www.----aspx?callback=?",
- {Name:"123",Pass:"123"},
- function(json){
- if(json.UserId==null){
- alert("NO");
- }else{
- alert(json.UserId);
- }
- }
- );
但是此方法处理数据时,只能在页面中进行,局限性很大。因此在具体实施时,使用了HttpClient来代替。
- import java.io.InputStreamReader;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpResponse;
- import org.apache.http.HttpStatus;
- import org.apache.http.NameValuePair;
- import org.apache.http.client.HttpClient;
- import org.apache.http.client.methods.HttpGet;
- import org.apache.http.client.utils.URLEncodedUtils;
- import org.apache.http.impl.client.DefaultHttpClient;
- import org.apache.http.message.BasicNameValuePair;
- import org.apache.http.protocol.HTTP;
- import org.json.JSONException;
- import org.json.JSONObject;
- import org.json.JSONTokener;
- /**
- * 使用HttpClient请求页面并返回json格式数据.
- * 对方接收的也是json格式数据。
- * 因此使用HttpGet。
- * */
- public class Json {
- public static void main(String[] args) throws JSONException {
- JSONObject json = new JSONObject();
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- params.add(new BasicNameValuePair("Name", "123"));
- params.add(new BasicNameValuePair("Pass", "123"));
- //要传递的参数.
- String url = "http://www.----aspx?" + URLEncodedUtils.format(params, HTTP.UTF_8);
- //拼接路径字符串将参数包含进去
- json = get(url);
- System.out.println(json.get("UserId"));
- }
- public static JSONObject get(String url) {
- HttpClient client = new DefaultHttpClient();
- HttpGet get = new HttpGet(url);
- JSONObject json = null;
- try {
- HttpResponse res = client.execute(get);
- if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
- HttpEntity entity = res.getEntity();
- json = new JSONObject(new JSONTokener(new InputStreamReader(entity.getContent(), HTTP.UTF_8)));
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- } finally{
- //关闭连接 ,释放资源
- client.getConnectionManager().shutdown();
- }
- return json;
- }
- }
package com.lianlian.agentllav.web.phoneReader.action;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.HttpEntity;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class PhoneReaderAction {
public static void main(String[] args) {
HttpClient httpClient = new DefaultHttpClient();
try {
HttpGet httpGet = new HttpGet("地址");//此处传入请求地址,返回JSON格式数据
System.out.println("手机报列表请求地址:" + httpGet.getURI());
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
String contentString = EntityUtils.toString(entity);
System.out.println("返回JSON:" + contentString);
Gson gson = new Gson();
Type targetType = new TypeToken<List<ViewObj>>(){}.getType();
List<ViewObj> list = gson.fromJson(contentString,targetType);
for(ViewObj vo : list){
System.out.println("原生方式: "+vo.getId()+","+vo.getName()+","+vo.getIntro());
}
}else{
//do something
}
System.out.println("----------------------------------------");
//终止操作
httpGet.abort();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭连接
httpClient.getConnectionManager().shutdown();
}
}
}
------------------------------------------------------------------------------------------------
HttpPost httpPost = new HttpPost(ORDER_URL);
System.out.println("手机报订制地址:" + httpPost.getURI());
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("cid", channelNo));
nvps.add(new BasicNameValuePair("mobile", custNo));
nvps.add(new BasicNameValuePair("bid", bid));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpClient.execute(httpPost, responseHandler);
System.out.println("返回移动订制结果JSON:" + responseBody);//返回结果示例:{"result":1000}
Gson gson = new Gson();
Properties prop = gson.fromJson(responseBody, Properties.class);
String reCode = prop.get("result").toString();
------------------------------------------------------------------------------------------------
//返回json格式为:
{"list":[{"id":137,"name":"打黑2","intro":"一场黑与黑的对决,一场情与法的冲突。绝望中的冷滟秋,手持致命“暗器”,在血与火的洗礼中,迅速做大,成为东州企业界一霸。可卧底棉球的死,让滟秋失去刻骨铭心的爱情,从而彻底走上一条不归路。"},{"id":138,"name":"余震","intro":"1976年7月的唐山,原本过着平凡幸福生活的一家四口,在某个傍晚遭遇了突然发生的地震。为了救孩子,父亲死了。但是两个孩子还被同一块楼板压在两边,想救哪一个都意味着要放弃另一个......"}]}
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, List<Book>>>() {}.getType();
HashMap<String, List<Book>> hashMap = gson.fromJson(string, type);
list = hashMap.get("list");
此处需要注意Book文件中只能包含id,name,intro属性,如需扩展属性,可通过extend 其他对象进行扩展,否则在windows下解析不会报错,可是到了linux系统下解析就报错了,本人暂时找不出原因。O(∩_∩)O哈哈~
json数据格式解析我自己分为两种; 一种是普通的,一种是带有数组形式的; 普通形式的: 服务器端返回的json数据格式如下: {"userbean":{"Uid":"100196","Showname":"\u75af\u72c2\u7684\u7334\u5b50","Avtar":null,"State":1}} 分析代码如下: // TODO 状态处理 500 200 int res = 0; res = httpClient.execute(httpPost).getStatusLine().getStatusCode(); if (res == 200) { /* * 当返回码为200时,做处理 * 得到服务器端返回json数据,并做处理 * */ HttpResponse httpResponse = httpClient.execute(httpPost); StringBuilder builder = new StringBuilder(); BufferedReader bufferedReader2 = new BufferedReader( new InputStreamReader(httpResponse.getEntity().getContent())); String str2 = ""; for (String s = bufferedReader2.readLine(); s != null; s = bufferedReader2 .readLine()) { builder.append(s); } Log.i("cat", ">>>>>>" + builder.toString()); JSONObject jsonObject = new JSONObject(builder.toString()) .getJSONObject("userbean"); String Uid; String Showname; String Avtar; String State; Uid = jsonObject.getString("Uid"); Showname = jsonObject.getString("Showname"); Avtar = jsonObject.getString("Avtar"); State = jsonObject.getString("State"); 带数组形式的: 服务器端返回的数据格式为: {"calendar": {"calendarlist": [ {"calendar_id":"1705","title":"(\u4eb2\u5b50)ddssd","category_name":"\u9ed8\u8ba4\u5206\u7c7b","showtime":"1288927800","endshowtime":"1288931400","allDay":false}, {"calendar_id":"1706","title":"(\u65c5\u884c)","category_name":"\u9ed8\u8ba4\u5206\u7c7b","showtime":"1288933200","endshowtime":"1288936800","allDay":false} ] } } 分析代码如下: // TODO 状态处理 500 200 int res = 0; res = httpClient.execute(httpPost).getStatusLine().getStatusCode(); if (res == 200) { /* * 当返回码为200时,做处理 * 得到服务器端返回json数据,并做处理 * */ HttpResponse httpResponse = httpClient.execute(httpPost); StringBuilder builder = new StringBuilder(); BufferedReader bufferedReader2 = new BufferedReader( new InputStreamReader(httpResponse.getEntity().getContent())); String str2 = ""; for (String s = bufferedReader2.readLine(); s != null; s = bufferedReader2 .readLine()) { builder.append(s); } Log.i("cat", ">>>>>>" + builder.toString()); /** * 这里需要分析服务器回传的json格式数据, */ JSONObject jsonObject = new JSONObject(builder.toString()) .getJSONObject("calendar"); JSONArray jsonArray = jsonObject.getJSONArray("calendarlist"); for(int i=0;i<jsonArray.length();i++){ JSONObject jsonObject2 = (JSONObject)jsonArray.opt(i); CalendarInfo calendarInfo = new CalendarInfo(); calendarInfo.setCalendar_id(jsonObject2.getString("calendar_id")); calendarInfo.setTitle(jsonObject2.getString("title")); calendarInfo.setCategory_name(jsonObject2.getString("category_name")); calendarInfo.setShowtime(jsonObject2.getString("showtime")); calendarInfo.setEndtime(jsonObject2.getString("endshowtime")); calendarInfo.setAllDay(jsonObject2.getBoolean("allDay")); calendarInfos.add(calendarInfo); } 总结,普通形式的只需用JSONObject ,带数组形式的需要使用JSONArray 将其变成一个list。
public static JSONObject post(String url,JSONObject json){ HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost(url); JSONObject response = null; try { StringEntity s = new StringEntity(json.toString()); s.setContentEncoding("UTF-8"); s.setContentType("application/json"); post.setEntity(s); HttpResponse res = client.execute(post); if(res.getStatusLine().getStatusCode() == HttpStatus.OK.value()){ HttpEntity entity = res.getEntity(); String charset = EntityUtils.getContentCharSet(entity); response = new JSONObject(new JSONTokener(new InputStreamReader(entity.getContent(),charset))); } } catch (Exception e) { throw new RuntimeException(e); } return response; }
import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class ClientSendData { static Log log = LogFactory.getLog(ClientSendData.class); private String Url; // 初始化数据 public ClientSendData() { Url = "https://test.yihaodian.com:8443/ims/feedbackToPingAn_getData.action"; } public String sendData(String data) { String receivedData = null; try { Map<String, String> paramsData = new HashMap<String, String>(); paramsData.put("data", data); receivedData = send(Url, paramsData); } catch (Exception e) { e.printStackTrace(); } return receivedData; } public static String send(String url, Map<String, String> paramsMap) { String result = null; PostMethod postMethod = null; HttpClient httpClient = new HttpClient(); httpClient.getParams().setParameter( HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8"); postMethod = new PostMethod(url); if (paramsMap != null && paramsMap.size() > 0) { NameValuePair[] datas = new NameValuePair[paramsMap.size()]; int index = 0; for (String key : paramsMap.keySet()) { datas[index++] = new NameValuePair(key, paramsMap.get(key)); } postMethod.setRequestBody(datas); } HttpClientParams httparams = new HttpClientParams(); httparams.setSoTimeout(60000); postMethod.setParams(httparams); try { int statusCode = httpClient.executeMethod(postMethod); if (statusCode == HttpStatus.SC_OK) { result = postMethod.getResponseBodyAsString(); log.info("发送成功!"); } else { log.error(" http response status is " + statusCode); } } catch (HttpException e) { log.error("error url=" + url, e); } catch (IOException e) { log.error("error url=" + url, e); } finally { if (postMethod != null) { postMethod.releaseConnection(); } } return result; } public static void main(String[] args) { ClientSendData t = new ClientSendData(); t.sendData("测试SSL单项连接,向服务端发送数据!"); } }
可能出现的异常
1.java.net.ConnectException: Connection refused: connect
服务器没有启动
2 .javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed
服务端的证书是不可信的。解决办法见这篇文章 http://zhuyuehua.iteye.com/blog/1102347
3.java.net.SocketException: Software caused connection abort: recv failed
这是由于服务端配置的是SSL双向认证,而客户端发送数据是按照服务器是单向认证时发送的,即没有将客户端证书信息一起发送给服务端。
4.org.apache.commons.httpclient.NoHttpResponseException
这一般是服务端防火墙的原因。拦截了客户端请求。
另外,当服务端负载过重时,也会出现此问题。
5.javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
这是由于服务端配置的是SSL双向认证,而客户端发送数据是按照服务器是单向认证时发送的,即没有将客户端证书信息一起发送给服务端。服务端验证客户端证书时,发现客户端没有证书,然后就断开了握手连接。
2.SSL双向验证时
双向验证时,暂时不知道如何用HTTPCLIENT发送数据,如需要双向验证时发送数据,参考我另外的文章。另外,有知道HTTPCLIENT如何在双向验证时发送数据的,恳请指教。
httpclient 通过https访问网站的方式有两种,一种是需要导入证书,一种是不需要的。导入证书的安全性比较高,但是如果网站证书更新了,证书需要重新导入。下面的例子是不安全的: package net.ben; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.cookie.Cookie; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.util.ArrayList; import java.util.List; public class HttpClientTest { public static void main(String[] args) throws Exception { DefaultHttpClient httpClient = new DefaultHttpClient(); try { TrustManager easyTrustManager = new X509TrustManager() { public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { //To change body of implemented methods use File | Settings | File Templates. } public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { //To change body of implemented methods use File | Settings | File Templates. } public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; //To change body of implemented methods use File | Settings | File Templates. } }; SSLContext sslcontext = SSLContext.getInstance("TLS"); sslcontext.init(null, new TrustManager[]{easyTrustManager}, null); SSLSocketFactory sf = new SSLSocketFactory(sslcontext); Scheme sch = new Scheme("https", 443, sf); httpClient.getConnectionManager().getSchemeRegistry().register(sch); HttpGet httpget = new HttpGet("https://www.xxx.com/"); System.out.println("executing request" + httpget.getRequestLine()); HttpResponse response = httpClient.execute(httpget); HttpEntity entity = response.getEntity(); System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); if (entity != null) { System.out.println("Response content length: " + entity.getContentLength()); } String content = EntityUtils.toString(entity); System.out.println(content); } finally { httpClient.getConnectionManager().shutdown(); } } }