上 一篇,写了struts2中的关键问题,至于详细的集成过程,我就不细表了,除了我描述的关键问题以外,其他的都雷同。下面说说Spring的集成,网上 搜的文章中大多介绍spring和struts2的集成,都是同一套路,将spring的配置往src根目录一扔,然后在web.xml中配个监听器,然 后在struts2的配置中增加struts.objectFactory的描述。就完了,虽然好用,但是都是照葫芦画瓢,不知所以然。其实struts 既然有这个个描述,那就意味着,struts2中所有实例的获取,都要通过这个定义的ObjectFactory来获取,工厂里用什么方式获取对象就和什 么集成,所以,和spring的集成关键不在web.xml的配置上,甚至web.xml上的监听可以完全不要。下面我们就来实际的做一下:编写 XKStrutsSpringObjectFactory继承SpringObjectFactory, 代码如下:
- public class XKStrutsSpringObjectFactory extends SpringObjectFactory
- {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- private static final Logger LOG = LoggerFactory.getLogger(XKStrutsSpringObjectFactory.class);
- @SuppressWarnings("deprecation")
- @Inject
- public XKStrutsSpringObjectFactory(@Inject(value = StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE, required = false) String autoWire,
- @Inject(value = StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT, required = false) String alwaysAutoWire,
- @Inject(value = StrutsConstants.STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE, required = false) String useClassCacheStr, @Inject ServletContext servletContext,
- @Inject(StrutsConstants.STRUTS_DEVMODE) String devMode, @Inject Container container)
- {
- super();
- boolean useClassCache = "true".equals(useClassCacheStr);
- if (LOG.isInfoEnabled())
- {
- LOG.info("Initializing Struts-Spring integration...");
- }
- // 关键代码
- Object rootWebApplicationContext = Initialization.getInstance().getApplicationContext();
- if (rootWebApplicationContext instanceof RuntimeException)
- {
- RuntimeException runtimeException = (RuntimeException) rootWebApplicationContext;
- LOG.fatal(runtimeException.getMessage());
- return;
- }
- ApplicationContext appContext = (ApplicationContext) rootWebApplicationContext;
- if (appContext == null)
- {
- // uh oh! looks like the lifecycle listener wasn't installed. Let's
- // inform the user
- String message = "********** FATAL ERROR STARTING UP STRUTS-SPRING INTEGRATION **********\n" + "Looks like the Spring listener was not configured for your web app! \n"
- + "Nothing will work until WebApplicationContextUtils returns a valid ApplicationContext.\n" + "You might need to add the following to web.xml: \n" + " <listener>\n"
- + " <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>\n" + " </listener>";
- LOG.fatal(message);
- return;
- }
- String watchList = container.getInstance(String.class, "struts.class.reloading.watchList");
- String acceptClasses = container.getInstance(String.class, "struts.class.reloading.acceptClasses");
- String reloadConfig = container.getInstance(String.class, "struts.class.reloading.reloadConfig");
- if ("true".equals(devMode) && StringUtils.isNotBlank(watchList) && appContext instanceof ClassReloadingXMLWebApplicationContext)
- {
- // prevent class caching
- useClassCache = false;
- ClassReloadingXMLWebApplicationContext reloadingContext = (ClassReloadingXMLWebApplicationContext) appContext;
- reloadingContext.setupReloading(watchList.split(","), acceptClasses, servletContext, "true".equals(reloadConfig));
- if (LOG.isInfoEnabled())
- {
- LOG.info("Class reloading is enabled. Make sure this is not used on a production environment!", watchList);
- }
- setClassLoader(reloadingContext.getReloadingClassLoader());
- // we need to reload the context, so our isntance of the factory is
- // picked up
- reloadingContext.refresh();
- }
- this.setApplicationContext(appContext);
- int type = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; // default
- if ("name".equals(autoWire))
- {
- type = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
- }
- else if ("type".equals(autoWire))
- {
- type = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
- }
- else if ("auto".equals(autoWire))
- {
- type = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
- }
- else if ("constructor".equals(autoWire))
- {
- type = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
- }
- else if ("no".equals(autoWire))
- {
- type = AutowireCapableBeanFactory.AUTOWIRE_NO;
- }
- this.setAutowireStrategy(type);
- this.setUseClassCache(useClassCache);
- this.setAlwaysRespectAutowireStrategy("true".equalsIgnoreCase(alwaysAutoWire));
- if (LOG.isInfoEnabled())
- {
- LOG.info("... initialized Struts-Spring integration successfully");
- }
- }
- }
关 键一步就在于第26行,那句代码,只要使用自己的方法获得applicationContext对象就行了。而Spring对于 ApplicationContext对象也提供了多种实现,既然咱们想自己定义配置的名称和位置,那么咱们就使用 FileSystemXmlApplicationContext,嗯,这个类的使用就不用我赘述了。很简单,实例化的时候将配置的路径传入就ok了。最 后在struts的配置中,将我们自己实现的工厂类应用上去,如:
- <constant name="struts.objectFactory" value="com.xk.commons.config.XKStrutsSpringObjectFactory" />
要 注意一点:代码71行中使用到了ClassReloadingXMLWebApplicationContext这个类,这个类的父类中会实现 FilesystemAlterationListener接口,这个接口在struts和spring提供的jar包中是找不到的,其包含在 apache的commons的jci库中,具体到jar包为commons-jci-fam-1.0.jar 下载地址:http://commons.apache.org/jci/downloads.html。
本文出自 “
My Joy is my joy ~”