Java REST 服务:返回异常的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35641406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 16:52:55  来源:igfitidea点击:

REST service: The proper way of returning exception

javarestexception

提问by MaxG

I use Jersey API for my REST service. My question is: Is there a more elegant way of returning exceptions in a JSON form? Is it better to concern myself with creating a json object myself and attaching it to the response directly?

我的 REST 服务使用 Jersey API。我的问题是:是否有更优雅的方式以 JSON 形式返回异常?自己创建一个 json 对象并将其直接附加到响应是否更好?

This is a simplified example of one of the methods in the service. As you see, I use HashMap only because the method may throw an exception, in which case I need to return information about It.

这是服务中方法之一的简化​​示例。如您所见,我使用 HashMap 只是因为该方法可能会抛出异常,在这种情况下,我需要返回有关它的信息。

@Path("/admin")
public class AdminService {

    @Context
    HttpServletRequest request;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Map<Integer, String> createCompany(Company company){

        Map<Integer, String> map = new HashMap<>();
        try{
            AdminFacade adminFacade = (AdminFacade)Utility.getFacade(request);
            adminFacade.createCompany(company);
            map.put(1,"success");
        } catch (ExceptionREST e) {
            map.put(e.getErrorNumber(), e.getMessage());
        } finally {
            return map;
        }
    }
}

采纳答案by Arun B Chandrasekaran

You can create a class like the one below to represent an error,

您可以创建一个如下所示的类来表示错误,

@JsonPropertyOrder({ "code", "field", "message" })
public class ErrorInfo {

    private String code;

    private String field;

    private String message;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

You can create a class which extends an exception like this,

您可以创建一个类来扩展这样的异常,

public class InvalidInputException extends RuntimeException {

    private static final long serialVersionUID = -5027121014723838738L;

    private List<ErrorInfo> errors;

    public List<ErrorInfo> getErrors() {
        return this.errors;
    }

    public InvalidInputException(List<ErrorInfo> errors) {
        super();
        this.errors = errors;
    }

    public InvalidInputException(String message, List<ErrorInfo> errors) {
        super(message);
        this.errors = errors;
    }

}

And have a exception mapper, where you can convert the List to json and return to the user with http status code 400 (Bad Request).

并有一个异常映射器,您可以在其中将列表转换为 json 并以 http 状态代码 400(错误请求)返回给用户。

@Provider
public class InvalidInputExceptionMapper implements ExceptionMapper<InvalidInputException> {

    @Override
    @Produces(MediaType.APPLICATION_JSON)
    public Response toResponse(InvalidInputException e) {

        ResponseBuilder rb = Response.status(Status.BAD_REQUEST);

        rb.entity(e.getErrors());
        return rb.build();   
    }
}

Http Response will be,

Http 响应将是,

HTTP/1.1 400 BAD REQUEST
{
"errors": [{
    "error": {
        "code": "100",
        "field": null,
        "message": "Name is required"
    },
    "error": {
        "code": "100",
        "field": null,
        "message": "Age is required"
    }
}]

}

}

回答by ST. Kee

I believe it is quite popular that people use http response status code to handle the error. E.g. 404 status is not found 5xx is server internal error e.t.c. You can easily set the error code by using the Response object. Instead of returning a map, return a Response object.

我相信人们使用 http 响应状态代码来处理错误是很流行的。例如 404 状态未找到 5xx 是服务器内部错误等 您可以使用 Response 对象轻松设置错误代码。返回一个 Response 对象,而不是返回地图。

@Path("/admin")public class AdminService {

@Context
HttpServletRequest request;

@POST
@Produces(MediaType.APPLICATION_JSON)
public Response createCompany(Company company){

    Map<Integer, String> map = new HashMap<>();
    try{
        AdminFacade adminFacade = (AdminFacade)Utility.getFacade(request);
        Company commpany=adminFacade.createCompany(company);//this entity annotated by XmlRootElement
        Response response=Response.ok().entity(company).build();
    } catch (ExceptionREST e) {
        response=Response.status(404).build();
    } return response;
}}

To make the Restful api more robust, some will return an OK response to prevent "smart redirect" from the server and output some weird html. you can refer herefor a list of http status code and what it mean. For Java EE Response class, you can refer the official javadoc

为了使 Restful api 更加健壮,有些会返回 OK 响应以防止来自服务器的“智能重定向”并输出一些奇怪的 html。您可以在此处参考http 状态代码列表及其含义。Java EE Response类可以参考官方javadoc

回答by niharika_neo

You can wrap your error into a class, say I have an ErrorData class which has status, message and stacktrace. Everytime an exception occurs, I throw a GeneralAppException with the errordata object.

您可以将您的错误包装到一个类中,比如我有一个 ErrorData 类,它具有状态、消息和堆栈跟踪。每次发生异常时,我都会抛出一个带有 errordata 对象的 GeneralAppException。

public class GeneralAppException  extends WebApplicationException {
 public GeneralAppException(ErrorData er) {

            super(Response.status(er.getStatusCode()).
            entity(er).type(MediaType.APPLICATION_JSON).build());
          }
}

I have another class which has all the known errors, eg.

我有另一个类,其中包含所有已知错误,例如。

public static final ErrorData NODATAFOUND = new ErrorData(Response.Status.NOT_FOUND.getStatusCode(),"No data was found for given query");

public static final ErrorData CODEERROR = new ErrorData(502,"CodeError");

Your catch can look like

你的渔获物看起来像

catch (ExceptionREST e) {
        throw new GeneralAppException(ErrorData.NODATAFOUND);
    } 

Reference used : https://jersey.java.net/documentation/latest/representations.html#d0e6665

使用的参考:https: //jersey.java.net/documentation/latest/representations.html#d0e6665