Tl; р;
У меня есть контроллер REST в Spring-Boot, который либо возвращает MyPojo.class, либо RESTError.class.
Затем я вызываю этот контроллер из другой службы Spring с RestTemplate и хочу получить либо объект MyPojo, либо объект RESTError.
Есть ли способ сделать это, кроме проверки необработанной строки и последующего синтаксического анализа?
Подробное описание
У меня есть две Spring Services.
Давайте назовем их «сервер-сервис» и «клиент-сервис». «Клиент-сервис» должен извлечь POJO из «сервер-сервис». Если что-то пошло не так (неверный параметр, отсутствующий параметр и т. Д.), Возвращается пользовательский объект ошибки, который детализирует ошибку с помощью «сообщения разработчика» и более широкого «пользовательского сообщения».
Таким образом, если произошла ошибка, я смогу отобразить «пользовательское сообщение» в пользовательском интерфейсе.
Это только последнее средство. Конечно, я должен сначала выполнить проверку в моем «клиент-сервисе», прежде чем я вызову «сервер-сервис». Тем не менее, представьте, что кто-то меняет «сервер-сервис» без моего ведома ...
"сервер-сервис" - Код
MyPojo
@Getter @Setter @Accessors(chain = true)
public class MyPojo extends MyPojoSuper{
private String someString;
//hashCode & equals & toString
}
RESTError
Ниже приведен объект пользовательской ошибки. Он содержит сообщение об ошибке для обычного пользователя и сообщение для разработчика.
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Setter @Accessors(chain = true)
public class RESTError extends MyPojoSuper{
private String errorMessage, developerMessage;
//hashCode & equals & toString
}
@ ControllerAdvice
Класс ExceptionHandlerAdvice будет обрабатывать все сгенерированные исключения и возвращать RESTError.
@ControllerAdvice
@RequestMapping("/error")
@Slf4j
public class ExceptionHandlerAdvice {
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public RESTError missingServletRequestParameterException(MissingServletRequestParameterException ex) {
log.info("A parameter['" + ex.getParameterName() +"'] is missing.", ex);
RESTError error = new RESTError();
error.setDeveloperMessage(ex.getMessage());
error.setErrorMessage("The parameter['" + ex.getParameterName() +"'] is missing.");
return error;
}
}
"клиент-сервис - код"
Метод клиента, вызывающий «сервер-сервис»
public MyPojo getMyPojo(){
restTemplate.setErrorHandler(new MyCustomResponseErrorHandler());
return restTemplate.getForObject(getURLWithParams(), MyPojo.class);
}
Клиентская часть RESTError
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Setter @Accessors(chain = true)
public class RESTError extends MyPojoSuper{
private String errorMessage, developerMessage;
//hashCode & equals & toString
}
MyPojoSuper
@Getter @Setter @Accessors(chain = true)
public class MyPojoSuper{
public boolean error;
//equals & hashCode & toString
}
MyCustomResponseErrorHandler
@Slf4j
public class MyCustomResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
if (response.getStatusCode() != HttpStatus.OK) {
log.info("There was an error.");
return true;
}
return false;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
if (response.getStatusCode() != HttpStatus.OK) {
log.info("There was an error.");
}
}
}
Проблема
Как мне обработать мой пользовательский RESTError?
Используя RestTemplate, я могу анализировать мой JSON только один раз и только один класс (либо MyPojo.class, либо RESTError.class).
Поэтому я мог бы проанализировать строку, проверить строку, а затем снова обработать JSON в желаемый формат:
public MyPojoSuper getMyPojo() {
ObjectMapper mapper = new ObjectMapper();
restTemplate.setErrorHandler(new MyCustomResponseErrorHandler());
String res = restTemplate.getForObject(getURL(), String.class);
try {
if (res.contains("\"error\":true")) {
return mapper.readValue(res, RESTError.class);
} else {
return mapper.readValue(res, MyPojo.class);
}
} catch (IOException e) {
e.printStackTrace();
}
return new RESTResponse().setError(true);
}
Мне не нравится это решение, и я буду признателен за любые другие предложения.