Java过滤器无法设置响应标头

Sol*_*lay 11 java servlets request http-headers servlet-filters

我正在尝试创建一个Java"过滤器"来检测自定义HTTP请求标头,并插入响应标头,以便文件自动下载.对此最重要的响应标头是"Content-Type = Attachment"响应标头.我创建了一个插入自定义标头的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());
}
Run Code Online (Sandbox Code Playgroud)

这会将X-Wria-Download标头插入请求中.然后我有一个Java过滤器,它查找该请求标头,并应将响应标头设置为"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);
}


}
Run Code Online (Sandbox Code Playgroud)

然后当然web.xml有代码在所有jsp文件中包含Filter.

令我感到困惑的是,标题是在响应文件上设置的,但它不是应该下载的.如果我把res.setHeader("Content-Disposition","attachment; filename = success.pdf"); 在"if"语句之外的行,然后它将工作,但它将下载行为应用于我不想要的所有JSP.

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

Ton*_*Rad 12

我认为您的问题与您Web Context在Web上下文中执行的过滤器顺序(即某些过滤器)有关,在过滤器后执行并覆盖标头.

Servlet 过滤器责任链模式的实现

所以你可以尝试:

  • 调用chain.doFilter后设置标题:

.

...

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");
}
Run Code Online (Sandbox Code Playgroud)

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

  • 确保你的过滤器是指在执行的Servlet后要执行的最后,也就是说,它应该是第一个Servlet过滤器声明解释在这里:

在此输入图像描述

正如您所看到的,Filter1(在web.xml中声明的第一个)是在执行servlet之前执行的第一个,以及在执行servlet之后执行的最后一个.因此,如果您想确保最后一个Filter设置标题,则将其声明为Filter1.

执行顺序由Deployment Descriptor(web.xml)中的声明顺序决定:

Servlet规范(第6.2.4节):

"容器用于构建要应用于特定请求URI的过滤器链的顺序如下:

"1.首先,匹配过滤器的映射顺序与这些元素在部署描述符中出现的顺序相同.

"2.接下来,匹配过滤器的映射顺序与这些元素在部署描述符中出现的顺序相同."

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


小智 5

假设您使用其他人在此处描述的响应包装器,那么秘密就在于何时在原始响应上调用getWriter()!这是因为响应对象会忽略您要求作家之后添加的所有标头!

因此,请确保在调用getWriter()之前添加所有标头。这是我推荐的doFilter()序列:

  1. 创建响应包装

  2. chain.doFilter(origRequest,包装器);

  3. 将所有必需的标题分配给原始(!)响应

  4. 从原始回复中获取作家

  5. 将包装器的内容复制到该作者


Akb*_*hry 0

试试这个:如果请求标头存在,则在请求上设置一个属性。然后,检查 后面的属性chain.doFilter(...)并设置响应标头。