2015-04-15 8 views
1

Я довольно новичок в программировании на Android и недавно получил успешный HTTP-запрос, только чтобы узнать, что мои файлы cookie не хранятся между последующими сообщениями Post/Get. Я посмотрел на interweb и нашел несколько примеров для Android-клиента Android и HttpURLConnection от Java. Мне не удалось реализовать какой-либо метод в моем текущем классе, поэтому мне было интересно, сможет ли кто-то с большим опытом просматривать мой код и предлагать предложения.Управление файлами cookie с Java URLConnection

Резюме:

  1. Мой первоначальный запрос POST успешно и аутентификации.
  2. Мой второй запрос POST не сохраняет файлы cookie из первоначального запроса POST.
  3. Есть ли какой-либо конкретный пример или причина, почему кто-то может выбрать метод Apache или реализацию Java? Оба равны в своем собственном праве или же они предлагают больше возможностей и гибкости, чем другие?

Любая помощь приветствуется, благодарю вас.

webCreate.java

import android.util.Log; 

import java.io.BufferedReader; 
import java.io.DataOutputStream; 
import java.io.InputStreamReader; 
import java.net.CookieHandler; 
import java.net.CookieManager; 
import java.net.HttpCookie; 
import java.net.HttpURLConnection; 
import java.net.URL; 

import javax.net.ssl.HttpsURLConnection; 

public class webCreate { 

    private final String USER_AGENT = "Mozilla/5.0"; 


    // HTTP GET request 
    public void sendGet(String url) throws Exception { 

     CookieManager cookieManager = new CookieManager(); 
     CookieHandler.setDefault(cookieManager); 
     HttpCookie cookie = new HttpCookie("lang", "en"); 


     URL obj = new URL(url); 
     HttpURLConnection con = (HttpURLConnection) obj.openConnection(); 

     // optional default is GET 
     con.setRequestMethod("GET"); 

     //add request header 
     con.setRequestProperty("User-Agent", USER_AGENT); 

     int responseCode = con.getResponseCode(); 
     Log.d("sendGet", "\nSending 'GET' request to URL : " + url); 


     BufferedReader in = new BufferedReader(
       new InputStreamReader(con.getInputStream())); 
     String inputLine; 
     StringBuffer response = new StringBuffer(); 


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

     in.close(); 

     //print result 
     System.out.println(response.toString()); 
     Log.d("Response Code", response.toString()); 
    } 

    // HTTP POST request 
    String sendPost(String url, String urlParams) throws Exception { 

     CookieManager cookieManager = new CookieManager(); 
     CookieHandler.setDefault(cookieManager); 
     HttpCookie cookie = new HttpCookie("lang", "en"); 

     URL obj = new URL(url); 
     HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(); 

     //add request header 
     con.setRequestMethod("POST"); 
     con.setRequestProperty("User-Agent", USER_AGENT); 
     con.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); 

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

     int responseCode = con.getResponseCode(); 
     System.out.println("\nSending 'POST' request to URL : " + url); 
     System.out.println("Post parameters : " + urlParams); 
     System.out.println("Response Code : " + responseCode); 

     BufferedReader in = new BufferedReader(
       new InputStreamReader(con.getInputStream())); 
     String inputLine; 
     StringBuffer response = new StringBuffer(); 

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

     System.out.println("Response Code : " + response); 
     return response.toString(); 
    } 

} 

ответ

5

Вы должны поддерживать ваш контекст печенье внешним для каждого вызова и обеспечить то же печенье хранить его на последующем GETs и должностей. Это то же самое для реализации Java и реализации Apache.

По моему опыту, Apache's HTTP components лучше, чем встроенная реализация Java. Я потратил много времени на то, чтобы написать утилиту с использованием реализации Java, моей самой большой проблемой были тайм-ауты. Плохие веб-серверы будут зависать, что приведет к зависанию соединения бесконечно. После перехода на Apache таймауты были настраиваемыми, и у нас не было больше зависающих потоков.


Приведу пример, используя Apache.

Создать экземпляр CookieStore в вашем родительском методе:

CookieStore cookieStore = new BasicCookieStore(); 

Затем в GET или POST реализациях передать в экземпляр CookieStore и использовать его при построении HttpClient:

public void sendGet(String url, CookieStore cookieStore) throws Exception { 
    ... 
    HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build(); 

    HttpGet request = new HttpGet(uri); // or HttpPost... 
    request.addHeader("User-Agent", USER_AGENT); 
    HttpResponse response = client.execute(request); 

    BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 
    ... 
} 

Android расширил java.net.HttpURLConnection и рекомендует использовать его, поэтому я также дам план для этого.

HttpURLConnection и HttpsURLConnection автоматически и прозрачно использует CookieManager, установленный в CookieHandler. CookieHandler - VM-wide, поэтому должен быть установлен. Если вы создаете новый CookieManager для каждого запроса, как и в вашем коде, он уничтожит все файлы cookie, установленные в предыдущих запросах.

Вам не нужно создавать экземпляр HttpCookie самостоятельно. Когда HttpURLConnection получает cookie с сервера, CookieManager получит куки-файл и сохранит его. Будущие запросы на тот же сервер автоматически отправят ранее установленные файлы cookie.

Таким образом, перенести этот код в вашей установке приложения, так это происходит только один раз:

CookieManager cookieManager = new CookieManager(); 
CookieHandler.setDefault(cookieManager); 
+0

Спасибо за ответ, у меня не было возможности проверить код. Я просмотрел ваши отзывы и поднял еще один вопрос, который вы можете или не можете решить. Используя ваш пример и предполагая, что sendGet также является именем вашего класса: sendGet webReq = new sendGet(); webReq.sendGet ("www.google.com", файл cookie); Если бы я отправил второй webReq.sendGet, почему куки должны быть отправлены во второй раз, если был только один новый экземпляр класса sendGet? Надеюсь, этот вопрос имеет смысл. В этом текстовом поле было немного сложно форматировать. – snapplex

+0

'sendGet' - это имя метода, а не имя класса. Вы можете сохранить ссылку на «CookieStore» в своем классе, если хотите. Однако независимо от того, каждый раз, когда вы создаете новый экземпляр «HttpClient», вы должны предоставить тот же экземпляр «CookieStore», который вы использовали в предыдущих запросах на тот же сайт. – MCToon

+0

О, ладно. Я надеялся, что ваш пример будет работать, но Android-студия отказывается признать «HttpClientBuilder», он сделал рефакторинг HttpClient. – snapplex

Смежные вопросы