The directory structure is as follows:
Encapsulation of the Http protocol:
There are two main domains using the HTTP protocol: request and response. Below is the structure diagram of the Http protocol encapsulation
(1) HttpRequestInter.java: As a request domain object, the address of the client request and the httpRequest object should be available so that information such as the parameters of the client request can be obtained; in addition, public HttpResponseInter request() throws Exception; this method is used after the request request request has been executed, returns a response object (represented here by an interface)
/** * Requested Interface* @author xuliugen */ public interface HttpRequestInter { //Get httpRequest public HttpUriRequest getHttpRequest(); //Get the url address of the http request public String getRequestURL(); //Request server: To return a response object public HttpResponseInter request() throws Exception; }
(2) As the corresponding response object in (1), HttpResponseInter.java should have the following methods: get the returned status code, get the returned stream, get the returned string data, and so on. The next method is to get the corresponding data.
/** * Responsive Interface* @author xuliugen */ public interface HttpResponseInter { //Return status code public int statusCode(); // Return number of streams to client public InputStream getResponseStream() throws IllegalStateException,IOException; //Return byte array to client public byte[] getResponseStreamAsByte() throws IOException; //Return JSON data to client public String getResponseStreamAsString() throws ParseException, IOException; }
(3) This is the implementation class of the HttpRequestImpl.java interface. We can see that we have implemented not only the HttpRequestInter interface but also the ResponseHandler. The second is the data that needs to be returned when the request request is executed and stored in a response's Handler.
public class HttpRequestImpl implements HttpRequestInter,ResponseHandler<HttpResponseInter> { protected HttpUriRequest httpUriRequest;// url address to get request private AbstractHttpClient abstractHttpClient; // client object // Constructive Offense public HttpRequestImpl(AbstractHttpClient httpClient) { this.abstractHttpClient = httpClient; } // get method public HttpUriRequest getHttpRequest() { return httpUriRequest; } //url to get request public String getRequestURL() { return httpUriRequest.getURI().toString(); } //Execute the request request request and return? response object interfaces public HttpResponseInter request() throws Exception { return abstractHttpClient.execute(httpUriRequest, this);//Incoming ResponseHandler object } /** * Method implemented by inheriting ResponseHandler interface * Processing interface for response object after execution */ public HttpResponseInter handleResponse(HttpResponse response)throws ClientProtocolException, IOException { //Returns the class that implements HttpResponseInter: returns to a response interface HttpResponseInter httpResponseInter = new HttpResponseImpl(response); //response is required when returning return httpResponseInter; } }
(4) Then there is the implementation class for the interface: HttpResponseImpl.java can see an HttpResponse response object in the construction method, which is the response object returned by the handler after the request has been executed.
/** * Implementation class of interface* @author xuliugen */ public class HttpResponseImpl implements HttpResponseInter { private HttpResponse response; // HttpResponse object private HttpEntity entity; // HttpEntity Test Object public HttpResponseImpl(HttpResponse response) throws IOException { this.response = response; HttpEntity tempEntity = response.getEntity();// Get the entity returned by the server if (null != tempEntity) { entity = new BufferedHttpEntity(tempEntity); } } // Returns the status code of the response object public int statusCode() { return response.getStatusLine().getStatusCode(); } // stream to get results public InputStream getResponseStream() throws IllegalStateException, IOException { InputStream inputStream = entity.getContent(); return inputStream; } // The result is converted to string public String getResponseStreamAsString() throws ParseException, IOException { return EntityUtils.toString(entity); } // The result is converted to an array of characters public byte[] getResponseStreamAsByte() throws IOException { return EntityUtils.toByteArray(entity); } }
(5) ExecuteHttpPost.java is a class that inherits two main construction methods from HttpRequestImpl.java. The construction method is the actual post request method and parameter settings:
/** * Is this the real place to execute post requests? * * Inherit HttpRequestImpl to implement client-to-server requests? * * @author xuliugen * */ public class ExecuteHttpPost extends HttpRequestImpl { public ExecuteHttpPost(AbstractHttpClient httpClient, String url) { this(httpClient, url, null); } public ExecuteHttpPost(AbstractHttpClient httpClient, String url,HttpEntity entity) { super(httpClient);//httpClient in parent class this.httpUriRequest = new org.apache.http.client.methods.HttpPost(url);// Initialize httpUriRequest if (null != entity) {// Setting parameters ((HttpEntityEnclosingRequestBase) httpUriRequest).setEntity(entity); } } }
(6) Another important class is the implementation of the client: BaseHttpClient.java here we set up a series of methods to implement the request methods of different clients, and how to convert the parameters requested by the client into the parameter types of post requests, and the returned data into the corresponding formats.The cascade calls of the method, I hope you can calm down and look slowly.
/** * HttpClient Top Class of Client */ public class BaseHttpClient { private AbstractHttpClient httpClient; public static final int DEFAULT_RETIES_COUNT = 5; protected int retriesCount = DEFAULT_RETIES_COUNT; // Set maximum number of connections public final static int MAX_TOTAL_CONNECTIONS = 100; // Set the maximum wait time to get a connection public final static int WAIT_TIMEOUT = 30000; // Set the maximum number of connections per route public final static int MAX_ROUTE_CONNECTIONS = 100; // Set connection timeout public final static int CONNECT_TIMEOUT = 10000; // Set Read Timeout public final static int READ_TIMEOUT = 10000; /** * Construct method, call initialization method */ public BaseHttpClient() { initHttpClient(); } /** * Initialize client parameters */ private void initHttpClient() { //http parameters HttpParams httpParams = new BasicHttpParams(); //Set maximum number of connections ConnManagerParams.setMaxTotalConnections(httpParams,MAX_TOTAL_CONNECTIONS); //Set the maximum wait time to get a connection ConnManagerParams.setTimeout(httpParams, WAIT_TIMEOUT); //Set the maximum number of connections per route ConnPerRouteBean connPerRoute = new ConnPerRouteBean(MAX_ROUTE_CONNECTIONS); ConnManagerParams.setMaxConnectionsPerRoute(httpParams, connPerRoute); // Set connection timeout HttpConnectionParams.setConnectionTimeout(httpParams, CONNECT_TIMEOUT); // Set Read Timeout HttpConnectionParams.setSoTimeout(httpParams, READ_TIMEOUT); HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));//Set Port 80 schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));//Set Port 443 //Is the one that manages SchemeRegistry ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(httpParams, schemeRegistry); httpClient = new DefaultHttpClient(clientConnectionManager, httpParams); //Create a handler for http reconnection httpClient.setHttpRequestRetryHandler(new BaseHttpRequestRetryHandler(retriesCount)); } /** * Convert parameters to a collection of List <BasicNameValuePair> */ private List<BasicNameValuePair> parseParams(HashMap<String, Object> params) { if (params == null || 0 == params.size()){ return null; } List<BasicNameValuePair> paramsList = new ArrayList<BasicNameValuePair>(params.size()); for (Entry<String, Object> entry : params.entrySet()) { paramsList.add(new BasicNameValuePair(entry.getKey(), entry.getValue() + "")); } return paramsList; } /** * Request to the server: when only URLs have no parameters */ public String post(String url) throws Exception { return post(url, null); //post executed when a parameter is called and set to null } /** * post Return T-type results after request */ public <T> T post(String url, HashMap<String, Object> params, Class<T> clz) throws Exception { String json = post(url, params); return JSONUtil.fromJson(json, clz); //Convert to Specific Type Return } /** * Other functions call this method indirectly when the request has parameters */ public String post(String url, HashMap<String, Object> params) throws Exception { //Convert the incoming parameter to a parameter entity: Convert params to an enrity object: Formentity UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parseParams(params)); return request(url, entity).getResponseStreamAsString(); } /** * Return results of post execution directly */ public Result postAsResult(String url, HashMap<String, Object> params)throws Exception { return post(url, params, Result.class); } /** * Return the result of post execution as a Stream */ public InputStream postAsStream(String url, HashMap<String, Object> params) throws Exception { //Converts an incoming parameter to a parameter entity UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parseParams(params)); return request(url, entity).getResponseStream(); } public HttpResponseInter request(String url, HttpEntity entity) throws Exception { HttpRequestImpl httpRequestImpl = new ExecuteHttpPost(httpClient, url, entity); return httpRequestImpl.request(); } }
(7) The last is the number of times we use a BaseHttpRequestRetryHandler.java in httpClient to implement repeated requests on the network
/** * http Retry Connection: Primarily used to complete an attempt to reconnect* @author xuliugen */ public class BaseHttpRequestRetryHandler implements HttpRequestRetryHandler { private int max_retry_count;// Maximum number of attempts to connect public BaseHttpRequestRetryHandler(int maxretryCount) { this.max_retry_count = maxretryCount; } private static HashSet<Class<? extends IOException>> exceptionWhiteList = new HashSet<Class<? extends IOException>>(); private static HashSet<Class<? extends IOException>> exceptionBlackList = new HashSet<Class<? extends IOException>>(); static { exceptionWhiteList.add(NoHttpResponseException.class); exceptionWhiteList.add(UnknownHostException.class); exceptionWhiteList.add(SocketException.class); exceptionBlackList.add(SSLException.class); exceptionBlackList.add(InterruptedIOException.class); exceptionBlackList.add(SocketTimeoutException.class); } public boolean retryRequest(IOException exception, int executionCount,HttpContext context) { if (executionCount > max_retry_count){ return false; } if (exceptionBlackList.contains(exception.getClass())){ return false; } if (exceptionWhiteList.contains(exception.getClass())){ return true; } HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST); boolean idempotent = (request instanceof HttpEntityEnclosingRequest); if (!idempotent) { // Wulu Xuan baked a ton of Xuan return true; } Boolean b = (Boolean) context.getAttribute(ExecutionContext.HTTP_REQ_SENT); boolean sent = (b != null && b.booleanValue()); if (!sent) { return true; } return false; } }
Combination of Service and syncTask
The general process is as follows:
(1) We unified the tasks for Service, so we needed a Task entity
public class Task { private int taskId;// Task ID private Map<String, Object> taskParams;// parameter public static final int USER_LOGIN = 1; //A custom task ID //Construction method and get, set method omit }
(2) Below is Service which manages Task in a unified way. In Service, we need not only to manage Task as an asynchronous task, but also to manage the operation of updating the interface. Because the operation of updating the interface can no longer reside in the UI, we need a unified management activity. In Service, we perform different tasks.The operation of the step task has been implemented using Thread and Handler.
public class MainService extends Service implements Runnable { // Task Queue: The queue used to store tasks private static Queue<Task> tasks = new LinkedList<Task>(); // Add UI that needs to be updated to the collection private static ArrayList<Activity> appActivities = new ArrayList<Activity>(); private boolean isRun;// Whether to run threads Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case Task.USER_LOGIN: {// User Login: Update UI //Find activity by name: Since MAinActivity implements the MainActivityInter interface, it can be strongly converted to MainActivityInter type MainActivityInter activity = (MainActivityInter) getActivityByName("MainActivity"); activity.refresh(msg.obj.toString()); break; } default: break; } }; }; /** * Add Task to Task Queue */ public static void newTask(Task t) { tasks.add(t); } @Override public void onCreate() { isRun = true; Thread thread = new Thread(this); thread.start(); super.onCreate(); } /** * Keep the service iterating through execution */ public void run() { while (isRun) { // To listen for tasks Task task = null; if (!tasks.isEmpty()) { // Determine if there are values in the queue task = tasks.poll();// Remove the change from the task queue after executing the task if (null != task) { doTask(task); // TO DO: Perform tasks } } try { Thread.sleep(1000); } catch (Exception e) { } } } // Processing Tasks private void doTask(Task task) { Message msg = handler.obtainMessage(); msg.what = task.getTaskId(); switch (task.getTaskId()) { case Task.USER_LOGIN: { // User Login HashMap<String, Object> paramsHashMap = (HashMap<String, Object>) task.getTaskParams(); //Access the network to determine if a user exists String url = "http://172.23.252.89:8080/igouServ/userlogin.action"; BaseHttpClient httpClient = new BaseHttpClient(); try { String result = httpClient.post(url, paramsHashMap); msg.obj= result; //Return to handler for processing } catch (Exception e) { e.printStackTrace(); } break; } default: break; } handler.sendMessage(msg); } @Override public IBinder onBind(Intent intent) { return null; } /** * Add an Activity object to the collection */ public static void addActivity(Activity activity) { if (!appActivities.isEmpty()) { for (Activity ac : appActivities) { if (ac.getClass().getName().equals(ac.getClass().getName())) { appActivities.remove(ac); break; } } } appActivities.add(activity); } /** * Get Activity Objects from Activity's Name */ private Activity getActivityByName(String name) { if (!appActivities.isEmpty()) { for (Activity activity : appActivities) { if (null != activity) { if (activity.getClass().getName().indexOf(name) > 0) { return activity; } } } } return null; } /** * Exit System */ public static void appExit(Context context) { // Finish All Activities for (Activity activity : appActivities) { if (!activity.isFinishing()) activity.finish(); } // End Service Intent service = new Intent("com.xuliugen.frame.task.MainService"); context.stopService(service); } }
(3) There are two ways to write an Interface interface MainActivityInter.java in order to enable Service to manage the activity uniformly. One way is to refresh the interface so that we can operate the interface in the service.
public interface MainActivityInter { /** * Initialization operation */ public void init(); /** * Refresh UI */ public void refresh(Object... params); }
testing procedure
(1) MainActivity.java was created mainly to simulate a login operation, where we need to turn on the service. Unfortunately, UN should like to get a task, add it to the task queue managed by Service, and then leave the other operations to MainService.java (Service) for operation.
public class MainActivity extends Activity implements MainActivityInter { private Button btn_login; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_login = (Button) this.findViewById(R.id.btn_login); textView= (TextView) this.findViewById(R.id.textView1); // Start Services Intent serviceIntent = new Intent(this, MainService.class); startService(serviceIntent); btn_login.setOnClickListener(new OnClickListener() { public void onClick(View v) { //Construction parameters are passed to Task for processing Map<String, Object> paramsHashMap = new HashMap<String, Object>(2); paramsHashMap.put("userName", "xuliugen"); paramsHashMap.put("password", "123456"); Task task = new Task(Task.USER_LOGIN, paramsHashMap); MainService.newTask(task); } }); // Put activity into the activity queue collection MainService.addActivity(this); } /******************** The following two methods are *******************in the MainActivityInter interface*/ public void init() { } public void refresh(Object... params) { //Update UI based on returned parameters textView.setText(params[0].toString()); } }
Project download address: https://github.com/xuliugen/HttpAndAsyncTaskFrame
Reprinted at: https://my.oschina.net/zipu888/blog/549739