java - cookie在多线程中过期 [英] java - cookie overried in multi-thread

查看:231
本文介绍了java - cookie在多线程中过期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个WebBot接口,包含getHtmlResult方法发送请求并获取html页面结果:

  import java.util.Date; 

public interface WebBot {
public String getHtmlResult(Date pickedDate)throws Exception;
}

两个实现是WebBotA和WebBotB:
WebBotA:

  import java.io.BufferedReader; 
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service(webBotA)
@Scope(prototype)
public class WebBotA implements WebBot {
String urlHeader =http:// booknow。 jetstar.com;
String urlTailBeforeRedirect =/Search.aspx?culture=vi-VN;
String charset =UTF-8;
String requestMethod =POST;
int readTimeOut = 10000;

@Override
public String getHtmlResult(Date pickedDate)throws Exception {
System.out.println(WebBot A started);

String htmlResult =;

DateFormat df = new SimpleDateFormat(dd);
String pickedDateDay = df.format(pickedDate);

df = new SimpleDateFormat(yyyy-MM);
String pickedDateMonth = df.format(pickedDate);


映射< String,String> requestParams = initRequestParams();
String postParameters =ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListCurrency = VND& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListFareTypes = I& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24
+DropDownListMarketDay1 =+ pickedDateDay
+& ControlGroupSearchView %24AvailabilitySearchInputSearchView%24DropDownListMarketDay2 = 1&安培; ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListMarketDay3 =安培; ControlGroupSearchView%24AvailabilitySearchInputSearchView%24
+DropDownListMarketMonth1 =+ pickedDateMonth
+&放大器; ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListMarketMonth2 = 1968-1&安培; ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListMarketMonth3 =& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24
+DropDownListPassengerType_ADT =+ 1
+& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24
+DropDownListPassengerType_CHD =+ 0
+& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24
+DropDownListPassengerType_INFANT =+ 0
+& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24RadioButtonMarketStructure = OneWay& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24
+TextBoxMarketDestination1 =+HAN
+& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketDestination2 =& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketDestination3 =& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24
+TextBoxMarketOrigin1 =+ SGN
+&放大器; ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketOrigin2 =安培; ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketOrigin3 =安培; ControlGroupSearchView%24ButtonSubmit =安培; __ VIEWSTATE =%2FwEPDwUBMGQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFJ01lbWJlckxvZ2luU2VhcmNoVmlldyRtZW1iZXJfUmVtZW1iZXJtZSDCMtVG%2F1lYc7dy4fVekQjBMvD5与文化= VI-VN和放大器; date_picker =安培; go-booking =& pageToken = sLkmnwXwAsY%3D& ControlGroupSearchView%24AvailabilitySearchInputSearchView%24fromCS = yes;

try {
// Cookie管理器注册表
CookieHandler.setDefault(new CookieManager(null,CookiePolicy.ACCEPT_ALL));

URL obj = new URL(urlHeader + urlTailBeforeRedirect);
HttpURLConnection conn =(HttpURLConnection)obj.openConnection();

//将重定向设置为false
conn.setInstanceFollowRedirects(false);
conn.setReadTimeout(readTimeOut);
conn.setRequestMethod(requestMethod);
for(Map.Entry< String,String> requestParamEntry:requestParams.entrySet()){
conn.setRequestProperty(requestParamEntry.getKey(),requestParamEntry.getValue());
}

//发送请求后
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(postParameters);
wr.flush();
wr.close();

//从location头域获取重定向url
String urlTailAfterRedirect = conn.getHeaderField(Location);

//获取cookie(如果需要),用于登录
String cookies = conn.getHeaderField(Set-Cookie);

//再次打开新连接
conn =(HttpURLConnection)新URL(urlHeader + urlTailAfterRedirect).openConnection();
conn.setRequestProperty(Cookie,cookies);

conn.setReadTimeout(readTimeOut);
conn.setRequestMethod(requestMethod);
for(Map.Entry< String,String> requestParamEntry:requestParams.entrySet()){
conn.setRequestProperty(requestParamEntry.getKey(),requestParamEntry.getValue());
}

conn.setDoOutput(true);
wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(postParameters);
wr.flush();
wr.close();

String inputLine;

InputStream connectionInputStream = conn.getInputStream();
String contentEncoding = conn.getContentEncoding();
if(contentEncoding!= null){
if(contentEncoding.toLowerCase()。contains(gzip)){
connectionInputStream = new GZIPInputStream(connectionInputStream);
}
}
else {
throw new IOException(无法获取内容编码,可能由于Cookie Manager);
}

BufferedReader in = new BufferedReader(new InputStreamReader(connectionInputStream,charset));

StringBuffer html = new StringBuffer();

while((inputLine = in.readLine())!= null){
html.append(inputLine);
}
in.close();

htmlResult = html.toString();

}
catch(IOException e){
System.out.println(e.toString());
}
finally {
}
return htmlResult;
}

private Map< String,String> initRequestParams(){
Map< String,String> requestParams = new HashMap< String,String>();
requestParams.put(User-Agent,Mozilla / 5.0);
requestParams.put(Accept-Language,en-US,en; q = 0.5);
requestParams.put(Content-Type,application / x-www-form-urlencoded);
requestParams.put(Accept-Charset,charset);
requestParams.put(Host,booknow.jetstar.com);
requestParams.put(Referer,http://www.jetstar.com/vn/vi/home);
requestParams.put(Accept,text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8);
requestParams.put(Accept-Encoding,gzip,deflate);
requestParams.put(Connection,keep-alive);
return requestParams;
}
}

WebBotB:


b $ b

