gpt4 book ai didi

java - Jersey 和 Spring 中的全局异常处理?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:20:37 26 4
gpt4 key购买 nike

我正在使用 Jersey & Spring 3.2 以及 Open CMIS 开发 RESTful web 服务。

我没有使用 Spring 的 MVC 模式,它只是 Spring IOC 和 Jersey SpringServlet, Controller 类类似于下面的代码

@GET
@Path("/{objId:.+}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)

public statusMsg addObject(@PathParam("objId") String objId{

return repoService.addObject(objId);
}

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

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

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

经过更多研究,我发现 Jersey 提供了 ExceptionMapper 来处理自定义异常,但我想捕获更多 CMIS 异常或默认异常或 IO 异常等。

问题二:ExceptionMapper怎么办?

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

提前致谢。

最佳答案

我将 jersey2.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 { // 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类都扩展了这个抽象类)

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(至少这个映射器可以捕获任何未定义指定异常映射器的异常。)

@Provider
public class ExceptionMapper extends AbstractExceptionMapper implements
javax.ws.rs.ext.ExceptionMapper<Exception> {

@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<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类。

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

您还没有在整个应用程序的任何地方使用 try catch 和 throw。

我的代码设计使用这样的 throws at 方法,这使得通过 ExceptionMapper 类进行管理。

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

所以在上面的方法中,我只为我可以预期的所有异常创建了 1 个类,对于任何未知的异常,基本异常都将在那里捕获。现在在我的应用程序中的任何地方,如果发生任何异常,它都会出现 CentralControllerException 并发回带有 http 状态代码的适当响应。 Q.2.您是否预见到上述方法会出现任何问题。

我认为如果项目简单或从不更新/修改项目(项目生命周期很短),您的单类异常映射器方法就可以了。但是……我从不采用这种方法。简单地说,如果需要管理更多的异常,这个方法就会变得庞大和复杂,并且变得难以阅读和维护。

在我的政策中,OOP 应该在任何级别的代码(类计划、DI 计划)中使用多态性策略,这种方法的某些部分目的是在代码中排除 if/switch block 。并且这种思想使每个方法的代码都短而简单,“领域逻辑”清晰,代码变得难以修改。

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

顺便说一下,目前系统处理结果是一样的。但是如果需要降低 future 的开发成本,就不应该采取接近一级的异常处理方案。因为如果简单地放弃代码和重构状态,项目代码死得更快。

这是我的想法以及原因。

问候。

关于java - Jersey 和 Spring 中的全局异常处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25850486/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com