我正在构建一个基于Spring boot微服务的应用程序,我无法将我的错误消息从包含所有业务逻辑的服务传播回webapp。在我的服务中,我抛出的异常如下:
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class Http400ServiceException extends Exception {
public Http400ServiceException() {
super("Some error message");
}
}
一切都按预期运行,按预期发送响应代码。因此,如果我的服务发送了403异常,我将在webapp中获得403。我现在要做的是从我的服务中的例外中获取错误消息。
问题
当我以一种产生403的方式从其他客户端戳我的服务时,响应(用JSON)看起来像这样:
{
"timestamp": 1459453512220
"status": 403
"error": "Forbidden"
"exception": "com.mysite.mypackage.exceptions.Http403ServiceException"
"message": "Username Rob must be between 5 and 16 characters long"
"path": "/createLogin"
}
但是,出于某种原因,我无法从我的webapp访问“消息”字段。我在webapp中有一些通用的错误处理代码,如下所示:
@Override
public RuntimeException handleException(Exception e) {
...
if (e instanceof HttpClientErrorException) {
HttpClientErrorException httpError = (HttpClientErrorException) e;
LOGGER.info(httpError.getResponseBodyAsString());
}
...
}
但是当我查看我的日志/在调试中运行我的应用程序时,httpError.getResponseBodyAsString()
返回null。它有正确的响应代码,只是没有响应主体。
如果有人对出了什么问题有任何见解,我会非常感激。
答案 0 :(得分:0)
因此,当我们在应用程序的其他区域工作时,我们将此问题暂停了几个月。但是,如果其他人在尝试解决类似问题时看到这一点,我最终采用的方法是以下
为要实现的所有服务的所有响应创建一个接口,并使用一个异常类型来指示该异常是由于用户错误:
public interface IModel {
boolean isError();
UserException getError();
}
在每个服务的控制器中,捕获任何异常并从中创建某种IModel:
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(UserException.class)
public IModel handleException(UserException exception) {
return exception.toModel();
}
在用于调用服务的组件中,如果响应上有UserException,则抛出它,否则返回响应主体:
public <T extends IModel> T makeCall(Object payload, Endpoint<T> endpoint) throws UserException {
...
ResponseEntity<T> response = restTemplate.postForEntity(endpoint.getEndpointUrl(), payload, endpoint.getReturnType());
if (response.getBody().isError()) {
throw response.getBody().getError();
}
...
return response.getBody();
}
在webapp中,使用适当的@ExceptionHandler处理异常,例如
@ExceptionHandler(UserException.class)
public ModelAndView handleUserException(UserException e) {
ModelAndView modelAndView = new ModelAndView("viewName");
modelAndView.addObject("errorMessage", e.getMessage());
return modelAndView;
}
我觉得有一个更清洁的方法,但这是迄今为止我能够提出的最好的方法。如果我找到更好的方法,我会更新这个。