撰寫 Java Client 呼叫 Spring Service Exporter 提供之 Service

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 檢視的結果。