【问题标题】:Get JSON message in JAX-RS web service filter在 JAX-RS Web 服务过滤器中获取 JSON 消息
【发布时间】:2016-03-07 09:58:41
【问题描述】:

我有一个 Web 服务方法如下(部署在 WebLogic 12.2.1 上),我可以在 POJO 对象“requestParameters”中接收 JSON 请求正文:

@POST
@SessionChecker
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("LogIn")
public Response logIn(@Context HttpServletRequest request, Parameters requestParameters) {
    ....
}

我有一个过滤器,我想在上述web服务方法被调用之前拦截请求。

@Provider
@SessionChecker
public class CheckSessionFilter implements ContainerRequestFilter {

    @Context
    private HttpServletRequest servletRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws WebApplicationException {
        ....
    }

}

在filter()方法中,如何将JSON消息体放入Parameters类型的POJO对象中?我只需要从 JSON 消息中获取一个属性。过滤完成后,JSON 消息应该原封不动地传递给 Web 服务方法。

提前致谢。

【问题讨论】:

    标签: java json jax-rs weblogic12c


    【解决方案1】:

    这就是问题所在。当您的过滤器被命中时,请求流 (InputStream) 尚未被读取。因此,如果您尝试读取它,那么 Jersey 将无法读取它,因为流只能读取一次,因此它将是空的。

    Jersey 实际上为此提供了解决方案。 ContainerRequestContext,实际上是 Jersey 特定的 ContainerRequest 的一个实例。如果您查看链接的 API,您会发现一个 bufferEntity() 方法。这允许我们读取实体,而 Jersey 将能够再次读取它。所以你的第一步就是打这个电话

    @Override
    public void filter(ContainerRequestContext requestContext)
        ContainerRequest cr = (ContainerRequest) requestContext;
        cr.bufferEntity();
    }
    

    现在你可以得到实体了。如果您查看ContainerRequest 的API,还有readEntity(..) 的方法。如果您熟悉 JAX-RS 客户端 API,您可能以前使用过 Response#readEntity(...class) 来读取响应实体。 ContainerRequest#readEntity(..) 的工作方式几乎相同。

    所以如果你知道 JSON 格式应该是什么,并且你有 POJO,你可以这样做

    POJO pojo = cr.readEntity(POJO.class);
    

    否则,如果格式因请求而异,您可以将数据提取为地图

    Map<String, Object> json = cr.readEntity(new GenericType<Map<String, Object>>(){});
    

    更新

    如果您使用的是一个 JAX-RS API,而不是 Jersey 特定的 API,那么上述方法是不可行的。相反,您需要读取流以获取 JSON,并将流设置回原处,以便 Jersey 可以读取它。如果可能看起来像

    InputStream entityIn = requestContext.getEntityStream();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    // write `entityIn` to `baos`
    byte[] bytes = baos.toByteArray();
    POJO pojo = new ObjectMapper().readValue(bytes, POJO.class);
    // do something with POJO
    requestContext.setEntityStream(new ByteArrayInputStream(bytes));
    

    当然,您需要一些 JSON 反序列化器来执行此操作。我只是在示例中使用了 Jackson。

    它不像第一个示例那样优雅,但是如果您严格遵守 JAX-RS API,您将没有太多选择。如果可以的话,我建议您将 Jersey 依赖项添加到您的项目中(编译时),以便您可以使用 API,因为无论如何您都在使用 Jersey 和 WebLogic。

    【讨论】:

    • 谢谢peeskillet!你又帮了我! :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2015-04-26
    • 2015-07-11
    • 1970-01-01
    • 2013-07-06
    相关资源
    最近更新 更多