- 浏览: 96332 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
former:
neebe 写道楼主,能否提供完整的代码,这对我们新手而言,有 ...
在spring security3上实现验证码 -
neebe:
楼主,能否提供完整的代码,这对我们新手而言,有点无头无绪的感觉 ...
在spring security3上实现验证码 -
bin_1715575332:
运行前需要添加什么东西么,能否提供和联系方式?请求一下
在Eclipse中使用resin调试maven war项目 -
bin_1715575332:
还是有点不太懂。。。
在Eclipse中使用resin调试maven war项目 -
former:
crazoy 写道这点我非常认同。比如有的求职者会写“精通Ja ...
《软件人才管理的艺术》中的看简历的技巧
最近在处理web services时用到apache xmlrpc,这里简单总结一下。
1.选用xml rpc
web services有很多种实现,这里选用xml rpc的是因为公司各个项目都支持xml rpc的调用,其他的web services实现并非完全支持;xml rpc与平台无关;xml rpc可以保证项目与项目之间的无侵入性。
2.spring bean
由于目前的业务组件都由spring container去管理、增强,所以理想的实现是在xml rpc的server端作为服务的beans都由spring container提供。但是 xml rpc server端的默认实现中,服务beans都由classloader去加载,代码如下:
//org.apache.xmlrpc.server.PropertyHandlerMapping public void load(ClassLoader pClassLoader, Map pMap) throws XmlRpcException { for (Iterator iter = pMap.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); Class c = newHandlerClass(pClassLoader, value); registerPublicMethods(key, c); } }
//org.apache.xmlrpc.metadata.Util /** * Creates a new instance of <code>pClass</code>. */ public static Object newInstance(Class pClass) throws XmlRpcException { try { return pClass.newInstance(); } catch (InstantiationException e) { throw new XmlRpcException("Failed to instantiate class " + pClass.getName(), e); } catch (IllegalAccessException e) { throw new XmlRpcException("Illegal access when instantiating class " + pClass.getName(), e); } }
这样取得一个bean的实例并不能满足我们的要求,例如我们取的bean不能通过依赖注入得到相关属性;不能通过spring中设置的aop切面做动态的增强…………
有鉴于此,我们有必要自己实现一个xml rpc server的factorybean,并将其交由spring container管理。代码如下:
/** * <li>xmlrpc server 工厂</li> * * @author yangpeng 2008-8-1 上午09:18:34 */ public class XmlRpcServletServerFactoryBean extends ApplicationObjectSupport implements FactoryBean, InitializingBean { private XmlRpcServletServer server; /** XmlRpcServletServer的属性集合 */ private Map<String, String> serverProperties; /** 是否在父BeanFactory中寻找xml rpc services */ private boolean detectServersInAncestorContexts = false; private AbstractReflectiveHandlerMapping.AuthenticationHandler authenticationHandler; private RequestProcessorFactoryFactory requestProcessorFactoryFactory; private TypeConverterFactory typeConverterFactory; protected Log log = LogFactory.getLog(XmlRpcServletServerFactoryBean.class); public Object getObject() throws Exception { return server; } public Class<?> getObjectType() { return XmlRpcServletServer.class; } public boolean isSingleton() { return true; } public void afterPropertiesSet() throws Exception { server = new XmlRpcServletServer(); initServerProperties(); server.setHandlerMapping(newXmlRpcHandlerMapping()); } protected void initServerProperties() { if (null != serverProperties) { Set<String> keys = serverProperties.keySet(); for (String key : keys) { String value = serverProperties.get(key); try { if (!ReflectionUtil.setProperty(this, key, value) && !ReflectionUtil.setProperty(server, key, value) && !ReflectionUtil.setProperty(server.getConfig(), key, value)) { throw new BeanInitializationException("key:" + key + ";value:" + value + " is wrong property!"); } } catch (IllegalAccessException e) { log.error(e); throw new BeanInitializationException("key:" + key + ";value:" + value + " is wrong property!"); } catch (InvocationTargetException e) { log.error(e); throw new BeanInitializationException("key:" + key + ";value:" + value + " is wrong property!"); } } } } protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() throws XmlRpcException { SpringPropertyHandlerMapping mapping = new SpringPropertyHandlerMapping(); mapping.setAuthenticationHandler(authenticationHandler); if (requestProcessorFactoryFactory != null) { mapping .setRequestProcessorFactoryFactory(requestProcessorFactoryFactory); } if (typeConverterFactory != null) { mapping.setTypeConverterFactory(typeConverterFactory); } else { mapping.setTypeConverterFactory(server.getTypeConverterFactory()); } mapping.setVoidMethodEnabled(server.getConfig() .isEnabledForExtensions()); mapping.addHandler(detectServersInAncestorContexts, getApplicationContext()); return mapping; } //省略getter、setter }
SpringPropertyHandlerMapping继承于PropertyHandlerMapping,重载addHandler方法,将ApplicationContext作为参数传入,addHandler中的实现类似于spring2.5 MVC中查找声明@controller的Controller类的实现。为了能获得这样的效果,我们先要定义两个Annotation:
/** * <li>xml rpc service 注解</li> * * @author yangpeng 2008-8-1 下午03:37:34 */ @Target( { ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface XmlRpcService { /** * value为空则xml rpc service的名称默认使用sping bean的id。否则使用value */ String value() default ""; /** * 是否使用方法注解 * * @return false:默认服务组件中的所有公共方法都作为xml rpc的服务方法 <br> * true:在服务组件 */ boolean useMethodAnnotation() default false; }
/** * <li>标注此方法会作为xmlrpc server的响应方法</li> * * @author yangpeng 2008-8-1 下午03:33:12 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface XmlRpcMethod { String value() default ""; }
接着来看看SpringPropertyHandlerMapping,在这里它是核型:
/** * <li>注册spring bean的HandlerMapping</li> * * @author yangpeng 2008-8-1 上午10:42:21 */ public class SpringPropertyHandlerMapping extends PropertyHandlerMapping { public void addHandler(boolean detectServersInAncestorContexts, final ApplicationContext context) throws XmlRpcException { Assert.notNull(context, "context must not be null!"); String[] beanNames = (detectServersInAncestorContexts ? BeanFactoryUtils .beanNamesForTypeIncludingAncestors(context, Object.class) : context.getBeanNamesForType(Object.class)); for (String beanName : beanNames) { registerPublicMethods(beanName, context); } } @SuppressWarnings( { "unchecked", "unchecked" }) protected void registerPublicMethods(String beanName, final ApplicationContext context) throws XmlRpcException { Class<?> serviceType = context.getType(beanName); XmlRpcService service = AnnotationUtils.findAnnotation(serviceType, XmlRpcService.class); if (service == null && context instanceof ConfigurableApplicationContext && context.containsBeanDefinition(beanName)) { ConfigurableApplicationContext cac = (ConfigurableApplicationContext) context; BeanDefinition bd = cac.getBeanFactory().getMergedBeanDefinition( beanName); if (bd instanceof AbstractBeanDefinition) { AbstractBeanDefinition abd = (AbstractBeanDefinition) bd; if (abd.hasBeanClass()) { Class<?> beanClass = abd.getBeanClass(); serviceType = beanClass;// 得到被代理对象 service = AnnotationUtils.findAnnotation(beanClass, XmlRpcService.class); } } } if (service != null) { Map map = new HashMap(); Method[] methods = serviceType.getMethods(); for (Method method : methods) { if (!isHandlerMethod(service.useMethodAnnotation(), method)) { continue; } String serviceName = StringUtils.isEmpty(service.value()) ? beanName : service.value(); String name = serviceName + "." + method.getName(); Method[] mArray; Method[] oldMArray = (Method[]) map.get(name); if (oldMArray == null) { mArray = new Method[] { method }; } else { mArray = new Method[oldMArray.length + 1]; System.arraycopy(oldMArray, 0, mArray, 0, oldMArray.length); mArray[oldMArray.length] = method; } map.put(name, mArray); } for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); String name = (String) entry.getKey(); Method[] mArray = (Method[]) entry.getValue(); handlerMap.put(name, newXmlRpcHandler( context.getBean(beanName), mArray)); } } } protected XmlRpcHandler newXmlRpcHandler(final Object bean, final Method[] pMethods) throws XmlRpcException { String[][] sig = getSignature(pMethods); String help = getMethodHelp(bean.getClass(), pMethods); if (sig == null || help == null) { return new SpringXmlRpcHandler(this, getTypeConverterFactory(), bean, pMethods); } return new SpringReflectiveXmlRpcMetaDataHandler(this, getTypeConverterFactory(), bean, pMethods, sig, help); } protected boolean isHandlerMethod(boolean useMethodAnnotation, Method method) { if (useMethodAnnotation) { XmlRpcMethod xmlRpcMethod = AnnotationUtils.getAnnotation(method, XmlRpcMethod.class); if (null == xmlRpcMethod) { return false; } } return super.isHandlerMethod(method); } }
简单解释一下。SpringPropertyHandlerMapping遍历spring container中所有注册的beans,查找使用了@XmlRpcService注解的bean(无论其是否被代理)。对于这样的bean认为提供xml rpc服务,然后查找其声明的xml rpc服务方法。默认情况下,其所有的public、非static、非Object类方法的方法都会被当作xml rpc的服务方法(有点拗口)。如果在XmlRpcService注解中声明useMethodAnnotation为true,则其method除了要满足以上条件外,还要必须声明XmlRpcMethod注解才会被认为是xml rpc的服务方法。
SpringXmlRpcHandler与SpringReflectiveXmlRpcMetaDataHandler都非常简单,类似于默认实现的ReflectiveXmlRpcHandler、ReflectiveXmlRpcMetaDataHandler,这里就不多展开演示了。
3.例子
server1:
使用spring自带的petclinic,为业务实现一个xml rpc的faced:
package org.springframework.samples.petclinic.xmlrpcfaced; import java.util.Collection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.samples.petclinic.Clinic; import org.springframework.samples.petclinic.PetType; import xmlrpc.annotation.XmlRpcService; @XmlRpcService public class PetFaced { @Autowired Clinic clinic; public String getPetTypesName() { Collection<PetType> types = clinic.getPetTypes(); String typesName = ""; for (PetType petType : types) { typesName += petType.getName() + ","; } return typesName; } }
springcontext:
<bean id="rpcServer" class="xmlrpc.server.XmlRpcServletServerFactoryBean"> <property name="serverProperties"> <map> <entry key="enabledForExtensions" value="true"></entry> </map> </property> </bean>
最后实现一个测试filter:
public class SpringXmlRpcFilter extends OncePerRequestFilter { public static final String DEFAULT_XML_RPC_SERVIER_NAME = "xmlRpcServer"; private String servierName = DEFAULT_XML_RPC_SERVIER_NAME; private XmlRpcServletServer server; /* * (non-Javadoc) * * @see org.springframework.web.filter.OncePerRequestFilter#doFilterInternal(javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse, javax.servlet.FilterChain) */ @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { server.execute(request, response); // filterChain.doFilter(request, response); } /* * (non-Javadoc) * * @see org.springframework.web.filter.GenericFilterBean#initFilterBean() */ @Override protected void initFilterBean() throws ServletException { WebApplicationContext wac = WebApplicationContextUtils .getRequiredWebApplicationContext(getServletContext()); server = (XmlRpcServletServer) wac.getBean(servierName, XmlRpcServletServer.class); } public String getServierName() { return servierName; } public void setServierName(String servierName) { this.servierName = servierName; } }
server2:
使用被spring container代理过的service、具有事务属性的bean作为xml rpc的service
@XmlRpcService(useMethodAnnotation = true) @Transactional public class HibernateClinic implements Clinic { @Autowired private SessionFactory sessionFactory; @XmlRpcMethod @Transactional(readOnly = true) public String getTypeName(int id) throws DataAccessException { return String.valueOf(sessionFactory.getCurrentSession().createQuery( "select name from PetType type where id = ?").setInteger(0, id) .uniqueResult()); } //其他方法省略 }
其他地方都一样,只是省略了faced。
个人总结
xml rpc的明显局限是对于复杂、用户自定义java bean的支持很弱,只支持一些基本的类型。
性能方面我没有做过测试,不能乱讲。
目前3.1的发布版本的客户端代码的默认实现有线程不安全的bug,这个问题在后来的2007年10月份的版本中才被修复,但是提供给大家下载的版本为8月份的版本,一个有问题的版本,大家注意了!
那个filter有个小问题不知道大家发现了没有,就是如果使用filterChain.doFilter(request, response);这句代码程序会报异常,具体原因我没仔细查,建议大家写个servlet做代替,文档中也是用servlet去做的。
后记
补充一个xml rpc client的包装类,使得客户端也可以通过spring容器管理,注入到需要的service中。详见附件。
- xmlrpc_with_spring_beans.rar (6.5 KB)
- 下载次数: 154
- xml_rpc_spring_client.rar (2 KB)
- 下载次数: 94
评论
学习ing
强在哪里呢?
不要这样说。。。
能让你有所收获即可。。。
学习ing
<pre name='code' class='java'>public class XmlRpcServletServerFactoryBean implements FactoryBean,
InitializingBean {
@Resource
private ApplicationContext context;
//........
}</pre>
<p>取消对ApplicationObjectSupport.java的继承。</p>
发表评论
-
在多数据源(JTA)环境下使用Spring TestContext Framework
2010-08-09 10:26 2215项目背景 从08年开始 ... -
在spring security3上实现验证码
2010-07-25 17:24 4322关于验证码的实现 验证码的例子现在多如牛毛,大家google ... -
对Hibernate Session做一个简单的包装
2010-05-27 11:48 1293在谈包装之前,我们先看一看以下几个论断: 牛人们都说da ... -
spring3.0 rest在resin中的实现
2010-05-21 11:36 2736spring3.0发布后,其web方面一个很大的特性是支持re ... -
在Eclipse中使用resin调试maven war项目
2010-05-21 10:55 7102公司现在使用无版权问题的Eclipse环境,同时希望将目前手工 ... -
Ehcache定时刷新
2007-04-20 11:22 12394之前的文章介绍了在项目里使用Ehcache的经历,现在它可以很 ... -
使用EhCache1.1与Hibernate所吃的亏
2007-03-27 14:18 7684“偶们的系统越来越慢了!”,这是最近一直在我耳边萦绕的一句话, ... -
Eclipse里exadel studio pro与其他工具的冲突
2007-03-16 10:34 2980在之前的文章中写道exadel现在与jboss合作,旗下的ex ... -
自己做的Ajax4Jsf 的几个小例子
2007-03-09 16:57 9857JSF好像充满了争议,被很多Java大牛们所抱怨,而很多主流厂 ... -
exadel与jboss合作开源
2007-03-06 10:51 1848ajax4jsf选择与jboss合作开源了,详细链接 http ...
相关推荐
sping3 spring-beans 类图 chm
Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2Sping视频2
在探讨“spring中xml文件不提示”的问题时,我们首先需要理解Spring框架的基本概念以及XML配置文件在其中扮演的角色。Spring框架是一个开源的轻量级Java应用框架,旨在简化企业级应用开发。它通过依赖注入(DI)和...
它的配置可以通过XML或.properties文件进行,方便调整日志行为。 在实际开发中,Spring的jar包通常会被引入到项目的类路径中,通过Maven或Gradle等构建工具管理依赖。开发人员可以利用Spring提供的注解驱动开发,...
例如,XML配置文件(如`beans.xml`)可能会这样写: ```xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=...
mybatis+sping mvc mybatis+sping mvcmybatis+sping mvc mybatis+sping mvcmybatis+sping mvc mybatis+sping mvcmybatis+sping mvc mybatis+sping mvcmybatis+sping mvc mybatis+sping mvc
1. **spring-beans-2.5.6.jar**:这是 Spring 的核心库之一,主要用于 Bean 的生命周期管理和依赖注入。Bean 是 Spring 中的基本单元,代表应用程序中的对象。这个 jar 包包含了 Bean 定义、配置元数据解析以及 Bean...
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop=...
sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术sping 技术
sping+spingmvc+hibernate 在学习的时候毕业前夕自己根据资料和以前自己写的项目整合的套,对包哪些进行了选择,主要对事物aop的配置进行了配置,个人感觉不错,共享下,另外还对spingmvc,mybatis的整合项目也有,在...
3. `src/main/resources`:资源文件夹,存放配置文件,如Spring的`applicationContext.xml`和`springmvc-dispatcher-servlet.xml`,以及MyBatis的`mybatis-config.xml`和Mapper接口对应的XML映射文件。 4. `src/main...
标题中的“Spring定时器的使用”指的是Spring框架中的任务调度功能,主要由Spring的`TaskExecution`和`TaskScheduling`模块提供。Spring通过`@Scheduled`注解和`TaskScheduler`接口,允许开发者轻松地实现定时任务,...
通过XML配置或者基于注解的方式,开发者可以声明对象及其依赖,由IoC容器负责创建和装配这些对象。这种方式降低了对象间的耦合性,使得代码更易于测试和维护。 AOP则提供了在不修改原有代码的情况下,插入额外功能...
《Spring 3经典教程》是IT领域内关于Spring框架的一部权威著作,由Gary Mak、Josh Long和Daniel Rubio三位专家联合编写。此书专为希望深入掌握Spring 3框架的开发者设计,通过一系列编码实例(coding recipes)来...
- **ConfigLoad.txt**:这可能是关于配置加载逻辑的文件,Spring支持通过XML、Java配置或@Configuration注解的方式来加载和管理配置。在这个场景下,它可能涉及到如何加载和使用上述的加密解密配置和数据库连接池...
最后,"HelloWorld"项目中的其他文件可能包括配置文件(如`servlet-context.xml`或`web.xml`)、测试类以及必要的依赖库。配置文件会定义DispatcherServlet、Controller的映射、过滤器的注册等。 总结,这个"Spring...
### Sping翻转控制器知识点详解 #### 一、Spring IoC 容器概述 ##### 1.1 控制反转(Inversion of Control, IoC)原理 - **定义**:控制反转是一种设计模式,用于降低代码之间的耦合度。在Spring框架中,IoC容器...
XML配置和基于注解的配置都是Spring中定义Bean的方式。 2. **依赖注入(Dependency Injection, DI)**:Spring通过DI实现了对象之间的松耦合。DI允许Spring框架在运行时将依赖关系传递给Bean,而不是由Bean自己去...