JBoss下布署Spring2.5和Struts2系统

    技术2022-06-09  88

    目前在做JBoss下布署String2.5 & Struts2集成的工程,在工程中用Spring2.5 的component scan, Struts2 的convention 和 rest plugins。在JBoss下部署都有问题: Spring 2.5 component scan所有annotation标注的component都无法找到。原因是JBoss用了VFS,所以在Spring中找不到。 解 决方法:使用jboss的 spring-int-vfs 中提供的 org.jboss.spring.vfs.context.VFSClassPathXmlApplicationContext。这个包可以在 http://sourceforge.net/projects/jboss/files/JBoss-Spring Integration/ 下载到,在页面中部,可以找到JBoss-Spring Integration。下面是我的一段代码:                 ApplicationContext appContext = null;         switch(serverType) {         case tomcat:             appContext = new ClassPathXmlApplicationContext(configFiles);             break;         case jboss:             appContext = new VFSClassPathXmlApplicationContext(configFiles);             break;         } Struts2 convention, 原因也是JBoss用了VFS,于是URL的protocol都变成了vfsfile, vfszip等等。查看xword的源码,在类com.opensymphony.xwork2.util.finder.ClassFinder的 122行左右,里面是写死的,"jar".equals(location.getProtocol(),  "file".equals(location.getProtocol()。 解决方法:由于不能影响到非jboss server,如tomcat,所以不好改写ClassFinder。采用改写struts2 convention插件的方案,替换org.apache.struts2.convention.ActionConfigBuilder如下: File: src/plugins/convention/src/main/resources/struts-plugin.xml <bean type="org.apache.struts2.convention.ActionConfigBuilder" class="com.playphone.struts.convention.MyActionConfigBuilder"/> MyActionConfigBuilder类的内容如下,这里只是简单的解析WEB-INF/classes下的类,因为我没用到jar包需要被认为action的情况,所以简化。 package com.playphone.struts.convention; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts2.convention.ActionNameBuilder; import org.apache.struts2.convention.InterceptorMapBuilder; import org.apache.struts2.convention.PackageBasedActionConfigBuilder; import org.apache.struts2.convention.ResultMapBuilder; import org.apache.struts2.convention.StringTools; import com.opensymphony.xwork2.ObjectFactory; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.inject.Inject; import com.opensymphony.xwork2.util.finder.ClassFinder; import com.opensymphony.xwork2.util.finder.Test; import com.playphone.spring.EnvVariable; import com.playphone.spring.ServerType; /** * Solve the problem that could not found action under JBoss. * * @author <a href="mailto:sunyi4j@gmail.com">Roy</a> on Jul 6, 2009 */ public class MyActionConfigBuilder extends PackageBasedActionConfigBuilder { private static Log log = LogFactory.getLog(MyActionConfigBuilder.class); private static final String BASE_FILE = "appContext.xml";     private String[] actionPackages;     private String[] packageLocators; /**      * Constructs actions based on a list of packages.      *      * @param configuration         The XWork configuration that the new package configs and action configs      *                              are added to.      * @param actionNameBuilder     The action name builder used to convert action class names to action      *                              names.      * @param resultMapBuilder      The result map builder used to create ResultConfig mappings for each      *                              action.      * @param interceptorMapBuilder The interceptor map builder used to create InterceptorConfig mappings for each      *                              action.      * @param objectFactory         The ObjectFactory used to create the actions and such.      * @param redirectToSlash       A boolean parameter that controls whether or not this will create an      *                              action for indexes. If this is set to true, index actions are not created because      *                              the unknown handler will redirect from /foo to /foo/. The only action that is created      *                              is to the empty action in the namespace (e.g. the namespace /foo and the action "").      * @param defaultParentPackage  The default parent package for all the configuration.      */     @Inject     public MyActionConfigBuilder(             Configuration configuration,             ActionNameBuilder actionNameBuilder,             ResultMapBuilder resultMapBuilder,             InterceptorMapBuilder interceptorMapBuilder,             ObjectFactory objectFactory,                                     @Inject("struts.convention.redirect.to.slash") String redirectToSlash,                                     @Inject("struts.convention.default.parent.package") String defaultParentPackage) {      super(        configuration,        actionNameBuilder,        resultMapBuilder,        interceptorMapBuilder,        objectFactory,        redirectToSlash,        defaultParentPackage);     }         /**      * @param actionPackages (Optional) An optional list of action packages that this should create      *                       configuration for.      */     @Inject(value = "struts.convention.action.packages", required = false)     public void setActionPackages(String actionPackages) {      super.setActionPackages(actionPackages);         if (!StringTools.isTrimmedEmpty(actionPackages)) {             this.actionPackages = actionPackages.split("//s*[,]//s*");         }     }     /**      * @param packageLocators (Optional) A list of names used to find action packages.      */     @Inject(value = "struts.convention.package.locators", required = false)     public void setPackageLocators(String packageLocators) {      super.setPackageLocators(packageLocators);         this.packageLocators = packageLocators.split("//s*[,]//s*");     }     @Override @SuppressWarnings("unchecked") protected Set<Class> findActions() {   if(EnvVariable.getServerType() == ServerType.tomcat) {    return super.findActions();   } else {    Set<Class> classes = new HashSet<Class>();    try {     ClassFinder finder = new ClassFinder(getClassLoaderForFinder(), buildUrls(), true);     // named packages     if (actionPackages != null) {      for (String packageName : actionPackages) {       Test<ClassFinder.ClassInfo> test = getPackageFinderTest(packageName);       classes.addAll(finder.findClasses(test));      }     }     // package locators     if (packageLocators != null) {      for (String packageLocator : packageLocators) {       Test<ClassFinder.ClassInfo> test = getPackageLocatorTest(packageLocator);       classes.addAll(finder.findClasses(test));      }     }    } catch (Exception ex) {     if (log.isErrorEnabled()) {      log.error("Unable to scan named packages", ex);     }    }    return classes;   } }     private List<URL> buildUrls() throws MalformedURLException {   List<URL> urls = new ArrayList<URL>();   URL classesUrl = getClassLoader().getResource(BASE_FILE);   if(classesUrl == null) {    throw new IllegalStateException("File appContext.xml was not found. The folder WEB-INF/classes discovery base on file classes/appContext.xml.");   }   String baseFilePath = classesUrl.getFile();   URL url = new URL("file", "", baseFilePath.substring(0, baseFilePath.indexOf(BASE_FILE)));   if (log.isInfoEnabled()) {    log.info("Struts2 ActionConfigBuilder, classes directory: " + url.getFile());   }     urls.add(url);   return urls; }         private ClassLoader getClassLoader() {      return Thread.currentThread().getContextClassLoader();     }     } 为了调试方便,可以打开org.apache.struts2.convention log level为debug,然后你就可以清晰地看到哪些action被认出来了。


    最新回复(0)