在为我的图片设置缓存选项时,我有struts2的奇怪丢弃行为。
我正在尝试将来自db的图像放在客户端缓存 要渲染图像,我使用(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),并且标题中不显示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
我不知道为什么它会被删除,可能是网址问题?它是带参数的表格:
http://localhost:9090/web/_srv/teamcolor?loginId=3
答案 0 :(得分:2)
最后我发现我的代码有什么问题,这很奇怪,因为它部分有用(图像显示)。
罪魁祸首是:
HttpServletResponse response = ServletActionContext.getResponse();
必须替换为以下内容:
HttpServletResponse response = (HttpServletResponse)
invocation.getInvocationContext().get(StrutsStatics.HTTP_RESPONSE);
它看起来很神奇,但显然两个响应共享相同的输出流,但不是标头声明的容器。
答案 1 :(得分:0)
不确定这是否会更好,但你可以试试。创建一个修改响应头的自定义拦截器。像这样的东西(注意,我没有测试过这个):
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
。