之前项目中需要分开部署,使用hessian(4.0.7)交互,而项目本身就是用Spring(3.2.5),已提供相关组件,因此使用起来很容易。如果是作为服务端,暴露服务,使用的是org.springframework.remoting.caucho.HessianServiceExporter,已提供有debug属性,方便开发时调试。但提供给客户端用于代理指定接口的org.springframework.remoting.caucho.HessianProxyFactoryBean并没有提供debug属性。HessianProxyFactoryBean继承自org.springframework.remoting.caucho.HessianClientInterceptor,所有对HessianClientInterceptor的调用均委托给HessianProxyFactory处理,HessianProxyFactory本身有debug属性,只需要重写HessianClientInterceptor,暴露出来即可。完整代码如下(只是新增了方法setConnectTimeout),
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.ConnectException;
import java.net.MalformedURLException;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.RemoteConnectFailureException;
import org.springframework.remoting.RemoteLookupFailureException;
import org.springframework.remoting.RemoteProxyFailureException;
import org.springframework.remoting.support.UrlBasedRemoteAccessor;
import org.springframework.util.Assert;
import com.caucho.hessian.HessianException;
import com.caucho.hessian.client.HessianConnectionException;
import com.caucho.hessian.client.HessianProxyFactory;
import com.caucho.hessian.client.HessianRuntimeException;
import com.caucho.hessian.io.SerializerFactory;
public class HessianClientInterceptor extends UrlBasedRemoteAccessor implements MethodInterceptor {
private HessianProxyFactory proxyFactory = new HessianProxyFactory();
private Object hessianProxy;
/**
* Set the HessianProxyFactory instance to use. If not specified, a
* default HessianProxyFactory will be created.
* <p>
* Allows to use an externally configured factory instance, in particular
* a custom HessianProxyFactory subclass.
*/
public void setProxyFactory(HessianProxyFactory proxyFactory) {
this.proxyFactory = (proxyFactory != null ? proxyFactory : new HessianProxyFactory());
}
/**
* Specify the Hessian SerializerFactory to use.
* <p>
* This will typically be passed in as an inner bean definition of type
* {@code com.caucho.hessian.io.SerializerFactory}, with custom bean
* property values applied.
*/
public void setSerializerFactory(SerializerFactory serializerFactory) {
this.proxyFactory.setSerializerFactory(serializerFactory);
}
/**
* Set whether to send the Java collection type for each serialized
* collection. Default is "true".
*/
public void setSendCollectionType(boolean sendCollectionType) {
this.proxyFactory.getSerializerFactory().setSendCollectionType(sendCollectionType);
}
/**
* Set whether overloaded methods should be enabled for remote
* invocations. Default is "false".
*
* @see com.caucho.hessian.client.HessianProxyFactory#setOverloadEnabled
*/
public void setOverloadEnabled(boolean overloadEnabled) {
this.proxyFactory.setOverloadEnabled(overloadEnabled);
}
/**
* Set the username that this factory should use to access the remote
* service. Default is none.
* <p>
* The username will be sent by Hessian via HTTP Basic Authentication.
*
* @see com.caucho.hessian.client.HessianProxyFactory#setUser
*/
public void setUsername(String username) {
this.proxyFactory.setUser(username);
}
/**
* Set the password that this factory should use to access the remote
* service. Default is none.
* <p>
* The password will be sent by Hessian via HTTP Basic Authentication.
*
* @see com.caucho.hessian.client.HessianProxyFactory#setPassword
*/
public void setPassword(String password) {
this.proxyFactory.setPassword(password);
}
/**
* Set whether Hessian's debug mode should be enabled. Default is "false".
*
* @see com.caucho.hessian.client.HessianProxyFactory#setDebug
*/
public void setDebug(boolean debug) {
this.proxyFactory.setDebug(debug);
}
/**
* Set whether to use a chunked post for sending a Hessian request.
*
* @see com.caucho.hessian.client.HessianProxyFactory#setChunkedPost
*/
public void setChunkedPost(boolean chunkedPost) {
this.proxyFactory.setChunkedPost(chunkedPost);
}
/**
* Set the timeout to use when waiting for a reply from the Hessian
* service.
*
* @see com.caucho.hessian.client.HessianProxyFactory#setReadTimeout
*/
public void setReadTimeout(long timeout) {
this.proxyFactory.setReadTimeout(timeout);
}
/**
* Set whether version 2 of the Hessian protocol should be used for
* parsing requests and replies. Default is "false".
*
* @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Request
*/
public void setHessian2(boolean hessian2) {
this.proxyFactory.setHessian2Request(hessian2);
this.proxyFactory.setHessian2Reply(hessian2);
}
/**
* Set whether version 2 of the Hessian protocol should be used for
* parsing requests. Default is "false".
*
* @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Request
*/
public void setHessian2Request(boolean hessian2) {
this.proxyFactory.setHessian2Request(hessian2);
}
/**
* Set whether version 2 of the Hessian protocol should be used for
* parsing replies. Default is "false".
*
* @see com.caucho.hessian.client.HessianProxyFactory#setHessian2Reply
*/
public void setHessian2Reply(boolean hessian2) {
this.proxyFactory.setHessian2Reply(hessian2);
}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
prepare();
}
/**
* Initialize the Hessian proxy for this interceptor.
*
* @throws RemoteLookupFailureException
* if the service URL is invalid
*/
public void prepare() throws RemoteLookupFailureException {
try {
this.hessianProxy = createHessianProxy(this.proxyFactory);
}
catch (MalformedURLException ex) {
throw new RemoteLookupFailureException("Service URL [" + getServiceUrl() + "] is invalid", ex);
}
}
/**
* Create the Hessian proxy that is wrapped by this interceptor.
*
* @param proxyFactory
* the proxy factory to use
* @return the Hessian proxy
* @throws MalformedURLException
* if thrown by the proxy factory
* @see com.caucho.hessian.client.HessianProxyFactory#create
*/
protected Object createHessianProxy(HessianProxyFactory proxyFactory) throws MalformedURLException {
Assert.notNull(getServiceInterface(), "'serviceInterface' is required");
return proxyFactory.create(getServiceInterface(), getServiceUrl());
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (this.hessianProxy == null) {
throw new IllegalStateException("HessianClientInterceptor is not properly initialized - "
+ "invoke 'prepare' before attempting any operations");
}
ClassLoader originalClassLoader = overrideThreadContextClassLoader();
try {
return invocation.getMethod().invoke(this.hessianProxy, invocation.getArguments());
}
catch (InvocationTargetException ex) {
Throwable targetEx = ex.getTargetException();
// Hessian 4.0 check: another layer of
// InvocationTargetException.
if (targetEx instanceof InvocationTargetException) {
targetEx = ((InvocationTargetException) targetEx).getTargetException();
}
if (targetEx instanceof HessianConnectionException) {
throw convertHessianAccessException(targetEx);
}
else if (targetEx instanceof HessianException || targetEx instanceof HessianRuntimeException) {
Throwable cause = targetEx.getCause();
throw convertHessianAccessException(cause != null ? cause : targetEx);
}
else if (targetEx instanceof UndeclaredThrowableException) {
UndeclaredThrowableException utex = (UndeclaredThrowableException) targetEx;
throw convertHessianAccessException(utex.getUndeclaredThrowable());
}
else {
throw targetEx;
}
}
catch (Throwable ex) {
throw new RemoteProxyFailureException("Failed to invoke Hessian proxy for remote service [" + getServiceUrl() + "]", ex);
}
finally {
resetThreadContextClassLoader(originalClassLoader);
}
}
/**
* Convert the given Hessian access exception to an appropriate Spring
* RemoteAccessException.
*
* @param ex
* the exception to convert
* @return the RemoteAccessException to throw
*/
protected RemoteAccessException convertHessianAccessException(Throwable ex) {
if (ex instanceof HessianConnectionException || ex instanceof ConnectException) {
return new RemoteConnectFailureException("Cannot connect to Hessian remote service at [" + getServiceUrl() + "]", ex);
}
else {
return new RemoteAccessException("Cannot access Hessian remote service at [" + getServiceUrl() + "]", ex);
}
}
/**
* 连接超时配置
*
* @param timeout
*/
public void setConnectTimeout(long timeout) {
this.proxyFactory.setConnectTimeout(timeout);
}
}
相关推荐
Spring框架是Java开发中广泛应用的一个开源框架,以其强大的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)功能而著名。本篇文章将详细解析Spring框架的初始化过程,...
《Spring3.x企业应用开发实战》是一本深入探讨Spring框架在实际项目中应用的书籍,其源代码提供了读者动手实践的机会,与书中的讲解相辅相成,加深理解。源代码按照章节进行组织,便于读者根据阅读进度或兴趣点进行...
在本项目"springboot-dubbo整合框架2"中,我们主要关注的...开发者可以通过这个项目学习到如何在Spring Boot中配置和使用Dubbo,以及如何进行服务的注册、发现、调用和治理,从而提升自己的微服务架构设计和实施能力。
【标题】"zk+dubbo+spring本地工程"指的是一个整合了Zookeeper、Dubbo和Spring框架的本地开发环境。这个项目可能是一个分布式服务治理的示例或者开发模板,旨在帮助开发者快速搭建具备服务注册与发现、远程调用等...
在IT行业中,Spring Boot和Dubbo的整合是一个常见的微服务架构设计,而Zookeeper作为服务治理的工具,是实现这一整合的重要组成部分。本项目“dubbotest1.rar”显然是一个关于这三者结合的实践案例,下面我们将深入...
这是一个基于IntelliJ IDEA(简称Idea)17版本,使用Java 8开发的Spring Boot、Dubbo和Zookeeper整合的简单应用示例项目。这个压缩包中的内容可能包括了项目的基本结构、配置文件、源代码以及必要的依赖库。下面我们...
这个标题和描述涉及到的是一个关于Dubbo框架的代码库,它显然已经被打包成压缩文件,名为“ssm_dubbo”,暗示这可能是一个整合了Spring、SpringMVC和Dubbo的项目。Dubbo是一个高性能、轻量级的开源Java RPC框架,它...
这个框架的整合使得开发者能够更方便地实现业务逻辑和数据访问,尤其在处理分布式系统中的客户管理资源时,其优势更为显著。 **Spring框架**:Spring作为核心容器,负责管理应用对象(Bean)的生命周期和依赖注入。...
2.完成hessian+spring+hibernate整合,提供建筑信息和公司信息hessian查找服务 2009-12-23 1.配置hessian服务端缓存 2.配置hessian日志记录,输出到文件/log/wzucxd/html 3.完成建筑信息显示页,配置2级缓存 4.配置...
- **Spring整合**:Dubbo可以很好地与Spring框架集成,通过XML配置或注解实现服务的发布和引用。 - **Hessian/Protobuf序列化**:支持多种序列化方式,提高数据传输效率。 - **Zookeeper作为注册中心**:...
在这个项目中,你可以找到关于如何实现和使用这些框架的重要知识点。 1. **Spring框架**:Spring是Java企业级应用开发中的基石,它的核心特性包括依赖注入(DI)和面向切面编程(AOP)。通过DI,Spring可以帮助我们...