泽西和spring的全球exception处理?

我正在使用Jersey&Spring 3.2和Open CMIS开发RESTful Web服务。

我没有使用Spring的MVC模式,它只是Spring IOC和Jersey SpringServlet,控制器类就像下面的代码

@GET @Path("/{objId:.+}") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public statusMsg addObject(@PathParam("objId") String objId{ return repoService.addObject(objId); } 

在repoService我正在执行业务逻辑以使用CMIS添加对象,我的问题是我正在捕获与CMIS相关的5个exception然后基本exception即exception但是对于每个服务方法我必须重复它我不想做。

我在Google上搜索,发现@ControllerAdvice是解决此类问题的最佳解决方案,您可以定义所有已检查和未检查的exception以及从应用程序中删除所有try catch块的位置。 但它只适用于MVC模式。

问题1:有没有办法在Jersey-Spring框架中使用它?

经过更多的研究后,我发现Jersey提供了ExceptionMapper来处理自定义exception,但我想捕获更多的CMISexception或默认的exception或IOexception等。

问题2:如何使用ExceptionMapper执行此操作?

问题3:我是否采用了正确的方法,或者您是否建议采用更好的方法来处理此类问题。

提前致谢。

我使用带有Tomcat的jersey2.11和ExceptionMapper几乎exception处理。 (在域逻辑中,只有DB回滚过程使用try-catch代码。)

我认为带有@Provider的ExceptionMapper会自动选择正确的ExceptionMapper。 所以我认为这个函数满足于“我想要捕获更多的CMISexception或默认的exception或IOexception等”。

这段代码是我处理ExceptionMapper的设计代码。

1.Some Jersey Root Resource Class

 @GET @Produces("application/json") public String getUser(@NotNull @QueryParam("id") String id, @NotNull @QueryParam("token") String token) throws Exception { // This level throws exceptions handled by ExceptionMapper someComplexMethod(id, token); // possible throw Exception, IOException or other exceptions. return CLICHED_MESSAGE; } 

2.ExceptionMapper包。 com.yourdomain.exceptionmapper

AbstractExceptionMapper.java (所有ExceptionMapper类都扩展了这个Abstract类)

 public abstract class AbstractExceptionMapper { private static Logger logger = LogManager.getLogger(); // Example log4j2. protected Response errorResponse(int status, ResponseEntity responseEntity) { return customizeResponse(status, responseEntity); } protected Response errorResponse(int status, ResponseEntity responseEntity, Throwable t) { logger.catching(t); // logging stack trace. return customizeResponse(status, responseEntity); } private Response customizeResponse(int status, ResponseEntity responseEntity) { return Response.status(status).entity(responseEntity).build(); } } 

ExceptionMapper.java (至少这个映射器可以捕获任何未定义的exception指定exception映射器。)

 @Provider public class ExceptionMapper extends AbstractExceptionMapper implements javax.ws.rs.ext.ExceptionMapper { @Override public Response toResponse(Exception e) { // ResponseEntity class's Member Integer code, String message, Object data. For response format. 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 { @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 { @Override public Response toResponse(ConstraintViolationException e) { ResponseEntity re = new ResponseEntity(Code.ERROR_CONSTRAINT_VIOLATION); List> data = new ArrayList<>(); Map 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); } } 

..和其他指定exception可以创建ExceptionMapper类。

根据我的经验,Exception Mapper是专注于域逻辑的高级理念。 它可以从域逻辑中驱逐出无聊的分散try-catch块代码。 因此,我希望您在问题3中感受到“是的我”,以解决您所在环境中的问题。

祝你好运。

我不能“添加评论”的答案,所以我在下面添加评论。

你没有使用try catch并在应用程序中的任何地方抛出。

我的代码设计使用抛出这样的方法,这使得由ExceptionMapper类进行管理。

 public String getUser(@NotNull @QueryParam("id") String id, @NotNull @QueryParam("token") String token) throws Exception 

因此,在上面的方法中,我为所有可以预期的exception创建了一个类,并且对于任何未知exception,基本exception将在那里捕获。 现在,在我的应用程序中,如果发生任何exception,则会发生CentralControllerException并发送回http状态代码的相应响应。 Q.2。 您是否预见到上述方法中的任何问题。

我认为如果简单的项目或永远不会更新/修改项目(项目生命周期短时间),你的一个类exception映射器方法确定。 但是……我从不接受这种方法。 简单地说,如果需要管理更多exception,这种方法变得庞大而复杂,难以阅读和维护。

在我的策略中,OOP应该使用多形态策略任何级别代码(类计划,DI计划),这种方法的一些部分旨在驱逐if / switch阻止代码。 并且这个想法使每个方法简短,简单,清晰到“域逻辑”,代码变得耐受修改。

所以我创建了实现ExceptionMapper并委托给DI,ExceptionMapper类管理exception。 (所以DI管理替换你的单个类如果块管理哪个exception处理,这通常是重构方法类似Extract xxx http://refactoring.com/catalog/extractClass.html 。在我们的讨论案例中,单个类和一个方法太忙,所以提取每个ExceptionMapper类接近和DI调用合适的类和方法策略。)

顺便说一下,系统处理结果与目前相同。 但如果需要降低未来的开发成本,不应该采取一类exception处理计划。 因为如果放弃简单的代码和重构状态,项目代码就会死得更快。

这是我的想法,为什么这样。

问候。

感谢您的回复。 我可以看到你已经根据exception类型和行为创建了多个类。

Q1。 在你的服务方法中,你抛出任何exception,如

 public void addObject(String objId) throws WebApplicationException{ } 

或者你还没有使用try catch并在应用程序中的任何地方抛出。

实际上,我已尝试过在我的web应用程序中我没有使用try,catch和throws任何地方,并且在我提到的CentralControllerException中,如下所示:

 public class CentralControllerHandler implements ExceptionMapper { @Override @Produces(MediaType.APPLICATION_JSON) public Response toResponse(Exception ex) { if(ex instanceof CmisContentAlreadyExistsException){ log.error(ex); // send Response status as 400 } if(ex instanceof IOException){ log.error(ex); // send Response status as 400 } return Response; } } 

因此,在上面的方法中,我为所有可以预期的exception创建了一个类,并且对于任何未知exception,基本exception将在那里捕获。

现在,在我的应用程序中,如果发生任何exception,则会发生CentralControllerException并发送回http状态代码的相应响应。

Q.2。 您是否预见到上述方法中的任何问题。