我一樣的問題。這裏是我的解決方案:
首先,我以和你一樣的方式處理SSL(我使用Bob Lee的方法)。
餅乾是一個不同的故事。過去沒有RestTemplate(即直接使用Apache的HttpClient類)處理Cookie的方式是將HttpContext的實例傳遞給HttpClient的execute方法。讓我們退後一步......
的HttpClient有許多重載execute方法,其中之一是:
execute(HttpUriRequest request, HttpContext context)
的HttpContext的實例可以有一個的CookieStore的參考。當您創建的HttpContext的實例,提供的CookieStore(無論是從以前的請求保存的一個新的,或一個):
private HttpContext createHttpContext() {
CookieStore cookieStore = (CookieStore) StaticCacheHelper.retrieveObjectFromCache(COOKIE_STORE);
if (cookieStore == null) {
Log.d(getClass().getSimpleName(), "Creating new instance of a CookieStore");
// Create a local instance of cookie store
cookieStore = new BasicCookieStore();
}
// Create local HTTP context
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
return localContext;
}
當然,你也可以發送請求之前添加餅乾的CookieStore實例如果你喜歡。現在,當你調用execute方法,使用的HttpContext的該實例:
HttpResponse response = httpClient.execute(httpRequester, localContext);
(其中httpRequester是HttpPost,HTTPGET等實例)
如果您需要重新發送在後續請求中的任何cookie,請確保您存儲的cookie的地方:
StaticCacheHelper.storeObjectInCache(COOKIE_STORE, localContext.getAttribute(ClientContext.COOKIE_STORE), MAX_MILLISECONDS_TO_LIVE_IN_CACHE);
是在這段代碼中使用的StaticCacheHelper類僅僅是可以將數據存儲在自定義類靜態地圖:
public class StaticCacheHelper {
private static final int TIME_TO_LIVE = 43200000; // 12 hours
private static Map<String, Element> cacheMap = new HashMap<String, Element>();
/**
* Retrieves an item from the cache. If found, the method compares
* the object's expiration date to the current time and only returns
* the object if the expiration date has not passed.
*
* @param cacheKey
* @return
*/
public static Object retrieveObjectFromCache(String cacheKey) {
Element e = cacheMap.get(cacheKey);
Object o = null;
if (e != null) {
Date now = new Date();
if (e.getExpirationDate().after(now)) {
o = e.getObject();
} else {
removeCacheItem(cacheKey);
}
}
return o;
}
/**
* Stores an object in the cache, wrapped by an Element object.
* The Element object has an expiration date, which will be set to
* now + this class' TIME_TO_LIVE setting.
*
* @param cacheKey
* @param object
*/
public static void storeObjectInCache(String cacheKey, Object object) {
Date expirationDate = new Date(System.currentTimeMillis() + TIME_TO_LIVE);
Element e = new Element(object, expirationDate);
cacheMap.put(cacheKey, e);
}
/**
* Stores an object in the cache, wrapped by an Element object.
* The Element object has an expiration date, which will be set to
* now + the timeToLiveInMilliseconds value that is passed into the method.
*
* @param cacheKey
* @param object
* @param timeToLiveInMilliseconds
*/
public static void storeObjectInCache(String cacheKey, Object object, int timeToLiveInMilliseconds) {
Date expirationDate = new Date(System.currentTimeMillis() + timeToLiveInMilliseconds);
Element e = new Element(object, expirationDate);
cacheMap.put(cacheKey, e);
}
public static void removeCacheItem(String cacheKey) {
cacheMap.remove(cacheKey);
}
public static void clearCache() {
cacheMap.clear();
}
static class Element {
private Object object;
private Date expirationDate;
/**
* @param object
* @param key
* @param expirationDate
*/
private Element(Object object, Date expirationDate) {
super();
this.object = object;
this.expirationDate = expirationDate;
}
/**
* @return the object
*/
public Object getObject() {
return object;
}
/**
* @param object the object to set
*/
public void setObject(Object object) {
this.object = object;
}
/**
* @return the expirationDate
*/
public Date getExpirationDate() {
return expirationDate;
}
/**
* @param expirationDate the expirationDate to set
*/
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
}
}
但!!!!截至01年12月Spring中的RestTemplate Android不允許您添加HttpContext來執行請求!這在Spring Framework 3.1.0.RELEASE中得到修復,修復程序爲scheduled to be migrated into Spring Android 1.0.0.RC1。
因此,當我們獲得Spring Android 1.0.0.RC1時,我們應該能夠添加上述示例中描述的上下文。在此之前,我們必須使用ClientHttpRequestInterceptor從請求/響應頭中添加/拉取Cookie。
public class MyClientHttpRequestInterceptor implements
ClientHttpRequestInterceptor {
private static final String SET_COOKIE = "set-cookie";
private static final String COOKIE = "cookie";
private static final String COOKIE_STORE = "cookieStore";
/* (non-Javadoc)
* @see org.springframework.http.client.ClientHttpRequestInterceptor#intercept(org.springframework.http.HttpRequest, byte[], org.springframework.http.client.ClientHttpRequestExecution)
*/
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] byteArray,
ClientHttpRequestExecution execution) throws IOException {
Log.d(getClass().getSimpleName(), ">>> entering intercept");
List<String> cookies = request.getHeaders().get(COOKIE);
// if the header doesn't exist, add any existing, saved cookies
if (cookies == null) {
List<String> cookieStore = (List<String>) StaticCacheHelper.retrieveObjectFromCache(COOKIE_STORE);
// if we have stored cookies, add them to the headers
if (cookieStore != null) {
for (String cookie : cookieStore) {
request.getHeaders().add(COOKIE, cookie);
}
}
}
// execute the request
ClientHttpResponse response = execution.execute(request, byteArray);
// pull any cookies off and store them
cookies = response.getHeaders().get(SET_COOKIE);
if (cookies != null) {
for (String cookie : cookies) {
Log.d(getClass().getSimpleName(), ">>> response cookie = " + cookie);
}
StaticCacheHelper.storeObjectInCache(COOKIE_STORE, cookies);
}
Log.d(getClass().getSimpleName(), ">>> leaving intercept");
return response;
}
}
的截擊機攔截請求,看在高速緩存,看看是否有任何cookie添加到請求,然後執行請求,然後再換任何cookie關閉的響應,並將其存儲以備將來使用。
攔截器添加到請求模板:
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClientHelper.createDefaultHttpClient(GET_SERVICE_URL)));
ClientHttpRequestInterceptor[] interceptors = {new MyClientHttpRequestInterceptor()};
restTemplate.setInterceptors(interceptors);
而且你去那裏!我已經測試過它,它的工作原理。這應該讓你一直持續到Spring Android 1.0.0.RC1,直到我們可以直接使用HttpContext和RestTemplate。
希望這可以幫助別人!
感謝您的HttpUtils鏈接!絕望的解決SSL和其他提示沒有幫助。 – Solata