我正在使用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状态码?
有几种方法可以使用JAX-RS定制错误处理行为。这里有三个更简单的方法。
第一种方法是创建一个扩展WebApplicationException的Exception类。
例子:
public class NotAuthorizedException extends WebApplicationException {
public NotAuthorizedException(String message) {
super(Response.status(Response.Status.UNAUTHORIZED)
.entity(message).type(MediaType.TEXT_PLAIN).build());
}
}
要抛出这个新创建的异常,只需:
@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
// An unauthorized user tries to enter
throw new NotAuthorizedException("You Don't Have Permission");
}
注意,您不需要在throws子句中声明异常,因为WebApplicationException是一个运行时异常。这将向客户端返回401响应。
第二种更简单的方法是直接在代码中构造WebApplicationException的实例。只要您不需要实现自己的应用程序异常,这种方法就可以工作。
例子:
@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
// An unauthorized user tries to enter
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
这段代码也向客户端返回401。
当然,这只是一个简单的例子。如果需要,您可以使异常更加复杂,并且您可以生成任何您需要的http响应代码。
另一种方法是用一个小的包装器类来包装一个现有的异常(可能是ObjectNotFoundException),该类实现了用@Provider注释注释的ExceptionMapper接口。这告诉JAX-RS运行时,如果引发包装异常,则返回ExceptionMapper中定义的响应代码。
我也面临着同样的问题。
我想在一个中心位置捕捉所有的错误并对它们进行转换。
以下是我如何处理它的代码。
创建以下实现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
}
方法1:通过扩展WebApplicationException类
通过扩展WebApplicationException创建新的异常
public class RestException extends WebApplicationException {
private static final long serialVersionUID = 1L;
public RestException(String message, Status status) {
super(Response.status(status).entity(message).type(MediaType.TEXT_PLAIN).build());
}
}
现在在需要的时候抛出'RestException'。
public static Employee getEmployee(int id) {
Employee emp = employees.get(id);
if (emp == null) {
throw new RestException("Employee with id " + id + " not exist", Status.NOT_FOUND);
}
return emp;
}
您可以在此链接查看完整的应用程序。
方法2:实现ExceptionMapper
以下映射器处理类型为“DataNotFoundException”的异常
@Provider
public class DataNotFoundExceptionMapper implements
ExceptionMapper<DataNotFoundException> {
@Override
public Response toResponse(DataNotFoundException ex) {
ErrorMessage model = new ErrorMessage(ex.getErrorCode(),
ex.getMessage());
return Response.status(Status.NOT_FOUND).entity(model).build();
}
}
您可以在此链接查看完整的应用程序。