Java 过滤器无法设置响应标头 [英] Java filter failing to set response headers

查看:47
本文介绍了Java 过滤器无法设置响应标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create a Java "Filter" which detects a custom HTTP Request Header, and inserts response headers so that the file will download automatically. The response header that is most important for this is the "Content-Type = Attachment" response header. I have created an HTTP request object that inserts the custom Header:

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 标头插入到请求中.然后我有一个 Java 过滤器,它查找该请求标头,并将响应标头设置为Content-Type=attachment"

This will insert the X-Wria-Download header into the request. Then I have a Java Filter which looks for that request header and should set the response header to "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 文件中包含过滤器的代码.

And then of course the web.xml has the code to include the Filter on all jsp files.

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

The thing that is baffling me, is that the header is being set on the response file, but it is not downloading as it should. If I put the res.setHeader("Content-Disposition", "attachment; filename=success.pdf"); line outside the "if" statement, then it will work, but it will apply the download behavior to all JSP's which I don't want.

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

Why is it applying the content-disposition but not working when I have the res.setHeader in the if statement; and then working when it is outside the if statement? Any ideas for how I can get the desired behavior (only applying content disposition to jsp's that I have applied a custom request header to)?

推荐答案

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

I think your issue is related to the Filter order of execution of your Web Context, i.e. some filters, in you web context, executes after your filter and override the header.

Servlet Filter责任链模式

The Servlet Filter is an implementation of the Chain of Responsibility pattern

所以你可以尝试:

  • 在调用 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");
}

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

In this way your code will be executed after that the Servlet is called and, as explained below, if your filter is the first declared in web.xml, then the setHeader code will be the last executed (see image below).

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

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

As you can see Filter1 (the first declared in web.xml) is the first one executed before the servlet is executed and the last one executed after the servlet is executed. So if you want to be sure to be the last Filter setting the header then declare it as Filter1.

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

The order of execution is determined by the order of declaration in your Deployment Descriptor (web.xml):

Servlet 规范(第 6.2.4 节):

Servlet spec (section 6.2.4):

"容器在构建过滤器链时使用的顺序申请特定的请求URI如下:

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

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

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

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

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

因此,请务必将其声明为 web.xml 中的第一个过滤器.这样,它将是最后一个设置标题的过滤器.而且,当然,在调用 chain.doFilter 之后,在你的代码中设置标题,正如已经说过的.

So to be sure simply declare it as the first filter in your web.xml. In this way it will be the very last filter setting the header. And, of course, set the header in your code after calling chain.doFilter, as already said.

这篇关于Java 过滤器无法设置响应标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