  @Service(webBotB)
@Scope(prototype)
public class WebBotB implements WebBot {

String urlNoSessionId =https://ameliaweb5.intelisys.ca/VietJet/ameliapost.aspx?lang=en;
String urlWithSessionId =https://ameliaweb5.intelisys.ca/VIETJET/TravelOptions.aspx?lang=en&st=pb&sesid=;
String charset =UTF-8;
String requestPostMethod =POST;
String requestGetMethod =GET;
int readTimeOut = 10000;

@Override
public String getHtmlResult(Date pickedDate)throws Exception {

System.out.println(WebBot B started);
String htmlResult =;

DateFormat df = new SimpleDateFormat(dd);
String departDayStr = df.format(pickedDate);

df = new SimpleDateFormat(yyyy-MM);
String departMonthStr = df.format(pickingDate).replaceAll( - ,%2F);

日期currentDate = new Date(); $ b $ d df = new SimpleDateFormat(dd);
String currentDayStr = df.format(currentDate);
df = new SimpleDateFormat(yyyy-MM);
String currentMonthStr = df.format(currentDate).replaceAll( - ,%2F);

Map< String,String> requestParams = initRequestParams();
String postParameterRequest1 =chkRoundTrip =&
+lstOrigAP =+SGN
+& lstDestAP =+HAN
+& dlstDepDate_Day =+ departDayStr
+& dlstDepDate_Month =+ departMonthStr
+& dlstRetDate_Day =+ departDayStr
+& dlstRetDate_Month =+ departMonthStr
+& lstCurrency = VND& lstResCurrency = VND& lstDepDateRange = 0& lstRetDateRange = 0&
+txtNumAdults =+ 1
+& txtNumChildren =+ 0
+& txtNumInfants =+ 0
+& lstLvlService = 1& blnFares = False& txtPromoCode =;

字符串postParameterRequest2 =__VIEWSTATE =%2FwEPDwULLTE1MzQ1MjI3MzAPZBYCZg9kFg4CCA8QZGQWAGQCCQ8QZGQWAGQCCw8QZGQWAGQCDQ8QZGQWAGQCEQ8QZGQWAGQCEg8QZGQWAGQCEw8QZGQWAGRkDuhQN17CT5ZIydlFFSt%2BWc8NsCA%3D&放大器; __ VIEWSTATEGENERATOR = BA3C3B49&安培; SesID =安培; DebugID = 62安培; lstOrigAP = -1&安培; lstDestAP = -1&安培;
+dlstDepDate_Day =+ currentDayStr
+& dlstDepDate_Month =+ currentMonthStr
+& lstDepDateRange = 0& dlstRetDate_Day =+ currentDayStr
+& dlstRetDate_Month =+ departMonthStr
+& lstRetDateRange = 0
+& txtNumAdults = 0
+& txtNumChildren = 0
+& txtNumInfants = 0
+& lstLvlService = 1& lstResCurrency = VND& lstCurrency = VND& txtPromoCode =;

try {
CookieHandler.setDefault(null);

//开始第1步
URL objectURLForRequest1_2 = new URL(urlNoSessionId);
HttpURLConnection connection1 =(HttpURLConnection)objectURLForRequest1_2.openConnection();

//将重定向设置为false
connection1.setInstanceFollowRedirects(false);
connection1.setReadTimeout(readTimeOut);
connection1.setRequestMethod(requestPostMethod);
for(Map.Entry< String,String> requestParamEntry:requestParams.entrySet()){
connection1.setRequestProperty(requestParamEntry.getKey(),requestParamEntry.getValue());
}
connection1.setFixedLengthStreamingMode(postParameterRequest1.length());

//发送请求
connection1.setDoOutput(true);
DataOutputStream dataOutputStream = new DataOutputStream(connection1.getOutputStream());
dataOutputStream.writeBytes(postParameterRequest1);
dataOutputStream.flush();
dataOutputStream.close();

String cookieInRequest1String = connection1.getHeaderField(Set-Cookie);

//获取请求的会话ID 3
String sessionIdForRequest3 =;
List< HttpCookie> cookies = HttpCookie.parse(cookieInRequest1String);
for(HttpCookie httpCookie:cookies){
if(httpCookie.getName()。equals(ASP.NET_SessionId))
{
sessionIdForRequest3 = httpCookie.getValue
break;
}
}

//开始第2步
HttpURLConnection connection2 =(HttpURLConnection)objectURLForRequest1_2.openConnection();
//将重定向设置为false
connection2.setInstanceFollowRedirects(false);
connection2.setReadTimeout(readTimeOut);
connection2.setRequestMethod(requestPostMethod);
for(Map.Entry< String,String> requestParamEntry:requestParams.entrySet()){
connection2.setRequestProperty(requestParamEntry.getKey(),requestParamEntry.getValue());
}
connection2.setRequestProperty(Cookie,cookieInRequest1String);
connection2.setFixedLengthStreamingMode(postParameterRequest2.length());

//发送请求
connection2.setDoOutput(true);
dataOutputStream = new DataOutputStream(connection2.getOutputStream());
dataOutputStream.writeBytes(postParameterRequest2);
dataOutputStream.flush();
dataOutputStream.close();

//忽略此connection2.getInputStream将导致Session Expired!
@SuppressWarnings(unused)
InputStream connectionInputStream2 = connection2.getInputStream();

//开始第3步
urlWithSessionId = urlWithSessionId + sessionIdForRequest3;
URL objectURLForRequest3 = new URL(urlWithSessionId);
HttpURLConnection connection3 =(HttpURLConnection)objectURLForRequest3.openConnection();
connection3.setRequestMethod(requestGetMethod);
connection3.setRequestProperty(Cookie,cookieInRequest1String);
for(Map.Entry< String,String> requestParamEntry:requestParams.entrySet()){
connection3.setRequestProperty(requestParamEntry.getKey(),requestParamEntry.getValue());
}

String inputLine;

InputStream connectionInputStream = connection3.getInputStream();
String contentEncoding = connection3.getContentEncoding();
if(connection3.getContentEncoding()!= null){
if(contentEncoding.toLowerCase()。contains(gzip)){
connectionInputStream = new GZIPInputStream(connectionInputStream);
}
if(contentEncoding.toLowerCase()。contains(deflate)){
connectionInputStream = new DeflaterInputStream(connectionInputStream);
}
}

BufferedReader in = new BufferedReader(new InputStreamReader(connectionInputStream,charset));

StringBuffer html = new StringBuffer();

while((inputLine = in.readLine())!= null){
html.append(inputLine);
}
in.close();

htmlResult = html.toString();

}
catch(IOException e){
System.out.println(e.toString());
}
finally {
}
return htmlResult;
}

private Map< String,String> initRequestParams(){
Map< String,String> requestParams = new HashMap< String,String>();
requestParams.put(User-Agent,Mozilla / 5.0(Windows NT 6.1; Win64; x64)AppleWebKit / 537.36(KHTML,像Gecko)Chrome / 43.0.2329.0 Safari / 537.36
requestParams.put(Accept-Language,en-US,en; q = 0.5);
requestParams.put(Content-Type,application / x-www-form-urlencoded);
requestParams.put(Accept-Charset,charset);
requestParams.put(Host,ameliaweb5.intelisys.ca);
requestParams.put(Referer,https://ameliaweb5.intelisys.ca/VietJet/ameliapost.aspx?lang=vi);
requestParams.put(Accept,text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8);
requestParams.put(Accept-Encoding,gzip,deflate);
requestParams.put(Connection,keep-alive);
return requestParams;
}
}


$ b $ p我使用WebBotThread.java来实现Runnable运行多个线程:

  import java.util.Date; 

export org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import core.WebBot;
import core.WebBotA;
import core.WebBotB;

@Component(webBotThread)
@Scope(prototype)
public class WebBotThread implements Runnable {
@Autowired
AutowireCapableBeanFactory factory;

private Date pickedDate;
private int webBotType;

public WebBotThread(){}

@Override
public void run(){
WebBot webBot = null;
if(webBotType == 1)
{
webBot =(WebBotA)factory.getBean(webBotA);
}
else {
webBot =(WebBotB)factory.getBean(webBotB);
}

try {
webBot.getHtmlResult(pickedDate);
if(webBotType == 1)
System.out.println(WebBotA finished successfully);
else
System.out.println(WebBotB finished successfully);
} catch(Exception e){
if(webBotType == 1)
System.out.println(WebBotA failed:+ e.toString());
else
System.out.println(WebBotB failed:+ e.toString());
}
}

public Date getPickedDate(){
return pickedDate;
}

public void setPickedDate(Date pickedDate){
this.pickedDate = pickedDate;
}

public int getWebBotType(){
return webBotType;
}

public void setWebBotType(int webBotType){
this.webBotType = webBotType;
}

}

我的Main.java类:

  import java.util.Calendar; 
import java.util.Date;

import org.springframework.context.ApplicationContext;
export org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTask​​Executor;

public class Main {

public static void main(String [] args){
try {
@SuppressWarnings(resource)
ApplicationContext context = new ClassPathXmlApplicationContext(classpath:spring / applicationContext.xml);

日历cal = Calendar.getInstance();
cal.set(Calendar.YEAR,2015);
cal.set(Calendar.MONTH,Calendar.APRIL);
cal.set(Calendar.DAY_OF_MONTH,30);
Date receivedDate = cal.getTime();

ThreadPoolTask​​Executor threadPoolTask​​Executor =(ThreadPoolTask​​Executor)context.getBean(ticketFinderBoExecutor);

WebBotThread wbThreadA = context.getBean(WebBotThread.class);
wbThreadA.setWebBotType(1);
wbThreadA.setPickedDate(pickedDate);

WebBotThread wbThreadB = context.getBean(WebBotThread.class);
wbThreadB.setWebBotType(2);
wbThreadB.setPickedDate(pickedDate);

threadPoolTask​​Executor.execute(wbThreadA);
threadPoolTask​​Executor.execute(wbThreadB);
} catch(Exception e){
e.printStackTrace();
}
}

}

-thread.xml设置:

 <?xml version =1.0encoding =UTF-8?& 
< bean xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instancexmlns :aop =http://www.springframework.org/schema/aop
xmlns:tx =http://www.springframework.org/schema/txxmlns:context =http:// www.springframework.org/schema/context
xsi:schemaLocation =
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/ spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http ://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
default-autowire =byName>

< bean id =ticketFinderBoExecutor
class =org.springframework.scheduling.concurrent.ThreadPoolTask​​Executor>
< property name =corePoolSizevalue =2/>
< property name =maxPoolSizevalue =2/>
< property name =WaitForTasksToCompleteOnShutdownvalue =true/>
< / bean>
< / beans>

我的applicationContext.xml

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instancexmlns :aop =http://www.springframework.org/schema/aop
xmlns:tx =http://www.springframework.org/schema/txxmlns:context =http:// www.springframework.org/schema/context
xsi:schemaLocation =
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/ spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http ://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
default-autowire =byName>
< context:spring-configured />

< import resource =applicationContext-thread.xml/>

<! - 声明注释 - >
< context:annotation-config />

<! - 声明事务管理器 - >
< tx:annotation-driven />

<! - 自动扫描Bean到Spring容器 - >
< context:component-scan
base-package =core
,helper
,thread/>
< / beans>

我的问题是,当我在applicationContext-thread.xml中只设置了一个线程池时,两个WebBotA和WebBotB运行确定。但是,当我设置2个线程池以并发运行WebBotA和WebBotB时,两个WebBot实现之一将得到异常。
我发现这个主题 Wurstbro 可能有与我相同的问题,但是,我也失败,当应用他的解决方案到我的上下文。
我研究了很多,但仍然没有找到我的问题的解决方案。
请帮助我,非常感谢。



P / s:原谅我,我的英语不好。

解决方案

您在URL实例上调用openConnection。这将返回一个HttpUrlConnection实例。



缺省Java将通过标准UrlStreamHandlerFactory创建一个UrlStreamHandler一次。这意味着,如果你的应用程序使用多个UrlConnection,它总是使用相同的UrlStreamHandler。



如何修复?



或者,您可以创建自己的UrlStreamHandlerFactory强制的东西与ThreadLocals为了有不同的cookie。对我来说似乎不容易。



或者你切换到另一个库来处理URL。我鼓励使用HttpClient从Apache Http客户端库。如果你实例化2 HttpClient,他们不会共享cookie。



正如我看到你正在使用Spring框架,你肯定不会有问题使用Apache Http客户端库。



注意,如果你坚持实施它!


The problem is that the cookie has been override when using multiple threads.

I have a WebBot interface that contains getHtmlResult method to sent request and get html page result:

import java.util.Date;

public interface WebBot {
    public String getHtmlResult(Date pickedDate) throws Exception;
}

Two implement are WebBotA and WebBotB: WebBotA:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

@Service("webBotA")
@Scope("prototype")
public class WebBotA implements WebBot{
    String urlHeader = "http://booknow.jetstar.com";
    String urlTailBeforeRedirect = "/Search.aspx?culture=vi-VN";
    String charset = "UTF-8";
    String requestMethod = "POST";
    int readTimeOut = 10000;

    @Override
    public String getHtmlResult(Date pickedDate) throws Exception {
        System.out.println("WebBot A started");

        String htmlResult = "";

        DateFormat df = new SimpleDateFormat("dd");
        String pickedDateDay = df.format(pickedDate);

        df = new SimpleDateFormat("yyyy-MM");
        String pickedDateMonth = df.format(pickedDate);


        Map<String, String> requestParams = initRequestParams();
        String postParameters = "ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListCurrency=VND&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListFareTypes=I&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24"
                + "DropDownListMarketDay1=" + pickedDateDay
                + "&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListMarketDay2=1&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListMarketDay3=&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24"
                + "DropDownListMarketMonth1=" + pickedDateMonth
                + "&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListMarketMonth2=1968-1&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24DropDownListMarketMonth3=&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24"
                + "DropDownListPassengerType_ADT=" + 1
                + "&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24"
                + "DropDownListPassengerType_CHD=" + 0
                + "&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24"
                + "DropDownListPassengerType_INFANT=" + 0
                + "&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24RadioButtonMarketStructure=OneWay&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24"
                + "TextBoxMarketDestination1=" + "HAN"
                + "&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketDestination2=&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketDestination3=&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24"
                + "TextBoxMarketOrigin1=" + "SGN"
                + "&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketOrigin2=&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24TextBoxMarketOrigin3=&ControlGroupSearchView%24ButtonSubmit=&__VIEWSTATE=%2FwEPDwUBMGQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFJ01lbWJlckxvZ2luU2VhcmNoVmlldyRtZW1iZXJfUmVtZW1iZXJtZSDCMtVG%2F1lYc7dy4fVekQjBMvD5&culture=vi-VN&date_picker=&go-booking=&pageToken=sLkmnwXwAsY%3D&ControlGroupSearchView%24AvailabilitySearchInputSearchView%24fromCS=yes";

            try {
                // Cookie manager registry
                CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

                URL obj = new URL(urlHeader + urlTailBeforeRedirect);
                HttpURLConnection conn = (HttpURLConnection) obj.openConnection();

                // Set redirect to false
                conn.setInstanceFollowRedirects(false);
                conn.setReadTimeout(readTimeOut);
                conn.setRequestMethod(requestMethod);
                for (Map.Entry<String, String> requestParamEntry : requestParams.entrySet()) {
                    conn.setRequestProperty(requestParamEntry.getKey(), requestParamEntry.getValue());
                }

                // Send post request
                conn.setDoOutput(true);
                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
                wr.writeBytes(postParameters);
                wr.flush();
                wr.close();

                // get redirect url from "location" header field
                String urlTailAfterRedirect = conn.getHeaderField("Location");

                // get the cookie if need, for login
                String cookies = conn.getHeaderField("Set-Cookie");

                // open the new connnection again
                conn = (HttpURLConnection) new URL(urlHeader + urlTailAfterRedirect).openConnection();
                conn.setRequestProperty("Cookie", cookies);

                conn.setReadTimeout(readTimeOut);
                conn.setRequestMethod(requestMethod);
                for (Map.Entry<String, String> requestParamEntry : requestParams.entrySet()) {
                    conn.setRequestProperty(requestParamEntry.getKey(), requestParamEntry.getValue());
                }

                conn.setDoOutput(true);
                wr = new DataOutputStream(conn.getOutputStream());
                wr.writeBytes(postParameters);
                wr.flush();
                wr.close();

                String inputLine;

                InputStream connectionInputStream = conn.getInputStream();
                String contentEncoding = conn.getContentEncoding();
                if(contentEncoding != null){
                    if (contentEncoding.toLowerCase().contains("gzip")) {
                        connectionInputStream = new GZIPInputStream(connectionInputStream);
                    }   
                }
                else{
                    throw new IOException("Failed to get Content Encoding. May by cause Cookie Manager");
                }

                BufferedReader in = new BufferedReader(new InputStreamReader(connectionInputStream, charset));

                StringBuffer html = new StringBuffer();

                while ((inputLine = in.readLine()) != null) {
                    html.append(inputLine);
                }
                in.close();

                htmlResult =html.toString();

            }
            catch (IOException e) {
                System.out.println(e.toString());
            }
            finally{
            }
            return htmlResult;
        }

    private Map<String, String> initRequestParams(){
        Map<String, String> requestParams = new HashMap<String, String>();
        requestParams.put("User-Agent", "Mozilla/5.0");
        requestParams.put("Accept-Language", "en-US,en;q=0.5");
        requestParams.put("Content-Type", "application/x-www-form-urlencoded");
        requestParams.put("Accept-Charset", charset);
        requestParams.put("Host", "booknow.jetstar.com");
        requestParams.put("Referer", "http://www.jetstar.com/vn/vi/home");
        requestParams.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        requestParams.put("Accept-Encoding", "gzip, deflate");
        requestParams.put("Connection", "keep-alive");
        return requestParams;
    }
}

WebBotB:

@Service("webBotB")
@Scope("prototype")
public class WebBotB implements WebBot{

    String urlNoSessionId = "https://ameliaweb5.intelisys.ca/VietJet/ameliapost.aspx?lang=en";
    String urlWithSessionId = "https://ameliaweb5.intelisys.ca/VIETJET/TravelOptions.aspx?lang=en&st=pb&sesid=";
    String charset = "UTF-8";
    String requestPostMethod = "POST";
    String requestGetMethod = "GET";
    int readTimeOut = 10000;

    @Override
    public String getHtmlResult(Date pickedDate) throws Exception {

        System.out.println("WebBot B started");
        String htmlResult = "";

        DateFormat df = new SimpleDateFormat("dd");
        String departDayStr = df.format(pickedDate);

        df = new SimpleDateFormat("yyyy-MM");
        String departMonthStr = df.format(pickedDate).replaceAll("-", "%2F");

        Date currentDate = new Date();
        df = new SimpleDateFormat("dd");
        String currentDayStr = df.format(currentDate);
        df = new SimpleDateFormat("yyyy-MM");
        String currentMonthStr = df.format(currentDate).replaceAll("-", "%2F");

        Map<String, String> requestParams = initRequestParams();
        String postParameterRequest1 = "chkRoundTrip=&"
                + "lstOrigAP=" + "SGN"
                + "&lstDestAP=" + "HAN"
                + "&dlstDepDate_Day=" + departDayStr
                + "&dlstDepDate_Month=" + departMonthStr
                + "&dlstRetDate_Day=" + departDayStr
                + "&dlstRetDate_Month=" + departMonthStr
                + "&lstCurrency=VND&lstResCurrency=VND&lstDepDateRange=0&lstRetDateRange=0&"
                + "txtNumAdults=" + 1
                + "&txtNumChildren=" + 0
                + "&txtNumInfants=" + 0
                + "&lstLvlService=1&blnFares=False&txtPromoCode=";

        String postParameterRequest2 = "__VIEWSTATE=%2FwEPDwULLTE1MzQ1MjI3MzAPZBYCZg9kFg4CCA8QZGQWAGQCCQ8QZGQWAGQCCw8QZGQWAGQCDQ8QZGQWAGQCEQ8QZGQWAGQCEg8QZGQWAGQCEw8QZGQWAGRkDuhQN17CT5ZIydlFFSt%2BWc8NsCA%3D&__VIEWSTATEGENERATOR=BA3C3B49&SesID=&DebugID=62&lstOrigAP=-1&lstDestAP=-1&"
                + "dlstDepDate_Day=" + currentDayStr
                + "&dlstDepDate_Month=" + currentMonthStr
                + "&lstDepDateRange=0&dlstRetDate_Day=" + currentDayStr
                + "&dlstRetDate_Month=" + departMonthStr
                + "&lstRetDateRange=0"
                + "&txtNumAdults=0"
                + "&txtNumChildren=0"
                + "&txtNumInfants=0"
                + "&lstLvlService=1&lstResCurrency=VND&lstCurrency=VND&txtPromoCode=";

        try{
            CookieHandler.setDefault(null);

            // Begin step 1
            URL objectURLForRequest1_2 = new URL(urlNoSessionId);
            HttpURLConnection connection1 = (HttpURLConnection) objectURLForRequest1_2.openConnection();

            // Set redirect to false
            connection1.setInstanceFollowRedirects(false);
            connection1.setReadTimeout(readTimeOut);
            connection1.setRequestMethod(requestPostMethod);
            for (Map.Entry<String, String> requestParamEntry : requestParams.entrySet()) {
                connection1.setRequestProperty(requestParamEntry.getKey(), requestParamEntry.getValue());
            }
            connection1.setFixedLengthStreamingMode(postParameterRequest1.length());

            // Send post request
            connection1.setDoOutput(true);
            DataOutputStream dataOutputStream = new DataOutputStream(connection1.getOutputStream());
            dataOutputStream.writeBytes(postParameterRequest1);
            dataOutputStream.flush();
            dataOutputStream.close();

            String cookieInRequest1String = connection1.getHeaderField("Set-Cookie");

            // Get session id for request 3
            String sessionIdForRequest3 = "";
            List<HttpCookie> cookies = HttpCookie.parse(cookieInRequest1String);
            for (HttpCookie httpCookie : cookies) {
                if (httpCookie.getName().equals("ASP.NET_SessionId"))
                {
                    sessionIdForRequest3 = httpCookie.getValue();
                    break;
                }
            }

            // Begin step 2
            HttpURLConnection connection2 = (HttpURLConnection) objectURLForRequest1_2.openConnection();
            // Set redirect to false
            connection2.setInstanceFollowRedirects(false);
            connection2.setReadTimeout(readTimeOut);
            connection2.setRequestMethod(requestPostMethod);
            for (Map.Entry<String, String> requestParamEntry : requestParams.entrySet()) {
                connection2.setRequestProperty(requestParamEntry.getKey(), requestParamEntry.getValue());
            }
            connection2.setRequestProperty("Cookie", cookieInRequest1String);
            connection2.setFixedLengthStreamingMode(postParameterRequest2.length());

            // Send post request
            connection2.setDoOutput(true);
            dataOutputStream = new DataOutputStream(connection2.getOutputStream());
            dataOutputStream.writeBytes(postParameterRequest2);
            dataOutputStream.flush();
            dataOutputStream.close();

            // Ommit this connection2.getInputStream will lead to Session Expired !
            @SuppressWarnings("unused")
            InputStream connectionInputStream2 = connection2.getInputStream();

            // Begin step 3
            urlWithSessionId = urlWithSessionId + sessionIdForRequest3;
            URL objectURLForRequest3 = new URL(urlWithSessionId);
            HttpURLConnection connection3 = (HttpURLConnection) objectURLForRequest3.openConnection();
            connection3.setRequestMethod(requestGetMethod);
            connection3.setRequestProperty("Cookie", cookieInRequest1String);
            for (Map.Entry<String, String> requestParamEntry : requestParams.entrySet()) {
                connection3.setRequestProperty(requestParamEntry.getKey(), requestParamEntry.getValue());
            }

            String inputLine;

            InputStream connectionInputStream = connection3.getInputStream();
            String contentEncoding = connection3.getContentEncoding();
            if (connection3.getContentEncoding() != null){
                if (contentEncoding.toLowerCase().contains("gzip")) {
                    connectionInputStream = new GZIPInputStream(connectionInputStream);
                }
                if (contentEncoding.toLowerCase().contains("deflate")){
                    connectionInputStream = new DeflaterInputStream(connectionInputStream);
                }
            }

            BufferedReader in = new BufferedReader(new InputStreamReader(connectionInputStream, charset));

            StringBuffer html = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                html.append(inputLine);
            }
            in.close();

            htmlResult = html.toString();

        }
        catch (IOException e) {
            System.out.println(e.toString());
        }
        finally{
        }
        return htmlResult;
    }

    private Map<String, String> initRequestParams(){
        Map<String, String> requestParams = new HashMap<String, String>();
        requestParams.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2329.0 Safari/537.36");
        requestParams.put("Accept-Language", "en-US,en;q=0.5");
        requestParams.put("Content-Type", "application/x-www-form-urlencoded");
        requestParams.put("Accept-Charset", charset);
        requestParams.put("Host", "ameliaweb5.intelisys.ca");
        requestParams.put("Referer", "https://ameliaweb5.intelisys.ca/VietJet/ameliapost.aspx?lang=vi");
        requestParams.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        requestParams.put("Accept-Encoding", "gzip, deflate");
        requestParams.put("Connection", "keep-alive");
        return requestParams;
    }
}

I uses WebBotThread.java that implements Runnable to run multiple threads:

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import core.WebBot;
import core.WebBotA;
import core.WebBotB;

@Component("webBotThread")
@Scope("prototype")
public class WebBotThread implements Runnable{
    @Autowired 
    AutowireCapableBeanFactory factory;

