A few days ago, I made a small exercise using the Hessian framework for network access. Some asynchronous elements are added to the traditional Hessian network access requests. For example, a simple diagram of a traditional Hessian request
Take logon as an example to see the code process:
Request:
The blocking login method in the interface, with your own code:
/** Log on -- log on **/public user login (string username, string password, long ID, int typeid) throws interactionexception;
Generate a method to generate hessianproxy through hessianproxyfactory. See the source code:
public Object create(Class<?> api, URL url, ClassLoader loader) { if (api == null) throw new NullPointerException("api must not be null for HessianProxyFactory.create()"); InvocationHandler handler = null; handler = new HessianProxy(url, this, api); return Proxy.newProxyInstance(loader, new Class[] { api, HessianRemoteObject.class }, handler); }
After obtaining hessianproxy, call the invoke method in it, that is, the login proxy method, to implement a simple login request. Check the source code.
Public object invoke (Object proxy, method, object [] ARGs) throws throwable {....... export acthessianoutput out = _ factory. gethessianoutput (OS); out. call (methodname, argS); // write the login method name and parameter out. flush ();........}
The obtained hessianproxy can directly call the login method in step 1, and the code is as follows:
proxy.login("duancanmeng","123");
Based on the above, we assume some asynchronous elements,
How to embody Asynchronization?
This is nothing more than thread opening. How should we open it? Where can I start it? What kind of thread?
The first thought should be to put the invoke in hessianproxy into the new thread for processing, which is the most basic. New thread directly?
Of course, you can write a class hessiannewproxy to inherit hessianproxy and rewrite the invoke method. Some checks can be done here. If the judgment is asynchronous, the invoke method of the parent class is called in the new thread. Otherwise, the invoke method of the parent class is called directly in the main thread:
Hessiannewproxy:
Invoke () {If (asynchronous) {New thread () {run () {super. invoke ();}}. start ();} else {super. invoke ();}}
However, in Android, it is not recommended to use new threads to execute asynchronous requests (considering some interface refreshing Issues). Android encapsulates its own asynchronous task class asyntask. However, normal Java projects do not have such asynchronous task classes. To implement normal Java projects, you can also perform some operations before and after method execution, just like android projects. Here, we can extract the thread Implementation Method to the user for implementation as an interface. Therefore, in the asynchronous block of invoke, the asynchronous task executor is used to execute the asynchronous task, but the specific implementation method is handed over to the user as needed. The above code can be changed:
Invoke () {If (asynchronous) {self-depending thread mode (hessianasyntask task);} else {super. Invoke ();}}
Hessianasyntask:
Package COM. PCCW. hessian. support. client;/*** task execution listener. * This listener should only create * @ Param <r> returned result type for successful task execution in the UI thread * @ Param <E> exception type thrown during task execution */public interface hessianasyntask <r, E extends throwable> {r doinbackground () throws E; /*** this method will be called if an exception occurs during task execution * [run in Ui thread] */void onexceptionoccured (E ); /*** this method is called when the task is successfully executed. The result is the task result */void onexecutesuccess (R result ); /*** after the task is successfully executed [or an exception occurs], the method * @ Param context * @ Param urikey */void onfinally (R result) will be executed );}
In this way, we only need to control the sequence of the method execution in hessianasyntask in the self-implemented thread mode, taking care of both the android project and the Java project. How can we implement the thread by the user? You also need to define the hessianasyntaskexecuter interface of an asynchronous task executor. The Code is as follows:
Hessianasyntaskexecuter:
Package COM. PCCW. hessian. support. client;/*** asynchronous task executor **/public interface hessianasyntaskexecuter <R, E extends throwable> {public void execute (hessianasyntask <R, E> executer );}
Then, the invoke method in hessiannewproxy can be changed:
Invoke () {If (asynchronous) {hessianasyntaskexecuter.exe cute (hessianasyntask) ;}else {super. Invoke ();}}
We only care about the implementation of asynchronous task executors. In this way, no matter the android project or Java project, before or after calling the real business method, all of them can be processed in hessianasyntask.
For example, if I am a Java project, I can use the new thread in the implementation class of hessianasyntaskexecute to control the implementation sequence of methods in hessianasyntask to achieve the pre-and post-operations:
execute(HessianAsynTask task){ new Thread(){try{ task.doInBackground(){ login(); }; task.onExecuteSuccess();}}catch(){ task.onExceptionOccured(); }finally{ task.onFinally();} }}
If it is an android project, it is as follows:
execute(final HessianAsynTask<R,E> executer) {new AsyncTask<Void, Void, Exception, R>(){@Overrideprotected R doInBackground(Void... params) throws Exception {return executer.doInBackground();}@Overrideprotected void onPostExecute(R result) {executer.onExecuteSuccess(result);executer.onFinally(result);}@SuppressWarnings("unchecked")@Overrideprotected void onExceptionOccured(Exception e) {executer.onExceptionOccured((E) e);executer.onFinally(null);}}.execute();}}
Therefore, we can see that hessianasyntaskexecute is used together with hessianasyntask to adapt to different situations.
The specific process is as follows:
Hessianasyntaskexecuter: asynchronous task executor, used to execute asynchronous tasks in requests, such as Asynchronous Login
Hessiantaskexcuterobserver: The task execution observer used to monitor the execution of tasks (including asynchronous and non-asynchronous tasks). It can be used to process cache and resources.
Hessianasyntask: asynchronous task, which is mainly used in conjunction with hessianasyntaskexecuter and used as a parameter to pass in the method of the actuator for execution.
Taskexecutelistener: a task execution listener that monitors the execution of asynchronous tasks, including cache and resource processing.
1. Login Request
Interface blocking login method:
/** Log on -- log on **/Public void login (string username, string password, long ID, int typeid, taskexecutelistener <user, interactionexception> listener );
2. Factory generates a proxy.
remoteService = proxyFactory.create(RemoteService.class, url, new CMSAsynTaskExecuter<Object, Exception>(),new CMSExceptionHandler(),new CMSTaskExcuterObserver(SharedPreferencesUtlis.getAppSharedPreferences(context)),new CMSConnectionObserver(SharedPreferencesUtlis.getAppSharedPreferences(context)));
3. Determine whether the request is asynchronous. Here we use the parameters in the login method to determine whether the request is asynchronous. If the request is asynchronous, A taskexecutelistener is passed in.
Public object invoke (Object proxy, method, object [] ARGs) throws throwable {mtaskexecuteobserver. onperexecute (this, proxy, method, argS ); /*** ===================================================== ===== asynchronous task block */taskexecutelistener <object, throwable> taskexecutelistener = NULL; If (ARGs! = NULL & args. length> 0 & ARGs [args. length-1] instanceof taskexecutelistener) {// checks whether the method is asynchronous. The check is based on the last parameter type in the parameter list of the modified method: taskexecutelistenertaskexecutelistener = (taskexecutelistener <object, throwable>) ARGs [args. length-1]; ARGs = supportutils. copyofrange (ARGs, 0, argS. length-1); method = getnoasynmethod (method); // replace methods and parameters with non-asynchronous methods and parameters taskexecutelistener. onperexecute (method, argS);} If (taskexecutelistener! = NULL) {// if you need to obtain data remotely and find it as an asynchronous task, start the Asynchronous Method execution task. This method directly returns nulldoinvokeasyn (proxy, method, argS, taskexecutelistener ); return NULL;} else {// directly requests data object result = NULL from the remote server through blocking; throwable E = NULL; try {result = super. doinvoke (proxy, method, argS); mtaskexecuteobserver. onexecutesuccess (this, proxy, method, argS, result); return result;} catch (throwable E1) {e = exceptionhandler. parseexception (E1); object secondresult = mtaskexecuteobserver. onexceptionoccured (this, proxy, method, argS, e); // If the exceptional rescue measures are successful, the task is still successful mtaskexecuteobserver. onexecutesuccess (this, proxy, method, argS, secondresult); Return secondresult;} finally {mtaskexecuteobserver. onfinally (this, proxy, method, argS, result, e );}}}
4. Execute an asynchronous task through an asynchronous task executor
@SuppressWarnings("unchecked")private void doInvokeAsyn(final Object proxy, final Method method, final Object[] args,final TaskExecuteListener<Object,Throwable> taskExecuteListener){((HessianNewProxyFactory)_factory).getAsynTaskExecuter().execute(new HessianAsynTask<Object,Throwable>() {private Throwable mThrowable;private Object mResult;@Overridepublic Object doInBackground() throws Throwable {return doInvoke(proxy, method, args);}@Overridepublic void onExceptionOccured(Throwable exception) {exception=exceptionHandler.parseException(exception);Object result=null;try {result=mTaskExecuteObserver.onExceptionOccured(HessianNewProxy.this,proxy, method, args, exception);onExecuteSuccess(result);} catch (Throwable e) {mThrowable=e;taskExecuteListener.onExceptionOccured(method, args, e);}}@Overridepublic void onExecuteSuccess(Object result) {mResult=result;mTaskExecuteObserver.onExecuteSuccess(HessianNewProxy.this,proxy, method, args, result);taskExecuteListener.onExecuteSuccess(method, args, result);}@Overridepublic void onFinally(Object result) {mTaskExecuteObserver.onFinally(HessianNewProxy.this,proxy, method, args, mResult, mThrowable);taskExecuteListener.onFinally(method, args, mResult);}});}}
5. The code in step 4 of hessianasyntask is passed in as a parameter, and a listener parameter taskexecutelistener is also required in this parameter. taskexecutelistener only listens to asynchronous requests and has a small range, for this request only, the taskexecutelistener code is as follows:
/*** Task execution listener. * This listener should only create * @ Param <t> In the UI thread. The returned result type is successfully executed. */public interface taskexecutelistener <R, E extends throwable> {/*** execute this method before the task starts. You can perform initialization in this method * [run in Ui thread] */void onperexecute (method, object [] ARGs);/*** this method is called when an exception occurs during task execution * [executed in the UI thread] */void onexceptionoccured (method, object [] ARGs, e);/*** this method will be called when the task is successfully executed. The result is the task result */void onexecutesuccess (method, object [] ARGs, R result ); /*** the Method * @ Param context * @ Param urikey */void onfinally (method, object [] ARGs, R result );}
7. hessiantaskexcuterobserver is an overall listener. cache settings can be made for any request method, whether asynchronous or non-asynchronous. For example, after a long time of no operation, before obtaining the data, determine whether the information of the login user exists in the cache. If so, obtain the data. If not, log on.
Code:
Public interface hessiantaskexcuterobserver {/*** execute this method before the task starts. You can perform initialization in this method * [run in Ui thread] */void onperexecute (hessianproxy invocationhandler, object proxy, method, object [] ARGs);/*** perform some checks before the task is executed * @ return if it is true, there is no problem. Continue to execute, if the value is false, the system detects a problem. Stop the execution and execute oncheckfalsereturn */Boolean onperexecutecheck (hessianproxy invocationhandler, object proxy, method, object [] ARGs ); /*** perform some checks before the task is executed. If the value is false, an oncheckfalsereturn is executed and the task is stopped. */objectoncheckfalseandreturn (hessianproxy invocationhandler, object proxy, method, object [] ARGs);/*** this method is called when an exception occurs during task execution * @ return you can continue throw e in this method, however, you still have the opportunity to return the appropriate task execution result */object onexceptionoccured (hessianproxy invocationhandler, object proxy, method, object [] ARGs, throwable e) throws throwable; /*** this method is called when the task is successfully executed. The result is the task result */void onexecutesuccess (hessianproxy invocationhandler, object proxy, method, object [] ARGs, object result ); /*** after the task is successfully executed [or an exception occurs], the method */void onfinally (hessianproxy invocationhandler, object proxy, method, object [] ARGs, object result, throwable E );}
The package source code: http://download.csdn.net/detail/duancanmeng/4561246