Java Invoker Client、Spring Service Exporter。
所需 Jar 檔(版本可以依據自身需求調整):aopalliance-1.0.jar、commons-logging-1.2.jar、spring-beans-4.3.30.RELEASE.jar、spring-core-3.1.0.RELEASE.jar、spring-remoting-2.0.8.jar。
之前分享過如何利用 Spring 的 Service Invoker and Exporter 建立 AP 前後台機制 https://dotblogs.com.tw/Ryuichi/2019/12/14/102346。
本篇則接續分享如何撰寫 Java Client 程式直接使用後台 AP 的 Service。
為了盡可能符合現況,我們建一個新的類別叫做 InvokerParam,並設定一個 String 的變數在裡面。
import java.io.Serializable;
public class InvokerParam implements Serializable {
private String param = "";
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
}
接著將 TaskInterfaceBO 新增一個方法 responseInvoker,方法內帶入兩個 InvokerParam 物件當參數。
同時在 TaskInterfaceBOImpl 將方法 responseInvoker 完成,將兩個 InvokerParam 變數裡的字串串起來後回傳。
import com.spring.tku.model.InvokerParam;
import com.spring.tku.model.TransferBean;
public interface TaskInterfaceBO {
public TransferBean getResultFromBackEnd();
public TransferBean responseInvoker(InvokerParam invokerParam_1, InvokerParam invokerParam_2);
}
import org.springframework.context.annotation.ComponentScan;
import com.spring.tku.model.InvokerParam;
import com.spring.tku.model.TransferBean;
@ComponentScan("com.spring.tku")
public class TaskInterfaceBOImpl implements TaskInterfaceBO {
@Override
public TransferBean getResultFromBackEnd() {
TransferBean tb = new TransferBean();
tb.setResult("You Got Result");
return tb;
}
@Override
public TransferBean responseInvoker(InvokerParam invokerParam_1, InvokerParam invokerParam_2) {
TransferBean tb = new TransferBean();
tb.setResult(invokerParam_1.getParam() + "_" + invokerParam_2.getParam());
return tb;
}
}
接著我們撰寫 Client 端程式,依序設定 Url、Interface 名稱、方法名稱與變數。
ServiceExporterOverrider 是我上一篇網誌範例中防止任意呼叫而撰寫的阻擋機制,因此在這邊的範例需要將 key 與 token 加入才會通過檢查。
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.springframework.remoting.support.*;
import com.spring.tku.bo.TaskInterfaceBO;
import com.spring.tku.model.InvokerParam;
import com.spring.tku.model.TransferBean;
@SuppressWarnings("rawtypes")
public class InvokerClient {
public static void main(String args[]) {
try {
requestExecutorInvoke();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void requestExecutorInvoke()throws Exception {
HttpInvokerProxyFactoryBean httpInvokerProxyFactoryBean = new HttpInvokerProxyFactoryBean();
httpInvokerProxyFactoryBean.setServiceInterface(TaskInterfaceBO.class);
httpInvokerProxyFactoryBean.setServiceUrl("http://127.0.0.1:8080/spring_backend/TaskInterfaceBO");
SimpleHttpInvokerRequestExecutor simpleHttpInvokerRequestExecutor = new SimpleHttpInvokerRequestExecutor();
//塞入key and token
Map<String, Serializable> securityMap =new HashMap<String, Serializable>();
securityMap.put("key", "key");
securityMap.put("token", "token");
//發動invocation相關設定
RemoteInvocation invocation = new RemoteInvocation();
invocation.setAttributes(securityMap);
invocation.setMethodName("responseInvoker");//請去TaskInterfaceBOImpl找有@Override字眼的實作方法
InvokerParam invokerParam_1 = new InvokerParam();
InvokerParam invokerParam_2 = new InvokerParam();
invokerParam_1.setParam("invoker");
invokerParam_2.setParam("response");
invocation.setParameterTypes(new Class[] {InvokerParam.class, InvokerParam.class});//方法有兩個參數, 指定參數型態
invocation.setArguments(new Object[] {invokerParam_1, invokerParam_2});//把參數值帶進去
//發動呼叫
httpInvokerProxyFactoryBean.setHttpInvokerRequestExecutor(simpleHttpInvokerRequestExecutor);
RemoteInvocationResult result =simpleHttpInvokerRequestExecutor.executeRequest(httpInvokerProxyFactoryBean, invocation);
//接回傳值
TransferBean transferBean = (TransferBean)result.getValue();//根據方法回傳的物件做轉換
System.out.println(result);
}
}
下圖為我的 Client 程式在 Eclipse 內的結構,需要的類別必須放置在與後台 AP 宣告 package 一樣的路徑,否則執行會報錯。
最後放上使用 Debug Mode 檢視的結果。