有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用异常处理java REST API的应用程序和业务故障场景的设计模式

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

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) {
            ...
        } ... 

    }
}

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

我收到的一个抱怨是,我创建了很多异常类,而我的资源类有一长串针对不同故障场景的捕获块

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

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


共 (1) 个答案

  1. # 1 楼答案

    我建议不要在你的资源层中捕捉它们

    您的服务层应该了解业务逻辑,也应该进行检查和验证,并抛出带有正确错误消息的业务异常,让异常映射程序捕捉它们并创建相关响应

    这样你就不会有太多的try catch blockif 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();
        }
    }
    

    因此,通过这种方式,您可以创建尽可能多的异常映射程序,这样您的业务或资源层就不会因为所有的异常处理而受到污染

    异常映射程序也知道如何处理异常层次结构

    并让客户端处理响应错误状态和主体(错误消息)