我有一个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中的响应(后期处理处理)添加标题吗?
答案 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
作为输入,并将所有方法委托给包装响应,但您可以根据需要在类中覆盖它们。如果要阻止提交响应,则需要覆盖flushBuffer
,getOutputSteam
等方法(可以刷新返回的输出流,提交响应)和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过滤器所做的工作。