@ Том: Я не думаю, что создание собственного MarshallingHttpMessageConverter пойдет вам на пользу.Встроенный конвертер возвращает вам правильный класс (класс исключений), когда происходит сбой службы, но это RestTemplate
, который не знает, как вернуть класс исключений вызываемой стороне, потому что вы указали тип ответа как класс задания.
Я прочитал исходный код RestTemplate , и вы в настоящий момент вызываете этот API: -
public <T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException {
HttpEntityRequestCallback requestCallback = new HttpEntityRequestCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters());
return execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}
Как вы можете видеть, он возвращает тип T на основе вашеготип ответа.Что вам, вероятно, нужно сделать, это создать подкласс RestTemplate
и добавить новый postForObject()
API, который возвращает объект вместо типа T, чтобы вы могли выполнить проверку instanceof
для возвращенного объекта.
ОБНОВЛЕНИЕ
Я думал о решении этой проблемы, вместо того, чтобы использовать встроенный RestTemplate
, почему бы не написать его самостоятельно?Я думаю, что лучше, чем создавать подклассы RestTemplate
, чтобы добавить новый метод.
Вот мой пример ... предоставлено, я не тестировал этот код, но он должен дать вам представление: -
// reuse the same marshaller wired in RestTemplate
@Autowired
private Jaxb2Marshaller jaxb2Marshaller;
public Object genericPost(String url) {
// using Commons HttpClient
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);
// add your data here
method.addParameter("data", "your-data");
try {
int returnCode = client.executeMethod(method);
// status code is 200
if (returnCode == HttpStatus.SC_OK) {
// using Commons IO to convert inputstream to string
String xml = IOUtil.toString(method.getResponseBodyAsStream());
return jaxb2Marshaller.unmarshal(new StreamSource(new ByteArrayInputStream(xml.getBytes("UTF-8"))));
}
else {
// handle error
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
finally {
method.releaseConnection();
}
return null;
}
Если есть обстоятельства, когда вы хотите повторно использовать некоторые изAPI от RestTemplate
, вы можете создать адаптер, который обернет вашу пользовательскую реализацию и повторно использовать RestTemplate
API, фактически не выставляя RestTemplate
API по всему вашему коду.
Например, вы можете создать интерфейс адаптераПримерно так: -
public interface MyRestTemplateAdapter {
Object genericPost(String url);
// same signature from RestTemplate that you want to reuse
<T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables);
}
Конкретный пользовательский шаблон отдыха выглядит примерно так: -
public class MyRestTemplateAdapterImpl implements MyRestTemplateAdapter {
@Autowired
private RestTemplate restTemplate;
@Autowired
private Jaxb2Marshaller jaxb2Marshaller;
public Object genericPost(String url) {
// code from above
}
public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) {
return restTemplate.postForObject(url, request, responseType);
}
}
Я все еще думаю, что этот подход намного чище, чем использование подклассов RestTemplate
больше контроля над тем, как вы хотите обрабатывать результаты вызовов веб-службы.