IT

응답 유형에 적합한 HttpMessageConverter를 찾을 수 없습니다.

itgroup 2023. 8. 6. 10:00
반응형

응답 유형에 적합한 HttpMessageConverter를 찾을 수 없습니다.

스프링을 사용하여 다음 코드를 사용합니다.

List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
for(HttpMessageConverter httpMessageConverter : messageConverters){
  System.out.println(httpMessageConverter);
}
ResponseEntity<ProductList> productList = restTemplate.getForEntity(productDataUrl,ProductList.class);

알겠습니다

org.springframework.http.converter.ByteArrayHttpMessageConverter@34649ee4
org.springframework.http.converter.StringHttpMessageConverter@39fba59b
org.springframework.http.converter.ResourceHttpMessageConverter@383580da
org.springframework.http.converter.xml.SourceHttpMessageConverter@409e850a
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@673074aa
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter@1e3b79d3
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@52bb1b26

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class com.mycopmany.ProductList] and content type [text/html;charset=UTF-8]

포조의 토막글:

@XmlRootElement(name="TheProductList")
public class ProductList {

@XmlElement(required = true, name = "date")
private LocalDate importDate;

봄의 관점에서 볼 때, 어떤 것도.HttpMessageConverter에 등록된 인스턴스RestTemplate변환할 수 있습니다.text/html에 만족하는.ProductList물건.관심의 방법은.HttpMessageConverter#canRead(Class, MediaType)위의 모든 반품에 대한 구현false,포함하여Jaxb2RootElementHttpMessageConverter.

아니었기 때문에HttpMessageConverterHTTP 응답을 읽을 수 있습니다. 예외로 처리가 실패합니다.

서버 응답을 제어할 수 있는 경우, 서버 응답을 수정하여 다음을 설정합니다.Content-type로.application/xml,text/xml아니면 뭔가 일치하는 것.application/*+xml.

서버 응답을 제어하지 않는 경우, 자신의 응답을 작성하고 등록해야 합니다.HttpMessageConverter(Spring 클래스를 확장할 수 있음, 참조)AbstractXmlHttpMessageConverter및 하위 클래스)를 읽고 변환할 수 있습니다.text/html.

당신은 또한 간단히 말할 수 있습니다.RestTemplate모든 미디어 유형 허용:

@Bean
public RestTemplate restTemplate() {
   final RestTemplate restTemplate = new RestTemplate();

   List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
   MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
   converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
   messageConverters.add(converter);
   restTemplate.setMessageConverters(messageConverters);

   return restTemplate;
}

Spring Boot을 사용하는 경우 클래스 경로에 Jackson 종속성이 있는지 확인할 수 있습니다.다음을 통해 수동으로 이 작업을 수행할 수 있습니다.

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

또는 웹 스타터를 사용할 수 있습니다.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

모든 답변 외에도, 만약 당신이 응답을 받는다면.text/html당신이 다른 것을 기대하는 동안 (즉, 당신은)application/json), 서버 측에서 오류가 발생했으며(예: 404) 데이터 대신 오류 페이지가 반환되었음을 시사할 수 있습니다.

그래서 제 경우에 그런 일이 있었습니다.누군가의 시간을 절약할 수 있기를 바랍니다.

서버 미디어 유형 응답을 변경할 수 없는 경우 GsonHttpMessageConverter를 확장하여 추가 지원 유형을 처리할 수 있습니다.

public class MyGsonHttpMessageConverter extends GsonHttpMessageConverter {
    public MyGsonHttpMessageConverter() {
        List<MediaType> types = Arrays.asList(
                new MediaType("text", "html", DEFAULT_CHARSET),
                new MediaType("application", "json", DEFAULT_CHARSET),
                new MediaType("application", "*+json", DEFAULT_CHARSET)
        );
        super.setSupportedMediaTypes(types);
    }
}

RestTemplateXML이라는 클래스를 구성하여 RestTemplate를 확장할 수 있습니다.그런 다음 재정의doExecute(URI, HttpMethod, RequestCallback, ResponseExtractor<T>)그리고 분명히 얻어냅니다.response-headers세트content-type로.application/xml.

이제 Spring은 헤더를 읽고 'application/xml'임을 알게 되었습니다.그것은 일종의 해킹이지만 효과가 있습니다.

public class RestTemplateXML extends RestTemplate {

  @Override
  protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,
        ResponseExtractor<T> responseExtractor) throws RestClientException {

     logger.info( RestTemplateXML.class.getSuperclass().getSimpleName() + ".doExecute() is overridden");

     Assert.notNull(url, "'url' must not be null");
     Assert.notNull(method, "'method' must not be null");
     ClientHttpResponse response = null;
     try {
        ClientHttpRequest request = createRequest(url, method);
        if (requestCallback != null) {
           requestCallback.doWithRequest(request);
        }
        response = request.execute();

        // Set ContentType to XML
        response.getHeaders().setContentType(MediaType.APPLICATION_XML);

        if (!getErrorHandler().hasError(response)) {
           logResponseStatus(method, url, response);
        }
        else {
           handleResponseError(method, url, response);
        }
        if (responseExtractor != null) {
           return responseExtractor.extractData(response);
        }
        else {
           return null;
        }
     }
     catch (IOException ex) {
        throw new ResourceAccessException("I/O error on " + method.name() +
              " request for \"" + url + "\":" + ex.getMessage(), ex);
     }
     finally {
        if (response != null) {
           response.close();
        }
     }

  }

  private void logResponseStatus(HttpMethod method, URI url, ClientHttpResponse response) {
     if (logger.isDebugEnabled()) {
        try {
           logger.debug(method.name() + " request for \"" + url + "\" resulted in " +
                 response.getRawStatusCode() + " (" + response.getStatusText() + ")");
        }
        catch (IOException e) {
           // ignore
        }
     }
  }

  private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException {
     if (logger.isWarnEnabled()) {
        try {
           logger.warn(method.name() + " request for \"" + url + "\" resulted in " +
                 response.getRawStatusCode() + " (" + response.getStatusText() + "); invoking error handler");
        }
        catch (IOException e) {
           // ignore
        }
     }
     getErrorHandler().handleError(response);
  }
}

사용해 보십시오.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.1</version>
</dependency>

또는 사용할 수 있습니다.

public void set지원되는 미디어 유형(지원되는 미디어 유형 나열)

에 속하는 방법AbstractHttpMessageConverter<T>덧붙이자면ContentTypes당신이 좋아하는.이 방법으로 할 수 있습니다.MappingJackson2HttpMessageConverter canRead()응답을 원하는 클래스(이 경우에는 ProductList Class)로 변환합니다.

이 단계는 스프링 컨텍스트 초기화와 연결되어야 한다고 생각합니다.예를 들어, 을 사용하여

ApplicationListener {...} 구현

Vadim Zin4uk의 답변은 기존 GsonHttpMessageConverter 클래스를 사용하지만 setSupportedMediaType() setSupportedMediaType() setter를 호출하는 것입니다.

스프링 부팅 앱의 경우 구성 클래스에 다음 항목이 추가됩니다.

@Bean
public GsonHttpMessageConverter gsonHttpMessageConverter(Gson gson) {
    GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
    converter.setGson(gson);
    List<MediaType> supportedMediaTypes = converter.getSupportedMediaTypes();
    if (! supportedMediaTypes.contains(TEXT_PLAIN)) {
        supportedMediaTypes = new ArrayList<>(supportedMediaTypes);
        supportedMediaTypes.add(TEXT_PLAIN);
        converter.setSupportedMediaTypes(supportedMediaTypes);
    }
    return converter;
}

이것이 문제에 대한 답은 아니지만 적절한 메시지 변환기를 찾을 수 없다는 예외를 발견했을 때 이 질문에 답하는 사람이 있다면, 여기 제 문제와 해결책이 있습니다.

4.0.9 봄에 우리는 이것을 보낼 수 있었습니다.

    JSONObject jsonCredential = new JSONObject();
    jsonCredential.put(APPLICATION_CREDENTIALS, data);

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

ResponseEntity<String> res = restTemplate.exchange(myRestUrl), HttpMethod.POST,request, String.class);

Spring 4.3.5 릴리스에서는 컨버터를 찾을 수 없다는 메시지와 함께 오류가 표시되기 시작했습니다.

변환기는 클래스 경로에 있는 경우 등록됩니다. 변환기가 있으면 변환기가 등록됩니다.

Jackson-asl은 여전히 수업 경로에 있었지만 봄까지 인정받지 못했습니다.잭슨-asl을 더 빠른 xml 잭슨 코어로 대체했습니다.

일단 우리가 추가하면, 나는 컨버터가 등록되는 것을 볼 수 있었습니다.

enter image description here

또한 "응답을 추출할 수 없습니다. 응답 유형에 적합한 HttpMessageConverter를 찾을 수 없습니다..."라는 동일한 오류 메시지가 표시되었습니다.

변환할 개체 유형을 반환하지 않는 링크에서 정보를 가져오거나 링크에서 아무것도 반환하지 않을 때 발생했습니다.시도 캐치 블록을 사용하여 처리했습니다.

 try {
        status = restTemplate
            .getForObject(statusResourceUrl, Status.class);

        //TODO add new exceptions if necessary or simply use Exception
    } catch (BeanCreationException | UnknownContentTypeException | HttpClientErrorException e) {
        status.setStatus("DOWN");
        System.out.println("exception " + e.getMessage());
    }

저도 지난주에 같은 문제에 직면했습니다.승인된 것으로 표시되었지만 작동하지 않는 위의 해결책을 시도했습니다.

언제 오는지 : 외부 URL(REST 호출)을 호출하는 동안 응답이 복잡한 개체입니다.

잘못된 것은 아래 코드를 사용하여 변환기를 불필요하게 추가하는 것이었습니다.

org.springframework.web.client.restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));

솔루션:아래의 종속성만 추가하면 됩니다.

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>

스프링 부트는 모든 기본 메시지 변환기를 추가하기 때문입니다.추가할 필요가 없습니다.심지어 JaxB 의존성도 없습니다.존재하는 경우 삭제하고 사용해 보십시오.

댄크!

언급URL : https://stackoverflow.com/questions/21854369/no-suitable-httpmessageconverter-found-for-response-type

반응형