在项目开发中,使用sap服务器进行系统开发。由于编写的是webservice,所以启动的时候要加载spring的类,而sap服务器在这时候就会出现无法获得spring工厂中的类,万分头疼。
解决方案就是最上方的webservice不要去依赖注入spring的类,而是要在方法中取获取该spring工厂中的类。
问题又出现了,spring工厂提供的类不能去new,只能通过其他途径去获取了。
有人说:好,写一个工厂类BeanFactory,内部使用ClassPathXmlApplicationContext类加载spring的配置文件,从而获得需要的类。
可是项目是web项目,如果再使用这样的加载机制就会出现spring工厂不单一的情况,获得的类也可能不是单一的。所以我们要从web方面处理。
首先,如果你是这样直接使用的话,对象是空的,如下图,moneyuserDAO是无法直接使用的,即使spring已经对其进行加载,但是在webservice中是不能直接使用的,但是spring加载的访问数据库持久层的DAO对象等会存储在WebApplicationContext中,那么我有了以下的方式
解决方案:
一、编写ServicesSingleton,代码如下:
package com.common.bssp.home.servlet; import org.springframework.web.context.WebApplicationContext; public class ServicesSingleton { private WebApplicationContext servletContext; private volatile static ServicesSingleton singleton; public WebApplicationContext getServletContext() { return servletContext; } public void setServletContext(WebApplicationContext servletContext) { this.servletContext = servletContext; } private ServicesSingleton() { } public static ServicesSingleton getInstance() { if (singleton == null) { synchronized (ServicesSingleton.class) { if (singleton == null) { singleton = new ServicesSingleton(); } } } return singleton; } public Object getDAO(Class<?> classNameOfDAO) { String implName = classNameOfDAO.getSimpleName(); String firstChar = implName.substring(0, 1); // implName = firstChar.toLowerCase() + implName.substring(1) + "Impl"; implName = implName.substring(1) + "Impl"; return singleton.getServletContext().getBeansOfType(classNameOfDAO).get(implName); } }
然后编写初始化InitServlet,代码如下:
package com.common.bssp.home.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; public class InitServlet extends HttpServlet { private static final long serialVersionUID = -3962535683227715257L; @Override public void init() throws ServletException { System.out.println("=============================init InitServlet ===================="); WebApplicationContext ctx = WebApplicationContextUtils .getRequiredWebApplicationContext(getServletContext()); ServicesSingleton.getInstance().setServletContext(ctx); } public InitServlet() { super(); } public void destroy() { super.destroy(); } }
上面的代码就是将spring工厂存放在ServicesSingleton的变量中。
最后编写web.xml把InitServlet添加进去,需要load-on-startup值为1代码如下:
<servlet> <servlet-name>InitServlet</servlet-name> <servlet-class>com.common.bssp.home.servlet.InitServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
需要在XML中显式声明bean,ssoDao不能用注解
<bean id="ssoDao" class="com.common.bssp.home.dao.impl.SsoDaoImpl"> </bean>
CXF配置:
<jaxws:endpoint address="/SsoService" implementorClass="com.common.bssp.home.webservice.impl.SSOServiceImpl" />
使用示例:
private ISsoDao ssoDao ; public String acceptPublicKey(@WebParam(name="key")String key) { ServicesSingleton single = ServicesSingleton.getInstance(); ssoDao = (SsoDaoImpl)single.getServletContext().getBean("ssoDao"); if(key!=null && key.length()>0) { //保存到数据库 PublicKey publicKey = new PublicKey(); publicKey.setPublicKey(newKey); publicKey.setGenericDate(new Date()); this.ssoDao.save(publicKey);
启动Tomcat则自动发布webservice。测试代码:
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import com.common.bssp.home.webservice.SSOService; public class Client { // private final static String ADDRESS = "http://localhost:8080/BSSP/services/SSOService"; private final static String ADDRESS = "http://localhost:8080/BSSP/services/SsoService"; public static void main(String args[]) { JaxWsProxyFactoryBean jwpFactory = new JaxWsProxyFactoryBean(); jwpFactory.setAddress(ADDRESS); jwpFactory.setServiceClass(SSOService.class); SSOService hw = (SSOService)jwpFactory.create(); String response = hw.acceptPublicKey("key124"); System.out.println(response); } }