Struts 2 丢弃缓存头

发布于 2024-09-02 04:27:25 字数 2011 浏览 5 评论 0原文

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

我正在尝试将数据库中的图像缓存在客户端 要渲染图像,我使用( http://struts.apache.org/2.x/docs/how-can-we-display-dynamic-or-static- images-that-c​​an-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 ),并且 header 中没有出现 Expires 和 max-age

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 

我不知道为什么它消失了,可能是 url 中的问题?它是带参数的形式:

 http://localhost:9090/web/_srv/teamcolor?loginId=3

I have strange discarding behavior of struts2 while setting cache option for my image.

I'm trying to put image from db to be cached on client side
To render image I use ( 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 ) where special result type render as follow:

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();
}

But when image is embedded to page it is always reloaded (Firebug shows code 200), and neither Expires, nor max-age are presented in header

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 

I have no idea why it is dissapered, may be problem in url? It is forms with parameter:

 http://localhost:9090/web/_srv/teamcolor?loginId=3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮云落日 2024-09-09 04:27:26

不确定这是否会更好,但你可以尝试一下。创建一个修改响应标头的自定义拦截器。像这样的东西(注意,我还没有测试过这个):

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

Not sure if this would work any better, but you could try. Create a custom interceptor that modifies the response headers. Something like this (note, I haven't tested this):

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();
    }

}

Then in your struts.xml, define the interceptor and a new interceptor stack:

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

Then modify your action definition to use the extendedStack.

很快妥协 2024-09-09 04:27:25

最后我发现我的代码有什么问题,这很奇怪,因为它部分有效(显示图像)。

罪魁祸首是以下行:

HttpServletResponse response = ServletActionContext.getResponse();

它必须替换为以下内容:

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

它看起来像是一种魔法,但显然两个响应共享相同的输出流,但不共享标头声明的容器。

At last I've discovered what wrong with my code, it is rather strange because it is partially works (image is displayed).

The culprit is following line:

HttpServletResponse response = ServletActionContext.getResponse();

It must be replaced with following:

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

It is looks like kind of magic, but obviously both response shares the same output stream but not the container of header declarations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文