Java 过滤器无法设置响应 header

标签 java servlets http-headers request servlet-filters

我正在尝试创建一个 Java“过滤器”,它检测自定义 HTTP 请求 header ,并插入响应 header ,以便文件自动下载。对此最重要的响应 header 是“Content-Type = Attachment”响应 header 。我创建了一个插入自定义 header 的 HTTP 请求对象:

function myHttpObject(filePath){
function makeHttpObject() {
    return new XMLHttpRequest();
}

var request = makeHttpObject();

request.open("GET", filePath, false);
request.setRequestHeader("X-Wria-Download", "PDFdownload");
request.send(null);
window.open(filePath);
console.log(request.getAllResponseHeaders());
}

这会将 X-Wria-Download header 插入到请求中。 然后我有一个 Java 过滤器,它查找该请求 header 并应将响应 header 设置为“Content-Type=attachment”

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Contenttypefilter implements Filter  {

protected FilterConfig filterConfig;

public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
}

public void destroy() {
    //noop
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    //get the headers we placed in the request
    //based on those request headers, set some response headers

    if(req.getHeader("X-Wria-Download") != null){
        res.setHeader("Content-Type", "application/pdf");
        res.setHeader("Content-Disposition", "attachment; filename=success.pdf");
    }

    chain.doFilter(req,res);
}


}

当然,web.xml 包含在所有 jsp 文件中包含过滤器的代码。

让我感到困惑的是,响应文件中设置了 header ,但它没有按预期下载。如果我把 res.setHeader("Content-Disposition", "attachment; filename=success.pdf");在“if”语句之外的行,那么它将起作用,但它将下载行为应用于我不想要的所有 JSP。

当我在 if 语句中有 res.setHeader 时,为什么它应用了内容处置但不起作用;然后在 if 语句之外工作?关于如何获得所需行为的任​​何想法(仅将内容处置应用于我已应用自定义请求 header 的 jsp)?

最佳答案

我认为您的问题与您的 Web 上下文 的过滤器执行顺序有关,即您的 web 上下文中的某些过滤器在您的过滤器之后执行并覆盖 header 。

Servlet FilterChain of Responsibility 的一个实现图案

所以你可以尝试:

  • 在调用 chain.doFilter 后设置 header :

.

...

chain.doFilter(req,res);

HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;

//get the headers we placed in the request
//based on those request headers, set some response headers

if(req.getHeader("X-Wria-Download") != null){
    res.setHeader("Content-Type", "application/pdf");
    res.setHeader("Content-Disposition", "attachment; filename=success.pdf");
}

通过这种方式,您的代码将在 Servlet 被调用后执行,如下所述,如果您的过滤器是在 web.xml 中第一个声明的,那么 setHeader 代码将是最后一个已执行(见下图)。

  • 确保您的过滤器是在 Servlet 执行后最后执行的过滤器,即它应该是第一个声明的 servlet 过滤器,如说明 here :

enter image description here

可以看到Filter1(web.xml中声明的第一个)是servlet执行前第一个执行,servlet执行后最后一个执行。所以如果你想确定是最后一个设置header的Filter那么声明它为Filter1。

执行顺序由部署描述符 (web.xml) 中的声明顺序决定:

Servlet spec (section 6.2.4):

"The order the container uses in building the chain of filters to be applied for a particular request URI is as follows:

"1. First, the matching filter mappings in the same order that these elements appear in the deployment descriptor.

"2. Next, the matching filter mappings in the same order that these elements appear in the deployment descriptor."

所以为了确保简单地将它声明为 web.xml 中的第一个过滤器。这样,它将成为设置标题的最后一个过滤器。当然,如前所述,在调用 chain.doFilter 后在代码中设置 header 。

关于Java 过滤器无法设置响应 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13461500/

相关文章:

java - JAXB 将引用列表绑定(bind)到另一个元素

java - 如何读取Web项目中的内部文件

java - 如何使用计算机名而不是 IP 地址从另一台设备访问 Tomcat 服务器?

c++ - 读取 http 请求 header (Qt/c++)

java - 如何使用 J2EE 容器全局设置 RESPONSE Headers (Websphere)

asp-classic - 如何访问Http请求中的响应头

java - 如何获取Date数据类型中不带时间戳的系统日期?

java - 将输出保存到文件

java - Google App Engine 端点中的自定义 JSON 实体解析

java - 将多个图像写入 servlet 中的 outputStream