繁体   English   中英

使用异常处理Java REST API的应用程序和业务失败方案

[英]handling application and business failure scenarios for a java REST API using exceptions

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

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类中的每个失败方案,我都会为该失败方案创建一个特定的Exception,并将其抛出Service类中,并在API Resource类中处理所有这些异常。 我正在使用Exception作为有关失败情况的资源信号,并返回正确的HTTP状态代码和消息。

我收到的一个抱怨是,我正在创建许多Exception类,而Resource类却包含一长串针对不同故障情况的catch块。

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

我的问题是,在我的用例中可以有很多异常类,并且可以使用更好的体系结构吗?

我建议不要在“ 资源”层中捕获它们。

您的服务层应该意识到的业务逻辑,所以做你的检查和验证,并用正确的错误信息会让你的业务异常,让异常映射器- https://docs.oracle.com/javaee/7/api/javax/ ws / rs / ext / ExceptionMapper.html捕获它们并创建相关响应。

这样,您就不会有很多try catch块,也不会有其他语句

例:

PersonResource.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);
    }
...

PersonService.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();
    }
}

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM