首页 > 代码库 > 博客标题

博客标题

不管是Stuct2还是Spring MVC,都是通过在Web.xml里面加入filter,使得Web服务器启动时加载它。Jfinal也是。

filter本身是对Web所有请求的过滤。在 Web服务器启动的时候会加载Filter-class,利用这点Jfinal也就加载起来了。

<filter>
<filter-name>jfinal</filter-name>
<filter-class>com.jfinal.core.JFinalFilter</filter-class>
<init-param>
<param-name>configClass</param-name></init-param>
</filter>
<filter-mapping>
<filter-name>jfinal</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

这里的Filter-class是com.jfinal.core.JFinalFilter,所以我们要从它开始看起。

public final class JFinalFilter implements Filter

从定义中可以看出,JFinal是实现了Filter接口

Filter接口里面有三个主要的方法:

public void init(FilterConfig filterConfig);
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain);
public void destroy();

这是Java本身的东西,Jfinal是对他的实现。

在init方法中Jfinal完成了自身的初始化。

 public void init(FilterConfig filterConfig) throws ServletException {
  //实例化 ConfigClass

  createJFinalConfig(filterConfig.getInitParameter("configClass"));

  
  //进行最主要的Jfinal初始化(疑问:为什么不把ConfigClass也放到Jfinal.init中来,这样代码更容易理解)
  if (jfinal.init(jfinalConfig, filterConfig.getServletContext()) == false)

   throw new RuntimeException("JFinal init error!");
  //获得Jfinal初始化后的对象。
  handler = jfinal.getHandler();
  //获得配置的编码信息,(疑问:应该直接默认UTF-8,此处真是多此一举)
  constants = Config.getConstants();
  encoding = constants.getEncoding();
  jfinalConfig.afterJFinalStart();
  //解析路径的时候需要把前面的主机名,协议名去掉,比如 
  //此处contextPath 是http://127.0.0.1,那么以后得到http://127.0.0.1/helloworld时, 
  //可以根据contextPathLength把http://127.0.0.1截掉,这样得到helloworld,    
  //然后根据helloworld进行映射controller方法
  String contextPath = filterConfig.getServletContext().getContextPath();
  contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length());

 }

在doFilter中Jfinal调用真正的处理。

 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  //传过来的ServletRequest和 ServletResponse 进行类型转换HttpServletRequest,HttpServletResponse 
  //为什么进行类型转换: HttpServletRequest和ServletRequest都是接口 
//HttpServletRequest继承自ServletRequest 
//HttpServletRequest比ServletRequest多了一些针对于Http协议的方法。 
//如getHeader(String name),getMethod(),getSession() 等等。 

  
  HttpServletRequest request = (HttpServletRequest)req;
  HttpServletResponse response = (HttpServletResponse)res;
  request.setCharacterEncoding(encoding);

  String target = request.getRequestURI();
  if (contextPathLength != 0)
   target = target.substring(contextPathLength);
  //为什么要用数组,实在不知道,还要往里面看 
  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);
   }
  }
  if (isHandled[0] == false)
   chain.doFilter(request, response);
 }

在destroy只是留下了扩展接口,没有实际内容。

在整个JFinalFilter类中,还有两个方法

private void createJFinalConfig(String configClass)
static void initLogger()

createJFinalConfig使用了反射,实例化了ConfigClass,

ConfigClass就是在<param-value>com.demo.common.DemoConfig</param-value>配置的类。

createJFinalConfig里面的方法是比较common的方法,为什么没有放在util里面,很奇怪。

总结:

 JFinalFilter是直接和Web server耦合的类,是Jfinal的入口。从代码层面说,还有几点需要改进

  1. 去掉 createJFinalConfig,放入Jfinal主类中感觉比较好,并在init中调用

  2.  initLogger在Config类中被调用,Config被Jfinal调用,而JFinalFilter本身又调用Jfinal中的方法,

    形成的相互依赖,感觉不太好

  3. init方法内容是几个不相关的内容,最好分出来。

  4.  下面的代码段,放在init中没有意义,本身Constants是静态类,而且仅使用一次,在使用的地方直接

     Config.getConstants().getEncoding()即可,或者在使用该变量的方法开始的时候

          encoding=Config.getConstants().getEncoding();

  constants = Config.getConstants();

  encoding = constants.getEncoding();