    private Date pickedDate;
    private int webBotType;

    public WebBotThread(){}

    @Override
    public void run() {
        WebBot webBot = null;
        if (webBotType == 1)
        {
            webBot = (WebBotA)factory.getBean("webBotA");
        }
        else{
            webBot = (WebBotB)factory.getBean("webBotB");
        }

        try {
            webBot.getHtmlResult(pickedDate);
            if(webBotType == 1)
                System.out.println("WebBotA finished successfully");
            else
                System.out.println("WebBotB finished successfully");
        } catch (Exception e) {
            if(webBotType == 1)
                System.out.println("WebBotA failed: " + e.toString());
            else
                System.out.println("WebBotB failed: " + e.toString());
        }
    }

    public Date getPickedDate() {
        return pickedDate;
    }

    public void setPickedDate(Date pickedDate) {
        this.pickedDate = pickedDate;
    }

    public int getWebBotType() {
        return webBotType;
    }

    public void setWebBotType(int webBotType) {
        this.webBotType = webBotType;
    }

}

My Main.java class:

import java.util.Calendar;
import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

public class Main {

    public static void main(String[] args) {
        try {
            @SuppressWarnings("resource")
            ApplicationContext context = new ClassPathXmlApplicationContext( "classpath:spring/applicationContext.xml");

            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR, 2015);
            cal.set(Calendar.MONTH, Calendar.APRIL);
            cal.set(Calendar.DAY_OF_MONTH, 30);
            Date pickedDate = cal.getTime();

            ThreadPoolTaskExecutor threadPoolTaskExecutor = (ThreadPoolTaskExecutor) context.getBean("ticketFinderBoExecutor");

            WebBotThread wbThreadA = context.getBean(WebBotThread.class);
            wbThreadA.setWebBotType(1);
            wbThreadA.setPickedDate(pickedDate);

            WebBotThread wbThreadB = context.getBean(WebBotThread.class);
            wbThreadB.setWebBotType(2);
            wbThreadB.setPickedDate(pickedDate);

            threadPoolTaskExecutor.execute(wbThreadA);
            threadPoolTaskExecutor.execute(wbThreadB);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

My applicationContext-thread.xml settings:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"
    default-autowire="byName">

    <bean id="ticketFinderBoExecutor"
        class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="2" />
        <property name="maxPoolSize" value="2" />
        <property name="WaitForTasksToCompleteOnShutdown" value="true" />
    </bean>
</beans>

My applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"
    default-autowire="byName">
    <context:spring-configured/>

    <import resource="applicationContext-thread.xml" />

    <!-- Declare for annotation -->
    <context:annotation-config />

    <!-- Declare for transaction manager -->
    <tx:annotation-driven />

    <!-- Auto scan Beans to Spring container -->
    <context:component-scan
        base-package="core
                    , helper
                    , thread" />
</beans>

And my problem is that when I set only 1 thread pool in applicationContext-thread.xml, two WebBotA and WebBotB run OK. However, when I set 2 thread pool to run WebBotA and WebBotB concurrently, one of the two WebBot implements will be got exception. I found this topic of Wurstbro maybe have the same problem with me, however, I also failed when applied his solution to my context. I've researched a lot but still not find a solution for my problem. Please help me and thanks a lot.

P/s: Forgive me, my English is not good.

解决方案

You call the openConnection on a URL instance. This is returning you a HttpUrlConnection instance.

Default Java will create a UrlStreamHandler through the standard UrlStreamHandlerFactory only once. This means, if your application uses multiple UrlConnection, it is always using the same UrlStreamHandler. That's the reason why your cookies are shared.

How to fix?

Or you create your own UrlStreamHandlerFactory and force something with ThreadLocals in order to have different cookies. Doesn't seem easy to me.

Or you switch to another library to deal with URLs. I encourage to use HttpClient from Apache Http Client library. If you instantiate 2 HttpClient, they won't share the cookies.

As I see you are using the Spring Framework, you definitely won't have problems to use the Apache Http Client library.

Shout if you get stuck implementing it!

这篇关于java - cookie在多线程中过期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