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

时间:2018-04-05 10:30:54

标签: java spring-boot exception-handling jersey jax-rs

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

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设置为值&#34; uri&#34;。在此之后,调用toResponse方法。我的uriInfo实例变量被重置。为什么?然而,当我将实例变量设为静态时,保留该值。

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

***** UPDATE *****

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

当我们抛出新的CustomFilterBadRequest(&#34; uri&#34;,&#34; msg&#34;)时,会创建一个对象,其状态为uriInfo,初始化为值uri。我们将此对象称为object2。

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

并且我们不必在Custom异常映射器中仅使用类变量。

这种实现非常混乱。我已经在下面的答案中更新了直接的实现。

3 个答案:

答案 0 :(得分:0)

问题是在JAX-RS运行时注册的toResponse(...)实例上调用CustomFilterBadRequest方法。如果在注册中使用no-arg构造函数,那么uriInfo总是将其默认值设置为null。

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

例外:

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;
  }
}

ExceptionMapper:

@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();
  }
}

答案 1 :(得分:0)

我理解这个问题背后的原因。

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

抛出自定义异常时,将创建自定义异常对象,JAX-RS运行时搜索异常映射器以映射异常。如果未找到,则只映射到默认的异常映射器。如果找到自定义异常映射器,则调用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();
}

}

非常感谢大家的回应。

答案 2 :(得分:0)

我很确定这就是你要做的全部:

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静止。这会导致巨大的并发问题。