2014-04-02 01:47:29

Jboss 6以上全局Filter加载顺序问题

在之前调试Tomcat的时候就已经发现了Tomcat存在此问题Tomcat7.0.30以上全局Filter加载顺序问题,今天调试Jboss6的时候也发现了同样的问题。原因很简单,Jboss沿用了Tomcat的内核,Servlet容器那块核心代码是使用的Tomcat源码。

既然知道问题所在那么现在的问题就是要找到之前调试Tomcat出问题的类和方法。根据我之前的记录,Tomcat 的Filter加载问题出现的位置大约是在“org.apache.catalina.core.ApplicationFilterRegistration.java的版本变动(修改74-78行、103-107行):Tomcat7.0.29的isMatchAfter判断的顺序反了。所以想办法把 顺序弄回去就行了。把context.addFilterMapBefore(filterMap);”。上一次我是改的catalina.jar的核心源码,所以在Jboss6目录搜索catalina.jar,发现没找到。搜catalina、Tomcat同样没找到对应的jar。估计是Jboss的开发人员把jar名改了,于是想写个递归遍历Jboss下所有的jar里面带有ApplicationFilterRegistration类或addFilterMapBefore方法的所有文件。

实现目录搜索jar和内容:

package jar;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.apache.commons.io.IOUtils;
public class Test {
	public static void getJarContent(File jarFile){
		try {
			JarFile jf = new JarFile(jarFile);
			Enumeration<JarEntry> je = jf.entries();
			while(je.hasMoreElements()){
				JarEntry jar = je.nextElement();
				if(!jar.isDirectory()){
					String str = IOUtils.toString(jf.getInputStream(jar));
					if(jarFile.toString().contains("ApplicationFilterRegistration")){
						System.out.println("ApplicationFilterRegistration:"+jarFile.toString()+":"+jar.getName());
					}else if(str.contains("addFilterMapBefore")){
						System.out.println("addFilterMapBefore:"+jarFile.toString()+":"+jar.getName());
					}
				}
			}
			jf.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void listFile(File f){
		File[] files = f.listFiles();
		for(File ff:files){
			if(ff.isDirectory()){
				listFile(ff);
			}else{
				if(ff.toString().endsWith(".jar")){
					getJarContent(ff);
				}
			}
		}
	}
	public static void main(String[] args) {
		listFile(new File("/Users/yz/Documents/install/jboss-6.0.0.Final/"));
	}
}

一会儿功夫就完成了,输出结果:

addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/all/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/Context.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/all/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/ApplicationFilterConfig.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/all/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/StandardContext.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/default/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/Context.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/default/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/ApplicationFilterConfig.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/default/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/StandardContext.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/jbossweb-standalone/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/Context.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/jbossweb-standalone/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/ApplicationFilterConfig.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/jbossweb-standalone/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/StandardContext.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/standard/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/Context.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/standard/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/ApplicationFilterConfig.class
addFilterMapBefore:/Users/yz/Documents/install/jboss-6.0.0.Final/server/standard/deploy/jbossweb.sar/jbossweb.jar:org/apache/catalina/core/StandardContext.class

搜索并未发现有ApplicationFilterRegistration这个类,Jboss的哥们又调皮了。虽然搜索结果出现了很多其实也就一个jar,Jboss默认配置有多个实例只看default目录下的就行了。

反编译jbossweb.jar,找到对应的:

Context.class、ApplicationFilterConfig.class、StandardContext.class这三个类

问题已经一目了然了,明显是采用了Tomcat7.0.29以上版本的Filter写法。Tomcat7.0.30开始if和else被调换了个顺序,导致加载全局Filter的时候会有一个BUG。只有在应用层404的情况下Filter才会走到全局拦截的Filter类里面去。解决办法当然是把if和else的内容换回来咯。

Tomcat7.0.29和7.0.30变更内容:

无奈,╮(╯_╰)╭。

发表回复