我们公司在已经上生产的应用里面,已经使用了hessian作为远程调用的组件使用。后期我们在做业务拓展的时候,做了很多hessian远程调用。
先来介绍一下我们公司hessian远程调用的开发流程:
1.在common中定义接口service。
2.在server端定义实现类,serviceImpl。
3在server端的xml里面定义serviceImpl的代理类。
4.在web.xml中定义servlet将hessian暴露到外部。
5.在client端的xml中定义serviceProxy,传入的参数包括在common中接口,以及server端的url。
6在client端配置中添加server端的url。
开发人员在开发和维护的时候使用的是eclipse ,如果按照这种开发流程走的话,如果是想修改某个service的服务端的配置,我们打开文件查找器,输入hessian服务端xml名称,如果项目多的话会有多个,需要选择正确的一个。然后再打开service.java 拷贝名称 打开xml查找对应的bean。
总之一句话,使用xml配置,无论是开发还是维护还是比较繁琐的。
在来介绍一下我开发的hessian基于注解配置的开发流程:
1在common中定义service,并在service上写上注解;
2.在server端定义实现类,serviceImpl;
3.在client端需要使用的地方注入service;
4在properties文件中定义服务端的url;
如果需要修改bean的配置,只要ctrl+点击service找到注解就能完成修改。 虽然有些地方繁琐程度并没有减少,但是那些地方属于配置的范畴,随着业务的拓展维护的时间程度很低。
我认为如果使用hessian基于注解进行开发,开发效率会更高。
这里再介绍一下,hessian基于注解开发的要点,也是对spring深入探讨。
1.注解扫描
private Set<BeanDefinition> findCandidateComponents(String basePackage, Class<?> annClass)
{
Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
try {
String packageSearchPath = "classpath*:" + resolveBasePackage(basePackage) + "/" + "**/*.class";
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable())
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
GenericBeanDefinition definition = sbd;
Class<?> entityClazz = Class.forName(definition.getBeanClassName());
hessianService annotation = (hessianService)entityClazz.getAnnotation(hessianService.class);
if (annotation != null)
candidates.add(sbd);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);
}
}
}
catch (IOException ex)
{
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}
2.bean xml定义,实现相关接口完成相关动作
bean必须实现接口
public class HessianServerBuilder
implements InitializingBean{
public void afterPropertiesSet() throws Exception {
//在实例化完成后,在设置完预定义的属性之后该方法会被执行(无论是在xml中配置还是手动实例化bean都是同样的原则)
}
}
3.手动实例化bean
public void afterPropertiesSet() throws Exception {
// 从spring上下文件获取到bean工厂
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) this.applicationContext
.getAutowireCapableBeanFactory();
// 扫描获取bean定义,这里得到的是包含 @hessianService 注解的service接口 的bean定义
Set<BeanDefinition> candidateComponents = findCandidateComponents(this.basePackage, hessianService.class);
for (BeanDefinition beanDefinition : candidateComponents)
try {
GenericBeanDefinition definition = (GenericBeanDefinition) beanDefinition;
Class<?> serviceInterfaceClazz = Class.forName(definition.getBeanClassName());
hessianService annotation = (hessianService) serviceInterfaceClazz.getAnnotation(hessianService.class);
Object bean = null;
try {
bean = beanFactory.getBean(serviceInterfaceClazz);
} catch (Exception e) {
logger.info("创建hessian server 业务处理 bean时发生异常!");
e.printStackTrace();
}
if (bean != null) {
String beanName = annotation.id();
if (StringUtils.isBlank(beanName)) {
beanName = serviceInterfaceClazz.getSimpleName();
beanName = beanName.substring(0, 1).toLowerCase() + beanName.substring(1);
}
if (!beanFactory.containsBean(beanName)) {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
.rootBeanDefinition(HessianServiceExporter.class);
AbstractBeanDefinition beanProxyDefinition = beanDefinitionBuilder.getBeanDefinition();
// 设置value就相当于在xml中设置 <property name="service"
// ref="beanServiceName" />
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.addPropertyValue("service", bean);
propertyValues.addPropertyValue("serviceInterface", serviceInterfaceClazz);
beanProxyDefinition.setPropertyValues(propertyValues);
// 这一步是很关键的,如果beanFactory不是注册bean的 class 而是注册
// bean的定义definition
beanFactory.registerBeanDefinition("/" + beanName, beanProxyDefinition);
} else {
logger.debug("beanName:" + beanName + "对应的bean已经存在!");
}
logger.info("创建hessian server bean:" + beanName);
try {
// 这里就实例化生成了bean,如果不调用这个方法,那么如果bean在其他地方使用了,同样也是会被实例化的
HessianServiceExporter hessianServiceExporter = beanFactory.getBean("/" + beanName,
HessianServiceExporter.class);
HessianBeanFactory.addSingle("/" + beanName, hessianServiceExporter);
} catch (Exception e) {
logger.info("创建hessian server bean:" + "/" + beanName + " 时发生异常!");
e.printStackTrace();
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
后面再给出下载链接.骚等