java - 使用异常处理 Java REST API 的应用程序和业务故障场景

标签 java design-patterns error-handling exception-handling restful-architecture

我正在开发一个 Java 应用程序,并且在我的资源类中定义了所有 JAX-RS API 方法。我还在我的资源类中使用依赖注入(inject)将每个任务委托(delegate)给它自己的服务类:

class Resource {

    // Services are injected.
    // Each service has a couple of failure scenarios.
    // Exp. Request Not valid, Id not valid, Database internal error, etc.
    DBService dbService;
    validationService validationService;
    searchService searchService;

    @GET(user/:id)
    public User getUser(int id) {
        try {
            validationService.validate(request);
            dbService.getUser(id);
            searchService.index(request);
            ...
        } catch (UserNotFoundException e) {
            // return proper http response code and message
        } catch (UserBannedException e) {
            ...
        } catch (DBInternalError e) {
            ...
        } ... 

    }
}

对于每个 Service 类中的每个故障场景,我都为该故障场景创建了一个特定的异常,并将其抛出到 Service 类中,并在 API Resource 类中处理所有这些异常。我使用异常作为我的资源关于失败场景的信号,并返回正确的 HTTP 状态代码和消息。

我得到的一个提示是我正在创建很多异常类,而我的 Resource 类有一长串用于不同故障场景的 catch block 。

一个建议的解决方案是,例如在我的 validationService 中,我返回一个 false boolean 值而不是异常,在我的资源中,我放置了一个 if/else 语句并返回正确的状态代码。但是我不喜欢这个解决方案,因为它使我的 api 充满了 if/else 语句并且线性度降低。

我的问题是,我的用例可以有很多异常类吗?有没有更好的架构供我使用?

最佳答案

我建议不要在您的资源层中捕获它们。

您的服务层应该了解业务逻辑,因此请进行检查和验证,并使用适当的错误消息抛出您的业务异常,并让异常映射器 - https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ExceptionMapper.html捕捉它们并创建相关的响应。

这样你就没有很多 try catch block 或 if else 语句。

例子:

人资源.java

@RequestScoped
@Path("/person")
@Produces({ "application/json" })
@Consumes({ "application/json" })
public class PersonResource {

    public PersonResource() {}

    @Inject
    PersonService personService;

    @POST
    @Path("/add")
    public void addPerson(Person person) throws MyValidationException{
        personService.add(person);
    }
...

人事服务.java
@RequestScoped
public class PersonServiceImpl implements PersonService {

    @Inject
    PersonDAO personDAO;

    @Transactional
    @Override
    public Long add(Person person) throws MyValidationException {

    //checking for existing person
    List<Person> list = personDAO.find(person.getName(), person.getDob());

    //if not found, save new person
    if(list == null || list.isEmpty()){
        Long id = personDAO.save(person);
        return id;
    }

    //otherwise throw exception
    String message = "Person already exists: '" + person.getName + "'";
    throw new MyValidationException(message);
}
...

ValidationExceptionMapper.java
@Provider
public class ValidationExceptionMapper implements ExceptionMapper<MyValidationException>{

    @Override
    public Response toResponse(MyValidationException e) {
        e.printStackTrace();
        String errorMessage = e.getMessage();
        return Response.status(Response.Status.BAD_REQUEST)//or whatever other status is more appropriate
                .entity(errorMessage)
                .build();
    }
}

因此,通过这种方式,您可以拥有与创建业务异常一样多的异常映射器,这样您的业务或资源层就不会受到所有异常处理的污染。

异常映射器也知道如何处理异常层次结构。

并让客户端处理响应错误状态和正文(错误消息)。

关于java - 使用异常处理 Java REST API 的应用程序和业务故障场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41204808/

相关文章:

java - java中synchronized(expr){}中expr的意义

java - LinkedList subList 返回 List 而不是 LinkedList?

ios - 在许多使用 VIPER 的 Controller 上使用的功能的更好位置在哪里?

ajax - Node.js Express-根据错误类型不同地处理错误

java - 异常处理,catch导致while循环停止

java - 转换为 JAR 文件时未找到 UCanAccess 驱动程序

c++ - 节点的迭代层次结构 - 访客和复合?

c++ - 复制链接在一起的类

grails - Grails-自定义Flash.message渲染

python - 为什么打印出来的格式会引发NoneType错误?