BirtViewer和Struts2框架的整合

      最近和同事在做一个birt相关的东西<Birt扫盲>,web这块是用ssh框架,MVC框架用的是struts2。同事负责报表展现这一块,考虑到工期,他选择了使用birt标签来展现birt报表。这一来,问题就出现了。因为web这块是在一个老项目的基础上添加的模块,很多配置都不要再修改,其中就有struts2的核心过滤器,拦截了/*和*.jsp,而如果使用birt标签的话,它自己向birt引擎(配置为servlet)发出的请求通通都被struts2过滤了,结果只要一到含有birt标签的页面,就会报异常:在xx下找不到xxAction。算是个冲突吧。问题的关键点就是:birt标签对于servlet的请求,被struts2的核心过滤器过滤了。如果从零开始做,这或许不是什么难事,但是项目里很多配置都定死了,没办法,只能想其他路子。

方案一:修改birtViewer相关的servlet源码
      将birt的servlet的url-mapping配置为类似于/preview.birt的话,是会被struts2的核心过滤器放过的,于是我反编译了birt的servlet的源码,发现请求路径基本都是硬编码的,不管了,一通乱改,基本都是将xxx改成xxx.birt,然后居然可以预览到报表的轮廓了,不过还是有NullPointer,没办法,这么改源码不是办法。

方案二:写过滤器,使对于servlet的请求跳过struts2的处理
      今天看struts2的核心过滤器的源码,灵感突然来了,我也写个过滤器,先于struts2的过滤器执行,在过滤器里直接将请求转发到对应的servlet。果然奏效!对于类似的需求,也可以采用同样的办法。
      这个url-pattern和代码还没解耦,可以修改web.xml,这样代码就不需要对url判断了,读者自己可以改进。不多说了,上代码。
  1 /**
  2  * BirtFilter.java 2009-8-21
  3  * by shoru
  4  */
  5 package com.shoru.filter;
  6 
  7 import java.io.IOException;
  8 import java.util.HashMap;
  9 import java.util.Map;
 10 import java.util.Set;
 11 
 12 import javax.servlet.Filter;
 13 import javax.servlet.FilterChain;
 14 import javax.servlet.FilterConfig;
 15 import javax.servlet.RequestDispatcher;
 16 import javax.servlet.ServletContext;
 17 import javax.servlet.ServletException;
 18 import javax.servlet.ServletRequest;
 19 import javax.servlet.ServletResponse;
 20 import javax.servlet.http.HttpServletRequest;
 21 
 22 /**
 23  * BirtViewer和Struts2框架整合必须配置此拦截器。 如下配置web.xml,注意struts2的核心过滤器必须配置在BirtFilter之后。
 24  * <filter>
 25  *        <filter-name>BirtFilter</filter-name>
 26  *         <filter-class>com.linkage.system.filter.BirtFilter</filter-class>
 27  * </filter>
 28  * <filter-mapping>
 29  *        <filter-name>BirtFilter</filter-name>
 30  *         <url-pattern>/*</url-pattern>
 31  * </filter-mapping>
 32  * 
 33  * @description
 34  * @author Shoru
 35  * @date 2009-8-21
 36  * @version 1.0.0
 37  * @since 1.0
 38  */
 39 public class BirtFilter implements Filter {
 40     /**
 41      * 容器,封装birt相关功能的uri和所对应Servlet名的键值对
 42      */
 43     Map<String, String> map = new HashMap<String, String>();
 44 
 45     /**
 46      * Context.
 47      */
 48     ServletContext context;
 49 
 50     /**
 51      * debug开关
 52      */
 53     static boolean debug = false;
 54 
 55     /**
 56      * @description
 57      * @author Shoru
 58      * @date 2009-8-21
 59      * @version 1.0.0
 60      */
 61     public void destroy() {
 62         map = null;
 63     }
 64 
 65     /**
 66      * 过滤birt请求,转发到对应的servlet,以绕过其他过滤器,e.g. struts2
 67      * 
 68      * @description
 69      * @author Shoru
 70      * @date 2009-8-21
 71      * @version 1.0.0
 72      * @param request
 73      * @param response
 74      * @param fc
 75      * @throws IOException
 76      * @throws ServletException
 77      */
 78     public void doFilter(ServletRequest request, ServletResponse response,
 79                          FilterChain fc)
 80         throws IOException, ServletException {
 81 
 82         HttpServletRequest req = (HttpServletRequest)request;
 83         String uri = req.getRequestURI();
 84         if (debug) {
 85             System.out.println(">>>Requesting " + uri + "?"
 86                                + req.getQueryString());
 87         }
 88         Set<String> keys = map.keySet();
 89 
 90         for (String key : keys) {
 91             /*
 92              * TODO:这里的判断只是简单地调用contains方法,这样就带来较多限制。
 93              * 比如工程子目录的命名、struts2命名空间等都受到birtViewer的约束。待改进。
 94              */
 95             if (uri.contains(key)) {
 96                 RequestDispatcher rd = this.context.getNamedDispatcher(map.get(key));
 97                 if (rd != null) {
 98                     if (debug) {
 99                         System.out.println(">>>Redirect successfully executed");
100                     }
101                     // 跳过其他过滤器,跳转到对应的servlet
102                     rd.forward(request, response);
103                 } else {
104                     if (debug) {
105                         System.out.println(">>>Redirect unsuccessfully executed");
106                     }
107                 }
108                 return;
109             }
110         }
111 
112         // 将请求交给下一个过滤器
113         fc.doFilter(request, response);
114     }
115 
116     /**
117      * @description
118      * @author Shoru
119      * @date 2009-8-21
120      * @version 1.0.0
121      * @param fc
122      * @throws ServletException
123      */
124     public void init(FilterConfig fc)
125         throws ServletException {
126 
127         this.context = fc.getServletContext();
128         /*
129          * 这里注意,在项目目录的命名时,不要取和birt内置的一些servlet名重复。 请根据项目的web.xml自行配置。
130          * (包括frameset、run、preview、download、parameter、document、output)
131          */
132         map.put("frameset""ViewerServlet");
133         map.put("preview""EngineServlet");
134     }
135 }

posted on 2009-08-21 17:24  晋哥哥  阅读(2920)  评论(0编辑  收藏  举报

导航