如何在Struts1应用程序中使用过滤器?

时间:2016-08-24 21:26:32

标签: servlet-filters struts-1

我有一个Struts1应用程序,并且尝试让过滤器工作以便在操作完成后向响应中添加标头/等,但是无法使其工作。

当struts操作完成并且控制权返回到我的过滤器时,响应已经提交。

的web.xml:

   <filter>
      <filter-name>workflow</filter-name>
      <filter-class>webapp.session.WorkflowModifierFilter</filter-class>
   </filter>
   <filter-mapping>
      <filter-name>workflow</filter-name>
      <servlet-name>action</servlet-name>
   </filter-mapping>


   <servlet>
      <servlet-name>action</servlet-name>
      <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
      <init-param>
         <param-name>config</param-name>
         <param-value>/WEB-INF/struts-config.xml</param-value>
      </init-param>
      <init-param>
         <param-name>debug</param-name>
         <param-value>0</param-value>
      </init-param>
      <init-param>
         <param-name>detail</param-name>
         <param-value>2</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
   </servlet>

我的过滤器如下:

   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

      if( !servletResponse.isCommitted() )
          log.debug("Not Committed!  Can modify it!");

      filterChain.doFilter(servletRequest, servletResponse);

      // depending on the response, I'd like to add headers here
      if( servletResponse.getStatus() == 200 )
          servletResponse.addIntHeader( "x-success", 1 );

      if( servletResponse.isCommitted() )
          log.debug("ACCCK!  Response Already Committed");
   }

但是,我注意到我的x-success标题从未添加过。一点点挖掘,我注意到我的响应已经在控件返回到我的过滤器链时返回/提交。

Struts1中执行此操作的正确方法是什么?过滤器执行不应该包装整个servlet吗?为什么我的回复在我的过滤器完成之前被提交了?我还可以根据Struts1中的响应(后期处理处理)添加标题吗?

1 个答案:

答案 0 :(得分:1)

当您调用filterChain.doFilter时,您将控制权从过滤器传递到请求的页面(即Struts),然后可以自由提交响应(如果它选择)。由于您要检查Struts servlet的结果,您应该创建一个响应包装类(extends HttpServletRequestWrapper)并将其传递给filterChain.doFilter,而不是传递过滤器的响应参数。

HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
ServletResponse wrapper = new MyHttpServletRequestWrapper(httpResponse);
filter.doChain(servletRequest, wrapper);

HttpServletRequestWrapper构造函数接受HttpServletResponse作为输入,并将所有方法委托给包装响应,但您可以根据需要在类中覆盖它们。如果要阻止提交响应,则需要覆盖flushBuffergetOutputSteam等方法(可以刷新返回的输出流,提交响应)和getWriter

但您可能不需要这样做 - 尝试覆盖包装器类中的setStatus方法以检查状态代码并在调用时添加标头:

public class MyHttpServletResponseWrapper extends HttpServletResponseWrapper {
    public MyHttpServletResponseWrapper(HttpServletResponse response) {
        super(response);
    }
    @Override
    public void setStatus(int sc) {
        if(sc == 200) {
            addIntHeader("x-success", 1);
        }
        super.setStatus(sc);
    }
}

虽然这个问题与Struts 1有关,但它适用于任何Web框架;我的回答是基于我为JSF过滤器所做的工作。