RCP 前后台通信的解析

eclipse平台提供一种rcp应用程序,开发出来的应用界面简洁漂亮,是做一些医疗、制造执行系统等比较合适的选择,刚入公司时就接触这方面的程序,当时感觉很强大。首先,程序可以打成jar包通过tomcat发布;其次,应用程序通过浏览器下载到本后执行,既有客户端的优势又有web程序的优势。本来以为这是一种java小程序,后来看来了下web包才知道,是因为一个jsp配置了一个jnlp标签后就可以实现了。

下面我们就说一下这种程序与后台的通信方式:

1.简要介绍程序的后台

 主要用了Spring+hibernate+ibatis,为什么要用hibernate+ibatiS呢,主要因为这个项目一开始时主要用的是ibatiS,可能近年来hibernate火了,其在单个对象的查询方式大大简化了程序的代码,使得单个对象的查询非常方便。这样对多个对象的关联查询用ibatis,单个就用hibernate,感觉可以完全丢掉ibatis了,不过要改的代码就多了(其实这个和这个通信一点关系也没有)。

        Spring这个有关系了,它管理着我们的所有接口和接口的实现。

 2.简单说下原理

前台调用接口的方法   ---》得到一个代理类-----》访问一个servlet请求(传递接口名和参数)-----到后台-----》后台通过反射得到接口实现----------》执行接口方法得到结果-------》response给前台。

当然在调用前和调用后我们都有一层封装,当然泛型是能简便实现这种通信的前提了。


3.例子说明

1.前台调用:

public class RomoteTest {

	public static void main(String[] args){
		IUserMstrService userMstrService =  RemoteProxyFactory.getService(IUserMstrService.class);//得到一个代理
		UserMastr bo = new UserMastr();
		bo.setUserName("wunai");
		bo = userMstrService.deleteUser(bo);//代理调用方式请看下面的代码
		System.out.println("userMastr:"+ bo.getUserName());
	}
}

2.得到代理

/**
	 * 得到默认应用服务器的Service代理
	 * @param 
	 * @param serviceClass
	 * @return
	 */
	public static  T getService(Class serviceClass) {
		return getService(serviceClass, null);
	}
	public static  T getService(Class serviceClass, String requestServerUrl) {
		if (serviceClass == null) {
			System.out.println("获得远程service实例出错:参数为空"); 
		} else if (!serviceClass.isInterface()) {
			System.out.println("获得远程service实例出错:参数不是接口类型");
		} else {
			try {
				ClassLoader cl = serviceClass.getClassLoader();
				Class[] interfaces = new Class[] { serviceClass };
				ProxyInvocationHandler handler = new ProxyInvocationHandler(serviceClass, requestServerUrl);
				return (T) Proxy.newProxyInstance(cl, interfaces, handler);
			} catch (IllegalArgumentException e) {
				System.out.println("获得远程service实例出错:未知异常");
			}
		}
		return null;
	}
3.代理访问servlet请求:

public ProxyInvocationHandler(Class serviceClass, String requestServerUrl) {
		this.serviceClass = serviceClass;
		this.requestServerUrl = requestServerUrl;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		ParamClass passParamObj = new ParamClass();
		String serviceName = getServiceName(serviceClass);
		String methodName = method.getName();
		Class[] parameterTypes = method.getParameterTypes();
		passParamObj.setServiceName(serviceName);
		passParamObj.setMethodName(methodName);
		passParamObj.setMethodParams(args);
		passParamObj.setParameterTypes(parameterTypes);
		try {
			PassOutObj passOutObj = null;
			if (requestServerUrl == null) {
				passOutObj = DelegateManager.getInstance().request("UserServlet", passParamObj);
			} else {
				passOutObj = DelegateManager.getInstance().request(requestServerUrl, "UserServlet", passParamObj);
			}
			if (passOutObj != null) {
				Exception exception = passOutObj.getException();
				Object result = passOutObj.getOutputObj();

				if (exception != null) {
					throw exception;
				} else {
					return result;
				}
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());	
		}
		return null;
	}

这里的passParamObj是将接口名,方法,参数进行了一次封装。

4.servlet接受数据,并通过反视得到实现(这里wac就是Spring 的 WebApplicationContext )

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ParamClass passParamObj = (ParamClass) request.getAttribute("inputObj");
		String serviceName = passParamObj.getServiceName();
		String methodName = passParamObj.getMethodName();
		Object[] methodParams = passParamObj.getMethodParams();
		Class[] parameterTypes = passParamObj.getParameterTypes();
		Object service = wac.getBean(serviceName);
		Method method = null;
		Object resultObject = null;
		try {
			method = service.getClass().getMethod(methodName,parameterTypes);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		try {
			resultObject = method.invoke(service, methodParams);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
                    // 把结果传递给后台在下面
}

5.结果的传递

public void serverWritePart(HttpServletResponse response, Object writeObj) throws IOException {
		if (writeObj != null) {
			ServletOutputStream sos = null;
			try {
				sos = response.getOutputStream();
			} catch (IOException e) {
				System.err.println(getClass() + " IOException occured in performing serverWritePart(HttpServletResponse response, Object writeObj)");
				e.printStackTrace();
				throw e;
			}
			if (sos != null) {
				byte[] bytes = StreamUtil.getInstance().object2Bytes(writeObj);
				StreamUtil.getInstance().writeBytes(sos, bytes, BYTE_OF_WRITE_EVERYTIME);
			}
		}
	}

感觉这种前后通信确实很不错的,不过这种方式也只是在局域网作用比较大吧,当然这种rcp的程序也是在局域网内发挥作用吧。






你可能感兴趣的:(问题解决方式,个人回顾)