其实就这个问题,本来是很简单的,我自己花了近两个下午才搞定,现在记录一下。也希望能帮助后来的朋友。
为什么说操蛋呢,因为从httpclient3到httpclient4,有很大的变化,而且我自己水平也不够,在jar包上出了很多问题(例如我不知道还有个httpcore)。
jar如下:
当我们在浏览器上,输入login.jsp的时候,我们其实向服务器发送了两次请求
第一次请求jsp,在浏览器解析jsp(准确的说是html)的时候发现
<img src="randPic" οnclick="changeValidateCode(this)" title="点击图片刷新验证码" /> <br />
然后就第二次向服务器发送了请求。
服务器第一次返回的信息里已经包含了session的id,我们要做的就是记录这个id
然后再向loginWithYZMAction这个action发送请求,当然得带上name,code还有之前得到的sessionid(cookie中保存的东西,除了sessionid,这些东西咱们后面再说)
然后关于验证码的读取,我现在使用的是人工读取,下一个步骤就是引入第三方的接口。
我们看代码说话
HttpClient4.x 使用cookie保持会话
HttpClient 解决中文乱码
使用HttpClient时遇到的 java.net.SocketException: Socket closed异常
先说httpclient
操蛋的httpclent!为什么说操蛋呢,因为从httpclient3到httpclient4,有很大的变化,而且我自己水平也不够,在jar包上出了很多问题(例如我不知道还有个httpcore)。
jar如下:
为了验证我们最后的程序
我们可以先搭建一个带有验证码的登陆demo。参考如下:
登陆验证码(struts2实现)
分析一下 大致的处理流程
以下面的login.jsp为例<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<script type="text/javascript">
function changeValidateCode(obj) {
/**** 获取当前的时间作为参数,无具体意义 * 每次请求需要一个不同的参数,否则可能会返回同样的验证码 * 这和浏览器的缓存机制有关系,也可以把页面设置为不缓存,这样就不用这个参数了。 */var timenow = new Date().getTime(); obj.src="randPic?d="+timenow;
}
</script>
</head><body> <form name="" action="loginWithYZMAction" method="post">用户名<input type="text" name="name" > <br>验证码<input type="text" name="code" > <img src="randPic" οnclick="changeValidateCode(this)" title="点击图片刷新验证码" /> <br /><input type="submit" value="登陆" /><input type="reset" value="重置" /></form>
</body>
</html>
当我们在浏览器上,输入login.jsp的时候,我们其实向服务器发送了两次请求
第一次请求jsp,在浏览器解析jsp(准确的说是html)的时候发现
<img src="randPic" οnclick="changeValidateCode(this)" title="点击图片刷新验证码" /> <br />
然后就第二次向服务器发送了请求。
服务器第一次返回的信息里已经包含了session的id,我们要做的就是记录这个id
然后再向loginWithYZMAction这个action发送请求,当然得带上name,code还有之前得到的sessionid(cookie中保存的东西,除了sessionid,这些东西咱们后面再说)
然后关于验证码的读取,我现在使用的是人工读取,下一个步骤就是引入第三方的接口。
我们看代码说话
package com.zw;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;/** 这个用来测试 bjadmin*/
public class HttpProxyZW {//下面这两个url 第一个是登陆用的地址 第二个是获得验证码的地址private static String urlValidate="http://localhost:8600/BJAdmin/yzm/loginWithYZMAction";private static String urlGetCookieAndValidate="http://localhost:8600/BJAdmin/yzm/randPic";private String cookie = null;/*** 以行为单位读取文件,常用于读面向行的格式化文件*/public static String getYZM(String fileName) {InputStream in = null;try {Thread.sleep(10000);in = new FileInputStream(new File(fileName));} catch (FileNotFoundException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}Scanner s = new Scanner(in);while (s.hasNextLine()) {return s.nextLine();}return null;}public static void main(String[] args) {HttpProxyZW hp = new HttpProxyZW();hp.getPicAndCookie(hp.urlGetCookieAndValidate);List<NameValuePair> params = hp.getParameter();hp.getResponse2(hp.urlValidate, params);} public List<NameValuePair> getParameter(){List<NameValuePair> params=new ArrayList<NameValuePair>();params.add(new BasicNameValuePair("eticketNoORIn","123456"));params.add(new BasicNameValuePair("passengerName_src","啦啦啦"));try {params.add(new BasicNameValuePair("passengerName",URLEncoder.encode("啦啦啦", "utf-8")));} catch (UnsupportedEncodingException e) {e.printStackTrace();}params.add(new BasicNameValuePair("validateFlag","0"));params.add(new BasicNameValuePair("invoiceNo",""));params.add(new BasicNameValuePair("imgSrc","/tsky/images/loading.gif"));params.add(new BasicNameValuePair("eticketNo","123456"));params.add(new BasicNameValuePair("invoiceNo",""));//这个目前比较操蛋//在e盘下 我下载了验证码 //然后人工读出 后把字符写进src/yzm.txtString randCode=getYZM("src/yzm.txt");System.out.println(randCode);params.add(new BasicNameValuePair("code", randCode));return params;}private void downloadJPG(HttpResponse httpResponse) throws IOException {InputStream input = httpResponse.getEntity().getContent(); OutputStream output = new FileOutputStream(new File("E:\\1.jpg")); IOUtils.copy(input, output);if (output != null) {output.close();}output.flush(); }/** 获取第一次下载图片的时候 远程服务器给我发的cookie*/public String getCookie(HttpResponse httpResponse) throws ClientProtocolException, IOException{String cookie="";Header[] headers=httpResponse.getHeaders("Set-Cookie");//BIGipServerpool_ip_port 这个参数是和负载均衡相关的//JSESSIONID 这就是sessionidfor(Header h:headers){if (h.getValue().contains("BIGipServerpool_122")) {String BIGipServerpool=h.getValue().substring("BIGipServerpool_122.119.122.179_80=".length(), h.getValue().indexOf(";"));cookie+="BIGipServerpool_122.119.122.179_80="+BIGipServerpool;}if (h.getValue().contains("JSESSIONID")) {String JSESSIONID=h.getValue().substring("JSESSIONID=".length(), h.getValue().indexOf(";"));cookie+="JSESSIONID="+JSESSIONID;}//这些参数的作用 我不清楚 加上就是了cookie+="Hm_lvt_486e71cc1c3c5d7a07853a6e72364f55=1456716098;__utma=88932958.523101033.1456716098.1456716098.1456716098.1;__utmz=88932958.1456716098.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);CNZZDATA1256052643=1173832624-1456716029-%7C1456884431";}return cookie;}public CloseableHttpResponse getPicAndCookie(String url) {CloseableHttpClient httpclient = HttpClientBuilder.create().build();HttpPost httppost = new HttpPost(url);CloseableHttpResponse response =null;try {response = httpclient.execute(httppost);getCookie(response);downloadJPG(response);} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}httppost.releaseConnection();return response;}public void getResponse2(String url,List<NameValuePair> params) {CloseableHttpClient httpclient = HttpClientBuilder.create().build();HttpPost httppost = new HttpPost(url);httppost.setHeader("Host", "www.travelsky.com");httppost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0");httppost.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");httppost.setHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");httppost.setHeader("Referer", "http://www.travelsky.com/tsky/validate");httppost.setHeader("Cookie", cookie);httppost.setHeader("Connection", "keep-alive");try {if (params != null)httppost.setEntity(new UrlEncodedFormEntity(params, "utf-8"));CloseableHttpResponse response = httpclient.execute(httppost);HttpEntity entity = response.getEntity();String jsonStr = EntityUtils.toString(entity, "utf-8");System.out.println("final result" + jsonStr); httppost.releaseConnection();} catch (Exception e) {e.printStackTrace();}}}
参考资料
Cookie/Session机制详解HttpClient4.x 使用cookie保持会话
HttpClient 解决中文乱码
使用HttpClient时遇到的 java.net.SocketException: Socket closed异常