簡體   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