在Java web开发中,通常会在web.xml中配置过滤器Filter,jFinal框架也是这样。
在web.xml中配置filter:
<filter>
<filter-name>jfinal</filter-name>
<filter-class>com.jfinal.core.JFinalFilter</filter-class>
<init-param>
<param-name>configClass</param-name>
<param-value>com.xh.common.util.DemoConfigPrintSql</param-value>
</init-param>
</filter>
同样,在容器初始化时候,这个Filter就会被加载,在jFinal源码中的JFinalFilter这个类,实现了Servlet的Filter接口,这就意味着需要实现其三个固定的方法:init()初始化,doFilter()以及destroy()方法
jfinal源码:
public final class JFinalFilter implements Filter {
private Handler handler;
private String encoding;
private JFinalConfig jfinalConfig;
private Constants constants;//常量配置
private static final JFinal jfinal = JFinal.me();//获取JFinal实例
private static Logger log;
private int contextPathLength;
public void init(FilterConfig filterConfig) throws ServletException {
//从web.xml的参数中configClass获取对应的值,根据对应的类初始化相关配置,
createJFinalConfig(filterConfig.getInitParameter("configClass"));
//JFinal中的各种信息的初始化(加载拦截器,插件,ActionMapping等)
if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false)
throw new RuntimeException("JFinal init error!");
handler = jfinal.getHandler();
constants = Config.getConstants();
encoding = constants.getEncoding();
jfinalConfig.afterJFinalStart();
String contextPath = filterConfig.getServletContext().getContextPath();
contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length());
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
request.setCharacterEncoding(encoding);//设置编码,默认为UTF-8
String target = request.getRequestURI();
if (contextPathLength != 0)
target = target.substring(contextPathLength);//处理访问的URL
boolean[] isHandled = {false};
try {
handler.handle(target, request, response, isHandled);
}
catch (Exception e) {
if (log.isErrorEnabled()) {
String qs = request.getQueryString();
log.error(qs == null ? target : target + "?" + qs, e);
}
}
当Filter被加载时,首先会进入init()方法进行初始化:
createJFinalConfig(filterConfig.getInitParameter("configClass"));
这一段代码是获取web.xml配置中的configClass的参数值,然后根据参数值(com.xh.common.util.DemoConfigPrintSql)进入对应的类,执行相应的处理方法。
另外,createJFinalConfig这个私有方法干了哪些事儿呢?
首先,判断这个参数在web.xml中到底配置了没有,如果没有就抛出异常信息告诉开发者需要在web.xml中配置这个参数;其次,利用反射动态获取configClass这个对应类的实例,判断这个实例是否实现了jFinalConfig这个抽象类(也可以理解为是否是jFinalConfig这个对象的一个实例),当继承了jFinalConfig这个抽象类,就需要继承重写一些方法(configConstant(),configHandler(),configInterceptor(),configPlugin(),configRoute());然后就是初始化jFinal对象之类的,具体的请参考jFinal这个类的源码。