修改UrlRewriter使其由单配置文件到支持多配置文件By forandever @ 09-08-07 PM.

 

 

Url Rewrite Filter是一个BSD协议的开源的JAVA语言下的URL伪静态化框架,类似Apachemod_rewrite功能,支持常用的WEB容器。其官方网站是http://tuckey.org/urlrewrite/ 。本文通过修改Url Rewrite Filter的源代码,增加了Url Rewrite Filter多配置文件的功能。

 

这里讨论的是它的3.2版本,其配置方式是采用在web.xml中书写filter进行,如下:

 

    <filter>

        <filter-name>UrlRewriteFilter</filter-name>

        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>

        <init-param>

            <param-name>confReloadCheckInterval</param-name>

            <param-value>60</param-value>

        </init-param>

 

        <!-- if you need to the conf file path can be changed

        it is specified as a path relative to the root of your context

        (default /WEB-INF/urlrewrite.xml) -->

        <init-param>

            <param-name>confPath</param-name>

            <param-value>/WEB-INF/urlrewrite.xml</param-value>

        </init-param>

       

</filter>

 

这里,confPath默认是不支持多个配置文件的方式进行配置的,但是对于一个大型的应用,如果系统中的URL多种多样,并且多个模块之间关联不大的情况,我们希望能够针对每一个模块有一个不同的配置文件,也就是各个模块之间是互相分离解耦,然后,在配置文件加载的位置统一加载,也就是类似如下红色部分的方式:

<filter>

        <filter-name>UrlRewriteFilter</filter-name>

        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>

        <init-param>

            <param-name>confReloadCheckInterval</param-name>

            <param-value>60</param-value>

        </init-param>

 

        <!-- if you need to the conf file path can be changed

        it is specified as a path relative to the root of your context

        (default /WEB-INF/urlrewrite.xml) -->

        <init-param>

            <param-name>confPath</param-name>

            <param-value>/WEB-INF/urlrewrite1.xml /WEB-INF/urlrewrite2.xml /WEB-INF/urlrewrite3.xml</param-value>

        </init-param>

       

</filter>

 

很可惜,查了Url Rewrite Filte的文档,它不支持这种方式,于是,末办法,只好修改它的源码。还好,它是BSD协议。下面简单描述一下修改方法。

步骤如下:

1、 修改UrlRewriteFilter.java文件:

1> 增加方法 loadUrlRewriterLocalMutil,如下:

    private void loadUrlRewriterLocalMutil(String confPath) {       

    List<InputStream> listInputStream = new ArrayList<InputStream>();

    List<String> listConfPath = new ArrayList<String>();

    List<String> listConfUrlStr = new ArrayList<String>();

   

    String [] confPathArray = confPath.split(" ");

    for(String conf : confPathArray){

        listConfPath.add(conf);

       

            InputStream inputStream = context.getResourceAsStream(conf);

            listInputStream.add(inputStream);

            URL confUrl = null;

            try {

                confUrl = context.getResource(conf);

            } catch (MalformedURLException e) {

                log.debug(e);

            }

            String confUrlStr = null;

            if (confUrl != null) {

                confUrlStr = confUrl.toString();

                listConfUrlStr.add(confUrlStr);

            }

    }

   

    Conf conf = new Conf(context, listInputStream, listConfPath, listConfUrlStr, modRewriteStyleConf);

        checkConf(conf);

    }

 

2>修改loadUrlRewriter方法,如下:

 

    protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {

    if(confPath.indexOf(" ") == -1) {

        loadUrlRewriterLocal();

    }else{

        loadUrlRewriterLocalMutil(confPath);

    }

}

 

这里,我们的web.xml 中,各个配置文件之间是通过空格来分隔的。

 

2、 修改Conf.java文件,如下:

1>     添加方法


    public Conf(ServletContext context, List<InputStream> inputStreamList, List<String> fileNameList, List<String> systemIdList, boolean modRewriteStyleConf) {

       // make sure context is setup before calling initialise()

       this.context = context;

       for (int i = 0; i < inputStreamList.size(); i++) {

           if (modRewriteStyleConf) {

              loadModRewriteStyle(inputStreamList.get(i));

           } else {

              loadDom(inputStreamList.get(i));

           }

           if (docProcessed)

              initialise();

       }

 

       loadedDate = new Date();

}

经过上面的修改之后,UrlRewriteFilter就具有了我们需要的功能。

另外,UrlRewriteFilter支持在修改了配置文件的内容之后,能够动态的load修改的文件。仅仅使用上面的修改,尽管实现了我们需要的功能,但是这个自动load 的功能就不灵了。

要同时实现这个功能,也很简单,记录一下每个配置文件的最后修改时间,然后在confReloadCheckInterval的时间到了之后,它会检查修改时间并进行比对。

修改文件UrlRewriteFilter.javagetConfFileLastModified方法和reloadConf即可:

    private long getConfFileLastModified() {

    long lastModified = 0L;

    String [] confPathArray = confPath.split(" ");

    for(String conf : confPathArray){

        File confFile = new File(context.getRealPath(conf.trim()));

            if(confFile.lastModified() > lastModified){

                  lastModified = confFile.lastModified();

            }

    }

       

        return lastModified;

    }


    public void reloadConf() {

        long now = System.currentTimeMillis();

        confReloadInProgress = true;

        confReloadLastCheck = now;

 

        log.debug("starting conf reload check");

        long confFileCurrentTime = getConfFileLastModified();

        if (confLastLoad < confFileCurrentTime) {

            // reload conf

            confLastLoad = System.currentTimeMillis();

            log.info("conf file modified since last load, reloading");

//            loadUrlRewriterLocal(); 

           

            loadUrlRewriterLocalMutil(confPath);

        } else {

            log.debug("conf is not modified");

        }

        confReloadInProgress = false;

    }

经过这样的修改之后,Url Rewrite Filter就支持了多文件的配置和多文件的自动Reload的功能。

By forandever @ 09-08-07 PM.

 

 

                                                       

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