我使用Jersey 2.11与Tomcat,并且几乎所有的异常都通过ExceptionMapper处理。(在领域逻辑中,只有DB回滚过程使用try-catch代码。)
我认为带有@Provider的ExceptionMapper可以自动选择正确的ExceptionMapper。因此,我认为这个功能能够满足“我想捕获更多的CMIS异常或默认异常或IO异常等”的需求。
以下是我的ExceptionMapper设计代码:
1.一些Jersey根资源类
@GET
@Produces("application/json")
public String getUser(@NotNull @QueryParam("id") String id,
@NotNull @QueryParam("token") String token) throws Exception {
someComplexMethod(id, token);
return CLICHED_MESSAGE;
}
2.异常映射器包。com.yourdomain.exceptionmapper
AbstractExceptionMapper.java(所有的ExceptionMapper类都继承自这个抽象类)
public abstract class AbstractExceptionMapper {
private static Logger logger = LogManager.getLogger();
protected Response errorResponse(int status, ResponseEntity responseEntity) {
return customizeResponse(status, responseEntity);
}
protected Response errorResponse(int status, ResponseEntity responseEntity, Throwable t) {
logger.catching(t);
return customizeResponse(status, responseEntity);
}
private Response customizeResponse(int status, ResponseEntity responseEntity) {
return Response.status(status).entity(responseEntity).build();
}
}
ExceptionMapper.java(至少此映射器可以捕获任何未定义指定异常映射器的异常。)
@Provider
public class ExceptionMapper extends AbstractExceptionMapper implements
javax.ws.rs.ext.ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception e) {
ResponseEntity re = new ResponseEntity(Code.ERROR_MISC);
return this.errorResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, re, e);
}
}
WebApplicationExceptionMapper.java(指定WebApplicationException)
@Provider
public class WebApplicationExceptionMapper extends AbstractExceptionMapper implements
ExceptionMapper<WebApplicationException> {
@Override
public Response toResponse(WebApplicationException e) {
ResponseEntity re = new ResponseEntity(Code.ERROR_WEB_APPLICATION);
return this.errorResponse(e.getResponse().getStatus(), re, e);
}
}
ConstraintViolationExceptionMapper.java(指定Hibernate Validator ConstraintViolationException)
@Provider
public class ConstraintViolationExceptionMapper extends AbstractExceptionMapper implements
ExceptionMapper<ConstraintViolationException> {
@Override
public Response toResponse(ConstraintViolationException e) {
ResponseEntity re = new ResponseEntity(Code.ERROR_CONSTRAINT_VIOLATION);
List<Map<String, ?>> data = new ArrayList<>();
Map<String, String> errorMap;
for (final ConstraintViolation<?> error : e.getConstraintViolations()) {
errorMap = new HashMap<>();
errorMap.put("attribute", error.getPropertyPath().toString());
errorMap.put("message", error.getMessage());
data.add(errorMap);
}
re.setData(data);
return this.errorResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, re, e);
}
}
..和其他指定的异常可以创建ExceptionMapper类。
根据我的经验,异常映射器是一个高级概念,专注于领域逻辑。它可以从领域逻辑中驱除无聊的散乱try-catch块代码。
因此,我希望在问题3中你能感受到“Yes i am”,以解决您的环境中的问题。
您没有在应用程序中使用try catch和throw。
我的代码设计在方法中使用throws,这使得通过ExceptionMapper类进行管理。
public String getUser(@NotNull @QueryParam("id") String id,
@NotNull @QueryParam("token") String token) throws Exception
在上述方法中,我创建了一个类来处理所有可能出现的异常,对于任何未知异常,都可以使用基本异常来捕获。
现在,在我的应用程序中,无论何时发生任何异常,它都会进入CentralControllerException,并返回适当的响应和HTTP状态码。
Q.2. 您是否预见到上述方法存在任何问题。
我认为,如果是简单的项目或从不更新/修改项目(项目生命周期短),您的一类异常映射器方法就可以了。
但是...我从未采用过这种方法。简单地说,如果需要管理更多的异常,则此方法变得复杂且难以阅读和维护。
在我的策略中,面向对象编程应该使用多态策略来计划代码(类计划、DI计划),并且这种方法的某些部分旨在消除代码中的if/switch块。这个想法使每个方法的代码变得简短和简单,清晰地表达“领域逻辑”,并使代码变得更加耐用。
所以我创建了实现ExceptionMapper并委托给DI的类,该ExceptionMapper类管理异常。(因此,DI管理替换您的单个类If块管理的异常处理,这通常是一种重构方法,类似于Extract xxx
http://refactoring.com/catalog/extractClass.html。在我们的讨论案例中,单个类和一个方法太忙了,因此采用每个ExceptionMapper类的方法,并且DI调用适当的类和方法策略。)
顺便说一下,系统处理结果在目前阶段是相同的。但是,如果需要减少未来的开发成本,则不应采用一类异常处理计划的方法。因为如果放弃简单的代码和重构状态,项目代码会更快死亡。
这是我的想法和原因。
问候。