代码之家  ›  专栏  ›  技术社区  ›  Dewfy

struts 2丢弃缓存头

  •  0
  • Dewfy  · 技术社区  · 15 年前

    我在为我的图像设置缓存选项时有奇怪的struts2丢弃行为。

    我正在尝试将数据库中的图像缓存到客户端 渲染我使用的图像( http://struts.apache.org/2.x/docs/how-can-we-display-dynamic-or-static-images-that-can-be-provided-as-an-array-of-bytes.html )其中特殊结果类型呈现如下:

    public void execute(ActionInvocation invocation) throws Exception {
         ...//some preparation
        HttpServletResponse response = ServletActionContext.getResponse();
        HttpServletRequest request = ServletActionContext.getRequest();
        ServletOutputStream os = response.getOutputStream();
        try
        {
            byte[] imageBytes = action.getImage();
            response.setContentType("image/gif");
            response.setContentLength(imageBytes.length);
            //I want cache up to 10 min
            Date future = new Date(((new Date()).getTime() + 1000 * 10*60l));
            ;
            response.addDateHeader("Expires", future.getTime());
          response.setHeader("Cache-Control", "max-age=" + 10*60 + "");
            response.addHeader("cache-Control", "public"); 
            response.setHeader("ETag", request.getRequestURI());
            os.write(imageBytes);
        }
        catch(Exception e)
        {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    
        os.flush();
        os.close();
    }
    

    但是当图像嵌入到页面中时,它总是被重新加载(firebug显示代码200),并且头中既不显示过期,也不显示最长期限。

    Host    localhost:9090
    Accept  image/png,image/*;q=0.8,*/*;q=0.5
    Accept-Language en-us,en;q=0.5
    Accept-Encoding gzip,deflate
    Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive  300
    Connection  keep-alive
    Referer http://localhost:9090/web/result?matchId=1
    Cookie  JSESSIONID=4156BEED69CAB0B84D950932AB9EA1AC; 
    If-None-Match   /web/_srv/teamcolor
    Cache-Control   max-age=0 
    

    我不知道它为什么会被破坏,可能是在网址的问题?它是带有参数的窗体:

     http://localhost:9090/web/_srv/teamcolor?loginId=3
    
    2 回复  |  直到 15 年前
        1
  •  2
  •   Dewfy    15 年前

    最后,我发现了我的代码有什么问题,这是相当奇怪的,因为它是部分工作(图像显示)。

    罪魁祸首如下:

    HttpServletResponse response = ServletActionContext.getResponse();
    

    必须用以下内容替换:

    HttpServletResponse response = (HttpServletResponse)
        invocation.getInvocationContext().get(StrutsStatics.HTTP_RESPONSE);
    

    这看起来有点神奇,但显然两个响应共享相同的输出流,但不共享头声明的容器。

        2
  •  0
  •   Tommi    15 年前

    不确定这是否会更好,但你可以试试。创建修改响应头的自定义拦截器。类似这样的事情(注意,我没有测试过这个):

    package com.yourpackage.interceptor;
    
    import java.util.Date;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.struts2.StrutsStatics;
    
    import com.opensymphony.xwork2.ActionContext;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    
    public class ResponseHeadersInterceptor extends AbstractInterceptor {
    
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
    
            ActionContext context = invocation.getInvocationContext();
            HttpServletResponse response = (HttpServletResponse)context.get(StrutsStatics.HTTP_RESPONSE);
            HttpServletRequest request = (HttpServletRequest)context.get(StrutsStatics.HTTP_REQUEST);
    
            if (response!=null) {
                Date future = new Date(((new Date()).getTime() + 1000 * 10*60l));
                response.addDateHeader("Expires", future.getTime());
                response.setHeader("Cache-Control", "max-age=" + 10*60 + "");
                response.addHeader("cache-Control", "public");
                if (request!=null)
                    response.setHeader("ETag", request.getRequestURI());
            }
    
            return invocation.invoke();
        }
    
    }
    

    然后在struts.xml中,定义拦截器和一个新的拦截器堆栈:

    <interceptors>
        <interceptor name="responseHeaders" class="com.yourpackage.interceptor.ResponseHeadersInterceptor" />       
        <interceptor-stack name="extendedStack">
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="responseHeaders" />
        </interceptor-stack>        
    </interceptors>
    

    然后修改动作定义以使用 extendedStack .