使用struts2注解(struts2-convention-plugin-2.1.8.1)无配置开发的web项目,在tomcat里面运行没有问题,移植到jboss后出现:no result defined for action异常,无法访问action,上google查询资料,找到相应解决方案。 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 如下:
<bean type="org.apache.struts2.convention.ActionConfigBuilder" name="convention" class="com.sunyard.ices.web.actions.jxc.MyActionConfigBuilder"/>
MyActionConfigBuilder类的内容如下:
package com.sunyard.ices.web.actions.jxc;
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.PackageBasedActionConfigBuilder;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.finder.ClassFinder;
import com.opensymphony.xwork2.util.finder.Test;
public class MyActionConfigBuilder extends PackageBasedActionConfigBuilder {
private static Log log = LogFactory.getLog(MyActionConfigBuilder.class);
private static final String BASE_FILE = "struts.xml";
private String[] actionPackages;
private String[] packageLocators;
public static String classPath = "";
/**
*
* @param configuration
* @param container
* @param objectFactory
* @param redirectToSlash
* @param defaultParentPackage
*/
@Inject
public MyActionConfigBuilder(Configuration configuration, Container container, ObjectFactory objectFactory,
@Inject("struts.convention.redirect.to.slash") String redirectToSlash,
@Inject("struts.convention.default.parent.package") String defaultParentPackage) {
super(configuration, container, 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 (!"".equals(actionPackages.trim())) {
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() {
Set<Class> classes = new HashSet<Class>();
try {
// ClassFinder finder = new ClassFinder(getClassLoaderForFinder(), buildUrls(), true);
ClassFinder finder = new ClassFinder(getClassLoaderInterface(), buildUrls(), true);
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 " + BASE_FILE
+ " was not found. The folder WEB-INF/classes discovery base on file classes/" + BASE_FILE + ".");
}
String baseFilePath = classesUrl.getFile();
URL url = new URL("file", "", baseFilePath.substring(0, baseFilePath.indexOf(BASE_FILE)));
System.out.println(url);
if (log.isInfoEnabled()) {
classPath = url.getFile();
log.info("Struts2 ActionConfigBuilder, classes directory: " + classPath);
}
System.out.println("classPath = " + classPath);
System.out.println(url.toExternalForm());
urls.add(url);
return urls;
}
/*private ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}*/
}
,
上述解决了struts2注解开发方式无法访问action的问题
但是jboss对spring的支持也有问题,解决方案
需引入jboss-spring-int-vfs.jar
在web.xml 加入配置:
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.jboss.spring.vfs.context.VFSXmlWebApplicationContext
</param-value>
</context-param>
这样就不会有问题,如果要在tomcat运行需要去掉web的配置