Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在tomcat中通过Filter类方法响应servlet客户端时设置http状态代码_Java_Tomcat_Servlets_Filter - Fatal编程技术网

Java 如何在tomcat中通过Filter类方法响应servlet客户端时设置http状态代码

Java 如何在tomcat中通过Filter类方法响应servlet客户端时设置http状态代码,java,tomcat,servlets,filter,Java,Tomcat,Servlets,Filter,我正在用spring编写一个Web服务(这个问题不是关于spring…),它实现了(希望如此)restful api。据我所知,所有响应都应该是xml或json格式。在大多数情况下,这并不是什么大问题。但在一种情况下,这似乎是不可能的。我使用的是tomcat的一个工具,其中涉及servlet。出于某种原因,我不得不使用过滤器(这就是身份验证)。由于我对servlets还不熟悉,我的理解最终不是很好,但对我来说,它看起来是这样的 我的filter类派生自javax.servlet.filter,我

我正在用spring编写一个Web服务(这个问题不是关于spring…),它实现了(希望如此)restful api。据我所知,所有响应都应该是xml或json格式。在大多数情况下,这并不是什么大问题。但在一种情况下,这似乎是不可能的。我使用的是tomcat的一个工具,其中涉及servlet。出于某种原因,我不得不使用过滤器(这就是身份验证)。由于我对servlets还不熟悉,我的理解最终不是很好,但对我来说,它看起来是这样的

我的filter类派生自javax.servlet.filter,我正在doFilter方法中编写代码:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
                          FilterChain chain) throws IOException, ServletException { // ... }
在某个时刻,我意识到我必须用http状态码401响应客户机,并且还想给他一个关于发生了什么的xml或json信息。现在对我来说,似乎我也可以

1) 使用ServletResponse:这允许我获取OutputStream并写出xml/json。但是,我根本无法设置http状态代码。到达客户端的最终响应确实包含一些http头


2) 将ServletResponse强制转换为HttpServletResponse:这允许我设置状态代码,但我似乎无法设置响应主体,而是让响应主体从tomcat处理

这两种方式似乎都不完整。如果我使用ServletResponse写入OutputStream,然后强制转换为HttpServletResponse,然后调用sendError(401)——希望写入OutputStream的内容到达客户端——我的响应不包含http“状态行”。但是,http头是像“Server:apachecoyote/1.1”这样出现的

欢迎任何帮助…

这对我很有用:

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

    response.resetBuffer();
    response.getOutputStream().write("Your content".getBytes());
    HttpServletResponse hsr = (HttpServletResponse) response;
    hsr.setStatus(401);
    chain.doFilter(request, response);
}

我很快就实现了一个用于身份验证的过滤器。我编写了类似的代码:

public void doFilter(ServletRequest req, ServletResponse resp,
                         FilterChain chain)
{
    HttpServletResponse response=(HttpServletResponse) resp;

    boolean authenticated=false;
    // perform authentication

    if (authenticated)
    {
         chain.doFilter(req, response);
    }
    else
    {
         // don't continue the chain
         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
         response.setHeader("WWW-Authenticate", "BASIC realm=\"Your realm\"");

         response.setContentType("what you need");
         PrintWriter writer=response.getWriter();

         // don't set content length , don't close
    }
}

方法HttpServletResponse::sendError正在为我工作,以便从SpringBoot 2.0应用程序中的筛选器返回:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (authenticated)
    {
         chain.doFilter(req, response);
    }
    else
    {
    ((HttpServletResponse) response).sendError(HttpStatus.FORBIDDEN.value(), "Authorization shall be provided");
    }
    chain.doFilter(request, response);
}

在我看来,在servlet中实现REST的水平相当低。如果可能的话,我会尝试将JAX-RS与Jersey一起使用,这样更方便。我没有很好地描述我的情况。。。请看更新的问题。rest api是用spring完成的。为什么在设置状态401后继续使用过滤器链?执行身份验证之前的筛选器anyway@Ulrich可能不需要继续使用过滤器链,但这取决于web.xml中过滤器的具体设置。您是对的,当然
web.xml
会影响过滤器的执行顺序。但一般来说,继续处理未经身份验证的请求是没有意义的。如果有要执行的任务(如日志记录),它们应该在身份验证之前链接的筛选器中执行。如果后续筛选器要设置头怎么办?我来这里是为了搜索为什么我设置CORS头的过滤器没有启动。是否可以发送自定义消息的用户定义状态代码,例如498?@Sanjeev-我没有尝试过,但我想这是可能的,因为代码只是一个整数。也许,您的基础结构中的其他组件只接受标准覆盖的状态。如果我正在使用PrintWriter,则日志中会出现以下异常:java.lang.IllegalStateException:getWriter()已为此响应调用。当我切换到outputStream()时,我无法在响应中设置http状态代码。这允许我设置状态代码,但我似乎无法使用getOutputStream()设置自定义响应正文。无法在此处添加代码段,因为它会导致未格式化的代码。@PiyushUpadhyay-发布新问题。在那里你可以添加一个MCVE或类似的东西。可以在响应中放置自定义主体,但不能在关闭OutputStream之后