[英]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.