JBoss下布署Spring2.5和Struts2系统

转载于:http://www.diybl.com/course/3_program/java/javajs/20100719/460908.html

 

目前在做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%20Integration/
下载到,在页面中部,可以找到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:[email protected]">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被认出来了。

 

你可能感兴趣的:(spring,ClassLoader,struts,jboss,String,action)