我正在使用Jersey学习JAX-RS(又名JSR-311)。我已经成功地创建了一个根资源,并正在摆弄参数:

@Path("/hello")
public class HelloWorldResource {

    @GET
    @Produces("text/html")
    public String get(
        @QueryParam("name") String name,
        @QueryParam("birthDate") Date birthDate) {

         // Return a greeting with the name and age
    }
}

这工作得很好,并处理当前区域内Date(String)构造函数能理解的任何格式(如YYYY/mm/dd和mm/dd/YYYY)。但如果我提供的值无效或无法理解,就会得到404响应。

例如:

GET /hello?name=Mark&birthDate=X

404 Not Found

如何自定义此行为?也许是一个不同的响应代码(可能是“400个坏请求”)?记录一个错误怎么样?也许可以在自定义报头中添加问题的描述(“糟糕的日期格式”)以帮助排除故障?或者返回一个完整的带有详细信息的Error响应,以及一个5xx状态码?


当前回答

@Provider
public class BadURIExceptionMapper implements ExceptionMapper<NotFoundException> {

public Response toResponse(NotFoundException exception){

    return Response.status(Response.Status.NOT_FOUND).
    entity(new ErrorResponse(exception.getClass().toString(),
                exception.getMessage()) ).
    build();
}
}

创建类之上。这将处理404 (NotFoundException),在toResponse方法中,您可以给出自定义响应。类似地,还有ParamException等,你需要映射它们来提供定制的响应。

其他回答

这实际上是正确的行为。Jersey将尝试为您的输入找到一个处理程序,并将尝试从提供的输入构造一个对象。在这种情况下,它将尝试使用提供给构造函数的值X创建一个新的Date对象。由于这是一个无效日期,按照惯例Jersey将返回404。

您可以重写并将出生日期作为字符串,然后尝试解析,如果您没有得到想要的结果,您可以通过任何异常映射机制(有几种)自由抛出任何您想要的异常。

我太喜欢StaxMan可能会实现QueryParam作为一个字符串,然后处理转换,重新抛出必要的。

如果特定于区域设置的行为是期望和预期的行为,您将使用以下命令返回400 BAD REQUEST错误:

抛出新的WebApplicationException(Response.Status.BAD_REQUEST);

有关更多选项,请参阅JavaDoc中的javax.ws.rs.core.Response.Status。

Jersey在解组参数失败时抛出com.sun.jersey.api.ParamException异常,因此一个解决方案是创建一个ExceptionMapper来处理这些类型的异常:

@Provider
public class ParamExceptionMapper implements ExceptionMapper<ParamException> {
    @Override
    public Response toResponse(ParamException exception) {
        return Response.status(Status.BAD_REQUEST).entity(exception.getParameterName() + " incorrect type").build();
    }
}

我也面临着同样的问题。

我想在一个中心位置捕捉所有的错误并对它们进行转换。

以下是我如何处理它的代码。

创建以下实现ExceptionMapper的类,并在该类上添加@Provider注释。这将处理所有异常。

重写toResponse方法并返回用自定义数据填充的Response对象。

//ExceptionMapperProvider.java
/**
 * exception thrown by restful endpoints will be caught and transformed here
 * so that client gets a proper error message
 */
@Provider
public class ExceptionMapperProvider implements ExceptionMapper<Throwable> {
    private final ErrorTransformer errorTransformer = new ErrorTransformer();

    public ExceptionMapperProvider() {

    }

    @Override
    public Response toResponse(Throwable throwable) {
        //transforming the error using the custom logic of ErrorTransformer 
        final ServiceError errorResponse = errorTransformer.getErrorResponse(throwable);
        final ResponseBuilder responseBuilder = Response.status(errorResponse.getStatus());

        if (errorResponse.getBody().isPresent()) {
            responseBuilder.type(MediaType.APPLICATION_JSON_TYPE);
            responseBuilder.entity(errorResponse.getBody().get());
        }

        for (Map.Entry<String, String> header : errorResponse.getHeaders().entrySet()) {
            responseBuilder.header(header.getKey(), header.getValue());
        }

        return responseBuilder.build();
    }
}

// ErrorTransformer.java
/**
 * Error transformation logic
 */
public class ErrorTransformer {
    public ServiceError getErrorResponse(Throwable throwable) {
        ServiceError serviceError = new ServiceError();
        //add you logic here
        serviceError.setStatus(getStatus(throwable));
        serviceError.setBody(getBody(throwable));
        serviceError.setHeaders(getHeaders(throwable));

    }
    private String getStatus(Throwable throwable) {
        //your logic
    }
    private Optional<String> getBody(Throwable throwable) {
        //your logic
    }
    private Map<String, String> getHeaders(Throwable throwable) {
        //your logic
    }
}

//ServiceError.java
/**
 * error data holder
 */
public class ServiceError {
    private int status;
    private Map<String, String> headers;
    private Optional<String> body;
    //setters and getters
}

一个明显的解决方案:采用字符串,转换为日期自己。这样你就可以定义你想要的格式,捕捉异常并重新抛出或自定义发送的错误。 对于解析,SimpleDateFormat应该可以正常工作。

我相信也有一些方法可以为数据类型钩子处理程序,但是在这种情况下,您可能只需要一点点简单的代码。