为什么 Custom Exception Mapper 中的实例变量必须是静态的?

Why instance variable inside Custom Exception Mapper has to be static?

我已经实现了一个自定义异常映射器,以便在我的应用程序中抛出错误的请求。这是代码:

CustomFilterBadRequest:

package com.test.exceptions;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import java.util.Date;

public class CustomFilterBadRequest extends Exception implements
        ExceptionMapper<CustomFilterBadRequest> {

    private String uriInfo;


    public CustomFilterBadRequest() {
        super("Invalid Request. Please try again with the valid request");
    }

    public CustomFilterBadRequest(String uriInfo, String message) {
        super(message);
        this.uriInfo = uriInfo;
    }

    @Override
    public Response toResponse(CustomFilterBadRequest exception) {
        return Response.status(400).entity(new ErrorDetails(new Date(),
                400, "bad request", exception.getMessage(),this.uriInfo)).type(MediaType.APPLICATION_JSON).build();
    }
}

问题:

注: 在此示例中,我有一个名为 uriInfo 的实例变量。 从另一个服务,我做:

throw new CustomFilterBadRequest("uri","message")

立即调用构造函数并将我的 uriInfo 设置为值 "uri"。此后,toResponse 方法获取 called.My uriInfo 实例变量被重置。为什么?然而,当我将实例变量设为静态时,该值将被保留。

我无法获得关于此的任何文档。请帮忙

*****更新*****

当调用与此异常相关的 REST 端点时,将调用 CustomFilterBadRequest 的默认构造函数,创建状态 uriInfo 初始化为 null 的对象。让我们称这个对象为 object1.

当我们抛出 new CustomFilterBadRequest("uri","msg") 时,会创建一个对象,其状态 uriInfo 初始化为值 uri。我们称这个对象为 object2.

JAX-RS 运行时将 CustomFilterBadRequest 异常映射到异常映射器,这里也是 CustomFilterBadRequest。因此 toResponse 方法被调用。它从 object1 获取 uriInfo。 (这里显然是空的)

我们没有必要在自定义异常映射器中只使用 class 个变量。

这种实现方式比较混乱。我在下面的答案中更新了直接实施。

问题是在 CustomFilterBadRequest 的实例上调用了 toResponse(...) 方法,该实例已注册到 JAX-RS 运行时。如果在注册中使用 no-arg 构造函数,这就是为什么 uriInfo 始终具有默认值 null 的原因。

我建议您在一个 class 中定义异常,在另一个中定义异常处理程序。

异常:

public class CustomBadRequest extends Exception {

  private String uriInfo;

  public CustomBadRequest() {
    super("Invalid Request. Please try again with the valid request");
  }

  public CustomBadRequest(String uriInfo, String message) {
    super(message);
    this.uriInfo = uriInfo;
  }

  public String getUriInfo() {
    return uriInfo;
  }
}

异常映射器:

@Provider
public class CustomFilterBadRequest implements ExceptionMapper<CustomBadRequest> {

  @Override
  public Response toResponse(CustomBadRequest exception) {
    return Response.status(400).entity(new ErrorDetails(new Date(),
      400, "bad request", exception.getMessage(),exception.getUriInfo())).type(MediaType.APPLICATION_JSON).build();
  }
}

我了解问题背后的原因。

每当我们到达终点时,都会调用在球衣上注册的异常映射器的默认构造函数,并创建每种类型的对象,并将状态初始化为其类型的默认值。

当抛出自定义异常时,创建自定义异常对象并且JAX-RS运行时搜索异常映射器来映射异常。如果找到 none,它就映射到默认的异常映射器。如果找到自定义异常映射器,则调用 toResponse 方法。在这种情况下,我们应该在 toResponse 方法中从它的对象本身获取 customexception 的状态。

我需要这个来获取 exceptionmapper 中的 uriInfo。

这是工作代码:

CustomFilterBadRequest.java

public class CustomFilterBadRequest extends Exception {

public CustomFilterBadRequest(String message) {
    super(message);
}

}

CustomFilterBadRequestExceptionMapper.java

public class CustomFilterBadRequestExceptionMapper implements ExceptionMapper<CustomFilterBadRequest> {

private UriInfo uriInfo;

public CustomFilterBadRequestExceptionMapper(@Context UriInfo uriInfo) {
    this.uriInfo = uriInfo;
}

@Override
public Response toResponse(CustomFilterBadRequest exception) {
    return Response.status(400).entity(new ErrorDetails(Instant.now(),
            400, "bad request", exception.getMessage(),this.uriInfo.getPath())).type(MediaType.APPLICATION_JSON).build();
}

}

非常感谢大家的回复。

我很确定这就是您要做的全部事情:

CustomFilterBadRequest:

package com.test.exceptions;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import java.util.Date;

public class CustomFilterBadRequest extends Exception implements
        ExceptionMapper<CustomFilterBadRequest> {

    private String uriInfo;


    public CustomFilterBadRequest() {
        super("Invalid Request. Please try again with the valid request");
    }

    public CustomFilterBadRequest(String uriInfo, String message) {
        super(message);
        this.uriInfo = uriInfo;
    }

    @Override
    public Response toResponse(CustomFilterBadRequest exception) {
        return Response.status(400).entity(new ErrorDetails(new Date(),
                400, "bad request", exception.getMessage(),exception.uriInfo)).type(MediaType.APPLICATION_JSON).build();
    }
}

我刚把this.uriInfo改成了exception.uriInfo

基本上,当您抛出 CustomFilterBadRequestException 时,JAX-RS 会创建一个新实例来映射您抛出的异常。这个新实例的默认值为 uriInfo。所以它没有被保存。

无论你做什么,都不要让 uriInfo 静止。那会导致巨大的并发问题。