Java 处理REST资源中的运行时异常并将其映射到JAX-RS响应
我有一个连接到数据库的RESTful web应用程序,它具有普通的REST、业务逻辑服务和持久性层。在RESTful层中,处理运行时错误(如数据库连接不可用)的JAX-RS标准方法是什么?我相信下面的方法,我用try/catch for the Throwable包装对我的服务/持久性层的任何调用,并抛出我的自定义MyApprumentMeException,这有点尴尬。有什么建议吗 RESTful服务:Java 处理REST资源中的运行时异常并将其映射到JAX-RS响应,java,rest,jax-rs,Java,Rest,Jax Rs,我有一个连接到数据库的RESTful web应用程序,它具有普通的REST、业务逻辑服务和持久性层。在RESTful层中,处理运行时错误(如数据库连接不可用)的JAX-RS标准方法是什么?我相信下面的方法,我用try/catch for the Throwable包装对我的服务/持久性层的任何调用,并抛出我的自定义MyApprumentMeException,这有点尴尬。有什么建议吗 RESTful服务: @Path("service") @Consumes({"application/json
@Path("service")
@Consumes({"application/json"})
@Produces({"application/json"})
public class MyResource {
@GET
@Path("/{id}")
public Response getPage(@PathParam("id") long id){
Object test=null;
try {
test = ...
//call business logic service method here which makes a call to database and populates test instance
} catch (Throwable e) {
throw new MyAppRuntimeException("custom error message string");
}
if(test != null){
return Response.ok(test).build();
}else{
return Response.status(Status.NOT_FOUND).build();
}
}
}
public class MyAppRuntimeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public MyAppRuntimeException(String message) {
super(message);
}
public MyAppRuntimeException(String message, Throwable cause) {
super(message, cause);
}
}
@Provider
public class MyAppRuntimeExceptionMapper implements ExceptionMapper<MyAppRuntimeException> {
private static final String ERROR_KEY = "DATA_ERROR";
@Override
public Response toResponse(MyAppRuntimeException exception) {
ErrorMessage errorMessage = new ErrorMessage(ERROR_KEY, exception.getMessage(), null);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(errorMessageDTO).build();
}
}
自定义异常:
@Path("service")
@Consumes({"application/json"})
@Produces({"application/json"})
public class MyResource {
@GET
@Path("/{id}")
public Response getPage(@PathParam("id") long id){
Object test=null;
try {
test = ...
//call business logic service method here which makes a call to database and populates test instance
} catch (Throwable e) {
throw new MyAppRuntimeException("custom error message string");
}
if(test != null){
return Response.ok(test).build();
}else{
return Response.status(Status.NOT_FOUND).build();
}
}
}
public class MyAppRuntimeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public MyAppRuntimeException(String message) {
super(message);
}
public MyAppRuntimeException(String message, Throwable cause) {
super(message, cause);
}
}
@Provider
public class MyAppRuntimeExceptionMapper implements ExceptionMapper<MyAppRuntimeException> {
private static final String ERROR_KEY = "DATA_ERROR";
@Override
public Response toResponse(MyAppRuntimeException exception) {
ErrorMessage errorMessage = new ErrorMessage(ERROR_KEY, exception.getMessage(), null);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(errorMessageDTO).build();
}
}
异常JAX-RS响应映射器:
@Path("service")
@Consumes({"application/json"})
@Produces({"application/json"})
public class MyResource {
@GET
@Path("/{id}")
public Response getPage(@PathParam("id") long id){
Object test=null;
try {
test = ...
//call business logic service method here which makes a call to database and populates test instance
} catch (Throwable e) {
throw new MyAppRuntimeException("custom error message string");
}
if(test != null){
return Response.ok(test).build();
}else{
return Response.status(Status.NOT_FOUND).build();
}
}
}
public class MyAppRuntimeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public MyAppRuntimeException(String message) {
super(message);
}
public MyAppRuntimeException(String message, Throwable cause) {
super(message, cause);
}
}
@Provider
public class MyAppRuntimeExceptionMapper implements ExceptionMapper<MyAppRuntimeException> {
private static final String ERROR_KEY = "DATA_ERROR";
@Override
public Response toResponse(MyAppRuntimeException exception) {
ErrorMessage errorMessage = new ErrorMessage(ERROR_KEY, exception.getMessage(), null);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(errorMessageDTO).build();
}
}
@Provider
公共类MyAppRuntimeExceptionMapper实现ExceptionMapper{
私有静态最终字符串错误\u KEY=“数据\u错误”;
@凌驾
公众响应(MyApprumentMeException例外){
ErrorMessage ErrorMessage=新的ErrorMessage(ERROR_键,exception.getMessage(),null);
返回Response.status(status.INTERNAL_SERVER_ERROR).entity(errorMessageDTO.build();
}
}
只要让您的异常类扩展WebApplicationException
并将其抛出到您喜欢的任何地方即可。您可以在下面的示例中看到,您可以以任何必要的方式自定义响应。快乐编码
注意:此示例处理403
错误,但您可以轻松创建异常以处理500
、503
等
package my.package.name;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.Serializable;
public class Http401NotAuthorizedException extends WebApplicationException implements Serializable {
private static final long serialVersionUID = 1L;
public Http401NotAuthorizedException(String msg){
super(
Response
.status(Response.Status.FORBIDDEN)
.header("Pragma", "no-cache, no-store")
.header("Cache-Control", "no-cache, no-store")
.header("Expires", "0")
.entity(msg)
.build()
);
}
}
您是否可以控制来自业务逻辑的异常?您可以直接映射这些异常,并避免catch-Throwable,这可能会对您隐藏代码(例如空指针异常)和性能(例如内存不足错误)。还禁止对响应代码的状态进行适当的描述,而不是说“服务不可用”?您的要求会要求这样做,但需要考虑一些事情。:)默认情况下,我认为未捕获的异常会导致内部服务器错误,这也可以根据您的需要/您希望与restful客户端定义的契约来确定。如果test=null,您还可以抛出WebApplicationException,这样,您就可以在OK的情况下返回值测试。@Charlie-我可以控制业务逻辑中可能发生的一些已知的异常,这些异常是使用不同的异常和映射器类抛出和映射的。我认为Status.INTERNAL_SERVER_ERROR比bidden或service unavailable更合适,因为NullPointerException并不意味着它不可用。@c12为什么不声明自己的
ExceptionMapper
处理泛型异常
。然后声明getPage(..)抛出异常
,并让映射器处理抛出的异常?