使用ContainerRequestContext.abortWith()后,Jersey为每个调用抛出NPE

Ale*_*lex 9 java rest grizzly jersey-2.0

我有一个RESTful端点,我通过自定义ContainerRequestFilter进行简单的授权检查.过滤器检查HTTP会话中包含的所有信息是否正确,如果不是,则执行以下操作:

requestContext.abortWith(Response.status(Response.Status.FORBIDDEN)
.entity("Forbidden").build());
Run Code Online (Sandbox Code Playgroud)

这一切都很好,花花公子.奇怪的是,当我再次发出相同的GET请求时,Jersey服务器报告NPE并且不返回任何内容.

NPE堆栈跟踪:

Jul 20, 2016 5:27:53 PM org.glassfish.jersey.server.ServerRuntime$Responder writeResponse
SEVERE: An I/O error has occurred while writing a response message entity to the container output stream.
java.lang.IllegalStateException: The output stream has already been closed.
    at org.glassfish.jersey.message.internal.CommittingOutputStream.setStreamProvider(CommittingOutputStream.java:147)
    at org.glassfish.jersey.message.internal.OutboundMessageContext.setStreamProvider(OutboundMessageContext.java:803)
    at org.glassfish.jersey.server.ContainerResponse.setStreamProvider(ContainerResponse.java:372)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:694)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:444)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:434)
    at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:329)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
    at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:384)
    at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)

怎么了?我不想关闭输出流.我只需要一个方法将http返回代码+消息返回给请求者.

Ale*_*lex 25

万一有人会遇到同样的问题我在这里得到答案:你不能重复使用回应!输出流编写器的实例绑定到Request,只要在abortWith()中使用它,流就会永久提交.因此,它不能再用于发送响应.

您需要在filter()方法中初始化一个新的Request .

简单来说,不要使用这样的结构:

 private static final Response ACCESS_FORBIDDEN = Response.status(Response.Status.FORBIDDEN)
            .entity("Access blocked for all users !!").build();
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我在这里找到了这段破碎的代码:http://howtodoinjava.com/jersey/jersey-rest-security/ 所以在实现这个RequestFilter时要小心.

  • 您可以重复使用ResponseBuilder并为其上的每个请求调用build()方法. (2认同)
  • 大声笑,一段时间做了同样的精确教程,最终到了这里 (2认同)

Ric*_*man 8

如上所述,问题出在已经设置的静态ACCESS_DENIED响应上.

private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("Accesso não Autorizado").build();
Run Code Online (Sandbox Code Playgroud)

所以替换:

requestContext.abortWith(ACCESS_DENIED)

通过

requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Accesso não Autorizado").build());
Run Code Online (Sandbox Code Playgroud)