我正在开发一个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语句而且不那么线性。
我的问题是,为我的用例提供许多异常类是否可以,是否有更好的架构供我使用?
答案 0 :(得分:0)
我建议不要在资源图层中删除它们。
您的服务层应该了解业务逻辑,因此请进行检查和验证,并使用正确的错误消息抛出业务异常,并让异常映射器 - https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ExceptionMapper.html捕获它们并创建相关响应。
这样你就不会有很多尝试捕获块,也没有 if else语句。
示例:
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();
}
}
因此,通过这种方式,您可以创建与业务异常一样多的异常映射器,这样您的业务或资源层就不会受到所有异常处理的污染。
异常映射器也知道如何处理异常层次结构。
让客户端处理响应错误状态和正文(错误消息)。