自己写的J2EE通用URL重定向工具

3 篇文章 1 订阅

[2011-5-8]

这次项目需要对一个URL进行重写,一个简单的方法就是针对本次的应用对请求的URL做一个特殊的处理。但是为了以后扩展方便,我把他写成了一个通用的URLRewrite工具类,理论上是支持各种框架的。项目的地址是:http://code.google.com/p/eagle-beak/, GPLv2协议,有兴趣的可以研究一下。

这里我给大家举个例子如何使用我的URLRewrite工具,以最基础的JavaEE做为例子。大家都知道,在JavaEE中要对请求进行处理自然要选择Filter,所以我们就把URLRewrite的工作放在Fitler 之中,如本实例的URLRewriteFilter,当然这里我们需要用“/*”来拦截所有的请求,以进行URL分析。URLRewriteFilter的代码如下:

package org.sefler.test;
import java.io.IOException;
/**
 * Servlet Filter implementation class URLRewriteFilter
 */
public class URLRewriteFilter implements Filter {
    private static final Logger LOG = Logger.getRootLogger();
    
    private static URLRewriteConfiger CONFIG;
    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        LOG.debug("Requesting: " + httpServletRequest.getServletPath());
        
        URLRewriter rewriter = CONFIG.getURLRewriter("test");
        try {
            URLRequest urlRequest = rewriter.rewrite(httpServletRequest.getServletPath());
            
            RequestDispatcher dispatcher = request.getRequestDispatcher(urlRequest.getTarget()); 
            dispatcher .forward(new ModifiableHttpServletRequest(httpServletRequest, urlRequest.getQueries()), response);
            
            LOG.debug("Redirecting to " + urlRequest.getTarget());
        } catch (NoURLMappingFoundException e) {
            // do not rewrite
            LOG.debug("No matching patterns were found, will do nothing");
            chain.doFilter(request, response);
        } catch (URLRewriteException e) {
            LOG.error("Error when rewriting URL in URLRewriteFilter, Reuqest URL: "
                    + httpServletRequest.getServletPath(), e);
        }
    }
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        try {
            String configPath = fConfig.getInitParameter("configFile");
            
            URLXMLConfiger.getInstance().init(fConfig.getServletContext().getResourceAsStream(configPath));
            CONFIG = URLXMLConfiger.getInstance();
        } catch (MalformedConfigException e) {
            LOG.error("Error when initializing filter: " + getClass().toString(), e);
        }
        
        CONFIG = URLXMLConfiger.getInstance();
    }
    @Override
    public void destroy() {}
}
请注意里面的init方法,在这个方法中我们发现以下两行,这里需要初始化URLRewrite的配置,我们的URLRewrite支持各种各样的配置,这里我们使用的是XML的方式进行配置的。

String configPath = fConfig.getInitParameter("configFile");
URLXMLConfiger.getInstance().init(fConfig.getServletContext().getResourceAsStream(configPath));

XML文件的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<config xmlns="http://www.taobao.com/wing/urlrewrite" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.taobao.com/wing/urlrewrite urlrewrite.xsd ">
 <rewriter name="test" type="regex" >
  <mapping>
   <target>/index.jsp</target>
   <pattern>/123.htm</pattern>
   <handler>org.sefler.test.SimpleTestHandler</handler>
  </mapping>
  <mapping>
   <target>/WEB-INF/viewArticle.jsp</target>
   <pattern>/a[0-9]+.htm</pattern>
   <handler>org.sefler.test.ArticleHandler</handler>
  </mapping>
 </rewriter>
</config>
好了,配置好了以后,我们就可以在Filter里面实现我们的大计了。从刚才的XML配置文件我们也看到了,对个mapping对应一个pattern(即客户端请求的URL模式)、target(即最终需映射到的服务器的页面)与一个handler,handler是需要用户自己来实现的。我们现在先来一个简单的,它要做的只是把index.jsp重写成123.htm,那么配置就是我们的第一个Mapping写的那样了,我们使用一个名为SimpleTestHandler的Handler来处理这个重写,它的代码如下:

