在項目中使用了Apache xml-rpc,遇到了一個麻煩的問題。spring沒有提供對xml-rpc的支持,在處理webservice請求的時候,沒有辦法使用spring容器中管理的各種各樣的bean對象。顯然,這是不能接受的。
使用Apache xml-rpc,一般只需要在web.xml中定義一個servlet (XmlRpcServlet), 再實現用於處理webservice請求的組件類就可以了。
比如定義一個Servlet:
- <servlet>
- <servlet-name>XmlRpcServletservlet-name>
- <servlet-class>org.apache.xmlrpc.webserver.XmlRpcServletservlet-class>
- <init-param>
- <param-name>enabledForExtensionsparam-name>
- <param-value>trueparam-value>
- init-param>
- servlet>
實現處理webservice請求的組件:
- public class Calculator
- {
- public int add(int i1, int i2)
- {
- return i1 + i2;
- }
- }
除此之外,還需要定義一個property文件,告訴xml-rpc,在請求來了以後,用哪個組件去處理。這個property文件必須命名為XmlRpcServlet.properties,並且必須放到org.apache.xmlrpc.webserver包下面。
Properties代碼
Calculator=com.oyl.Calculator
這樣,當webservice收到請求后,就會初始化一個新的組件對象去處理請求。這樣,新的問題也來了,一般的web應用程序都使用spring來管理各個業務組件,通過上面的例子不難發現,www.linuxidc.com 我們沒有辦法使用spring管理的bean去處理webservice的請求,每次都初始化一個新的對象去處理請求,也會造成資源的浪費。
那麼,怎麼才能在xml-rpc中使用spring管理的bean去處理webservice的請求呢?
首先,要實現一個介面org.apache.xmlrpc.server.RequestProcessorFactoryFactory,這個介面類定義了如何創建對象去處理webservice請求:
- public class CustomRequestProcessorFactoryFactory implements
- RequestProcessorFactoryFactory
- {
- private final RequestProcessorFactory factory = new CustomRequestProcessorFactory();
- private final CustomWebServiceHandler service;
-
-
- public CustomRequestProcessorFactoryFactory(CustomWebServiceHandler service)
- {
- this.service = service;
- }
-
-
- @Override
- public RequestProcessorFactory getRequestProcessorFactory(Class arg0)
- throws XmlRpcException
- {
- return factory;
- }
-
- private class CustomRequestProcessorFactory implements
- RequestProcessorFactory
- {
-
- @Override
- public Object getRequestProcessor(XmlRpcRequest arg0)
- throws XmlRpcException
- {
- return service;
- }
-
- }
- }
仔細看代碼會發現,介面org.apache.xmlrpc.server.RequestProcessorFactoryFactory實際上就是一個工廠的工廠,它是一個用於創建處理webservice請求對象的工廠的工廠類。在上面的例子中,創建webservice請求對象的工廠類是一個實現了RequestProcessorFactory介面的內部類,它主要是返回我們真正需要用來處理請求的CustomWebServiceHandler對象。
有了上面這個工廠的工廠類,我們還需要擴展一下默認的XmlRpcServlet。主要是實現newXmlRpcHandlerMapping方法,在newXmlRpcHandlerMapping方法中,把需要用到的spring bean對象取出來,www.linuxidc.com再作為參數創建一個RequestProcessorFactoryFactory對象,就可以達到目的了。
- public class CustomXmlRpcServlet extends XmlRpcServlet
- {
- private static final long serialVersionUID = 8615627610262194L;
- protected static ApplicationContext ctx = null;
-
- public CustomXmlRpcServlet()
- {
- super();
- }
-
-
- public void init()
- {
- if (ctx == null)
- {
- ctx = WebApplicationContextUtils
- .getRequiredWebApplicationContext(this.getServletContext());
- }
- }
-
-
- protected XmlRpcHandlerMapping newXmlRpcHandlerMapping()
- throws XmlRpcException
- {
- PropertyHandlerMapping mapping = new PropertyHandlerMapping();
-
- CustomWebServiceHandler service = (CustomWebServiceHandler) ctx.getBean("customWebServiceHandler");
-
- mapping.setRequestProcessorFactoryFactory(new CustomRequestProcessorFactoryFactory(service));
- mapping.addHandler("CustomWebServiceHandler", CustomWebServiceHandler.class);
-
- return mapping;
- }
- }
這樣擴展以後,之前提到的XmlRpcServlet.properties文件也不再需要了。