根本原因是struts扫描action时扫描不到,因为springboot达成jar包时,读取class文件时,前缀是/BOOT-INF/classes/,而struts的ClassFinder扫描时,只将war包形式的前缀 /WEB-INF/classes/ 前缀处理掉,没处理 /BOOT-INF/classes/ 前缀。
war包的类路径,前缀
要处理成这种,com…
jar包的类路径,前缀
修改点,处理类名全路径:
改造方式:
struts.xml 配置
<struts>
...
<!-- 自定义classFinderFactory -->
<bean type="com.opensymphony.xwork2.util.finder.ClassFinderFactory" name="default" class="com.lii.pbs.bean.StrutsClassFinderFactory"/>
...
</struts>
自定义 classFinderFactory
// 自定义classFinderFactory
public class StrutsClassFinderFactory implements ClassFinderFactory {
@Override
public ClassFinder buildClassFinder(ClassLoaderInterface classLoaderInterface, Collection<URL> collection, boolean b, Set<String> set,
Test<String> test) {
// 生成自定义 classFinder
return new StrutsClassFinder(classLoaderInterface, collection, b, set, test);
}
}
自定义 classFinder
暂时无法重载DefaultClassFinder 解决此问题,如有更好的方式,欢迎赐教。
/**
* 解决打包为jar时,struts扫描class问题
* 无法用重载方式解决,只能拷贝全部代码
* 拷贝于 @see {@link org.apache.struts2.convention.DefaultClassFinder}
* 只修改了 {@link #jar(JarInputStream jarStream)}
*
**/
public class StrutsClassFinder implements ClassFinder {
...
private List<String> jar(JarInputStream jarStream) throws IOException {
List<String> classNames = new ArrayList<>();
JarEntry entry;
while ((entry = jarStream.getNextJarEntry()) != null) {
if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
continue;
}
String className = entry.getName();
className = className.replaceFirst(".class$", "");
//war files are treated as .jar files, so takeout WEB-INF/classes
className = StringUtils.removeStart(className, "WEB-INF/classes/");
// 修改这里
// 打包为jar时,className前缀为BOOT-INF/classes/,也要进行处理
className = StringUtils.removeStart(className, "BOOT-INF/classes/");
className = className.replace('/', '.');
classNames.add(className);
}
return classNames;
}
...
}
ok,打包为jar包运行就可以了。
相关包
PackageBasedActionConfigBuilder
顺便记录下idea远程调试jar
此命令启动jar
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -jar xxx.jar
在Idea新增 Run/Debug Configurations
debug运行即可。