package org.sefler.test;
import java.util.Collections;
import java.util.Map;
import com.taobao.matrix.eagle.beak.URLMapping;
import com.taobao.matrix.eagle.beak.URLRequest;
import com.taobao.matrix.eagle.beak.URLRewriteHandler;
public class SimpleTestHandler implements URLRewriteHandler {
    @SuppressWarnings("unchecked")
    @Override
    public URLRequest parse(String requestPath, URLMapping mapping) {
        URLRequest urlRequest = new URLRequest(mapping.getTarget(), Collections.EMPTY_MAP);
        return urlRequest;
    }
    @Override
    public String render(Map<String, Object> queries, URLMapping mapping) {
        return "No render rule defined! Will do nothing!";
    }
}
可以看出这个Handler什么都没有做,只是把pattern映射成了target。那么最终的结果就如下:



OK, 现在我们来弄个更复杂的,现在我们的URL Patter的为a1234.htm,后面的数字是隐藏的参数,取名arNo。我们使用ArticleHandler来处理这个请求

package org.sefler.test;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
import com.taobao.matrix.eagle.beak.URLMapping;
import com.taobao.matrix.eagle.beak.URLRequest;
import com.taobao.matrix.eagle.beak.URLRewriteHandler;
import com.taobao.matrix.eagle.beak.URLUtil;
public class ArticleHandler implements URLRewriteHandler {
    public static final Logger LOG = Logger.getLogger("test"); 
    
    @Override
    public URLRequest parse(String requestPath, URLMapping mapping) {
        int arNo =  NumberUtils.toInt(URLUtil.getFileName(requestPath).substring(1), 0);
        LOG.debug("Parsed arNo parameter: " + arNo);
        
        Map<String, Object> queries = new HashMap<String, Object>();
        queries.put("arNo", arNo);
        
        URLRequest urlRequest = new URLRequest(mapping.getTarget(), queries);
        return urlRequest;
    }
    @Override
    public String render(Map<String, Object> queries, URLMapping mapping) {
        if (queries.size() == 0 || queries.get("arNo") == null) {
            return "index.jsp";
        }
        
       String renderedURL = "a" + queries.get("arNo") + ".htm";
        
        LOG.debug("Rended URL: " + renderedURL);
        return renderedURL;
    }
}

需要注意的是,JavaEE的HttpServletRequst并不充许你更改请求的参数,所以我们需要用HttpServletRequestWrapper进行wrap一下,具体怎么wrap 大家可以看最后附带的源码,这里也不多说了。至于重写URL的生成,比如在JSP里使用“viewArticle.jsp?arNO=123”这类的href自然希望渲染成“a123.htm”。由于JavaEE并没有专门负责URL的模块,这里们可以自己建一个应用级的URLBroker来负责生成想要的URL。例如在viewArticle.jsp下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<jsp:useBean id="urlBroker" class="org.sefler.test.URLBroker" scope="request" />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>View Article</title>
</head>
<body style="font-family: Arial">
 <div>
  You're viewing: <span style="color: green">viewArticle.jsp</span>
 </div>
 <div>
  Requesting article No.: <span style="color: green"><%= request.getParameter("arNo") %></span>
 </div>
 <div style="background-color: lightblue;">
  <% int arNo = org.apache.commons.lang.math.NumberUtils.toInt(request.getParameter("arNo"), 0) + 1; %>
  Click <a href="<%= urlBroker.setTarget("/WEB-INF/viewArticle.jsp").addParameter("arNo", arNo).render() %>"> here</a>
  to view next article
 </div>
</body>
</html>
只要把URLBroker作为JavaBean注入就可以。当然,我这里只是提供一种简单的方法,肯定有更优雅的方法,大家可以照着这种思想去想一想(偶们公司的框架解决这个问题轻而易举,^_^)。话说,某个开源项目与我的思想很像(好吧,我与它的很像吧),不过我想说的是,有些问题由于限制问题,可选用的解决方案也不多,大家的解决方案自然也就很像了~

?

地址:http://code.google.com/p/eagle-beak/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值