【问题标题】:How to produce error response in json如何在json中产生错误响应
【发布时间】:2015-02-20 05:31:28
【问题描述】:

我正在编写一个 Restful Webservice Impl,我通过注释 @Produces("application/json") 以 JSON 格式消费和产生响应。我也在产生 JSON 响应。这里正在处理具有错误代码和错误消息的类的异常。当出现异常时,它不会以application/json 格式生成。我使用ExceptionMapper 找到了解决方案,但它是`text/plain 格式。

sn-p

public Class Confiuration{
    @Path("getData")
    @Consumes("application/json")
    @Produces("application/json")
    public JSONGetDataResponseVo getData(GetDataRequestVo datarequestVO)
                                                          throws FaultResponse {
        JSONGetDataResponseVo response=new JSONGetDataResponseVo ();
        DataServiceValidator.validateGetConfigurationAndDataRequest(datarequestVO);
        ....
        ....
        }catch(ApplicationException applicationException){
            throw new FaultResponse(applicationException,locale);
        }  
}

故障响应映射器

@Provider
public class FaultResponseMapper implements ExceptionMapper<FaultResponse> {

    @Context
    private HttpHeaders headers;

    public Response toResponse(FaultResponse faultResponse) {
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity(faultResponse).type(MediaType.APPLICATION_JSON).build();
    }

}

应用程序异常

public abstract class ApplicationException extends Exception{

    private java.lang.String errorCode;

    public ApplicationException(String errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }


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



    public java.lang.String getErrorCode() {
        return this.errorCode;
    }


    public abstract String getLocaleMessage(Locale locale);

}

故障响应

public class FaultResponse extends WebApplicationException {

    private String errorCode;
    private String errorMessage;
    private String localErrorMessage;

    public FaultResponse(String errorCode, String errorMessage,
            String localErrorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
        this.localErrorMessage = localErrorMessage;
    }

    public FaultResponse(ApplicationException applicationException,
            Locale locale) {
        this.errorCode = applicationException.getErrorCode();
        this.errorMessage = applicationException.getMessage();
        if (locale != null
                && applicationException.getLocaleMessage(locale) != null) {
            this.localErrorMessage = applicationException
                    .getLocaleMessage(locale);
        } else {
            this.localErrorMessage = applicationException.getMessage();
        }
    }
}

那么我怎样才能以 JSON 格式生成我的 faultResponse。

【问题讨论】:

  • 这看起来很奇怪。 FaultResonse 是例外吗?我的意思是我猜这是因为你正在扔它,但这似乎很奇怪,特别是因为你也将它作为响应发送。如果您要映射ApplicationException,它似乎更正确。您可能想要显示 ApplicationException 类以及 FaultResponse 类以获得更好的帮助。
  • 您是否检查过映射器是否被调用?我猜想正在使用另一个映射器,或者异常正在冒泡到容器中。需要更完整的信息来测试
  • 应用程序异常是我的抽象类,它将被我使用的每个异常类扩展。在 sn-p 中更新应用程序异常
  • FaultResponse 呢?
  • 另外,您使用的是什么 JAX-RS 或(服务器)实现?

标签: json rest exception jax-rs


【解决方案1】:

这与您返回异常作为响应的事实有关。我会

  1. ApplicationException 制作异常映射器。
  2. 重构 FaultResponse 以不扩展和异常。只需在映射器中创建即可。
  3. 要查看响应,您需要发送除“无内容”以外的状态。你不能有一个身体在里面。发送错误请求之类的内容。
  4. 您可以将资源方法声明为throws ApplicationException。您无需抓住它并重新投掷。

我已经进行了这些更改,并且效果很好。


更新:完整测试

FaultResponse 添加了getter(编组所需)并删除了异常扩展

public class FaultResponse {
    ...
    public String getErrorCode() { return errorCode; }
    public String getErrorMessage() { return errorMessage; }
    public String getLocalErrorMessage() { return localErrorMessage; }
    ...
}

为测试和ApplicationException 实现创建了一个服务

public class ApplicationExceptionImpl extends ApplicationException { 
    public ApplicationExceptionImpl(){
        this("400", "Bad Request");
    }

    public ApplicationExceptionImpl(String errorCode, String message) {
        super(errorCode, message);
    }

    @Override
    public String getLocaleMessage(Locale locale) {
        return "Bad Request";
    }  
}

public class FaultService {
    public void doSomething() throws ApplicationException {
        throw new ApplicationExceptionImpl();
    }
}

资源类

@Path("fault")
public class FaultResource {
    
    FaultService service = new FaultService();
    
    @GET
    public Response getException() throws ApplicationException {
        service.doSomething();
        return Response.ok("Cool").build();
    }
}

异常映射器

@Provider
public class ApplicationExceptionMapper implements ExceptionMapper<ApplicationException> {

    @Override
    public Response toResponse(ApplicationException exception) {
        FaultResponse response = new FaultResponse(exception, Locale.ENGLISH);
        return Response.status(Response.Status.BAD_REQUEST)
                .entity(response).type(MediaType.APPLICATION_JSON).build();
    }  
}

ApplicationException 类保持不变

curl -v http://localhost:8080/api/fault
{"errorCode":"400","errorMessage":"Bad Request","localErrorMessage":"Bad Request"}

如果在此之后您仍然看不到 JSON,可能是您没有配置提供程序。如果是这种情况,请显示您的应用程序配置以及您的项目依赖项。

【讨论】:

  • 似乎没有调用 Mapper 来生成 JSON 媒体类型作为响应
  • 我忘了我到底做了什么,我删除了这个项目。我想我实现了ApplicationExceptionImpl。我想我仍然可以将ApplicationException 用于映射器。我还必须创建一个简单的测试服务,并从我在资源类中调用的服务方法中抛出ApplicationExceptionImpl
  • 在您的 cmets 之后,将作为抽象类的 Application Exception 类添加到我的异常映射器中,并且我没有在故障响应类中扩展任何东西。使我的资源抛出应用程序异常。但它仍然没有以 json 类型生成
  • 关于调试我在 ApplicationExceptionImpl 类中抛出的代码异常。它没有通过映射器类(提供者类)。
  • ServletException 的根本原因。 com.sun.jersey.api.container.MappableContainerException:
猜你喜欢
  • 2016-08-31
  • 2020-10-13
  • 1970-01-01
  • 2018-08-22
  • 1970-01-01
  • 1970-01-01
  • 2017-08-25
  • 1970-01-01
  • 2019-08-16
相关资源
最近更新 更多