如何在 Spring 启动时处理 UnsupportedMediaTypeException?

How to handle UnsupportedMediaTypeException in Spring Boot?

您好,我正在尝试在 spring 启动时使用 Webclient 调用 API。

但我遇到了一些问题。

虽然我请求的响应是json响应,但当服务器发生错误时,服务器给我一个xml响应。

所以当服务器发生错误时我收到 UnsupportedMediaTypeException 错误。

因此我想制作一个业务逻辑,当发生 UnsupportedMediaTypeException 错误时可以给我发送电子邮件。

如何处理 UnsupportedMediaTypeException?

下面的代码是我的api调用代码。

@Override
public void run() {
    //여기서 API를 호출할거임
    DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); //UriBuilder를 생성하는 옵션을 설정하는 DefaultUriBuilderFactory 인스턴스 생성
    factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); //encoding 모드 설정

    
    HttpClient client = HttpClient.create()
            .responseTimeout(Duration.ofSeconds(60)); //http response timeout 설정을 60초로 설정함
    
    WebClient wc = WebClient.builder()
            .uriBuilderFactory(factory) //위에서 만든 uri 인코딩 설정으로 uribuilder 설정을 함
            .baseUrl(BASE_URL) //baseURI 설정하고
            .clientConnector(new ReactorClientHttpConnector(client)) //위에서 만든 타임아웃 설정을 적용시키고
            .build(); //빌드한다.
    
    result = new SweatherRootRes();
    
    Mono<SweatherRootRes> response = wc.get()
            .uri(uriBuilder -> uriBuilder.path("/getVilageFcst")
                    .queryParam("serviceKey", swr.getServiceKey())
                    .queryParam("numOfRows", swr.getNumOfRows())
                    .queryParam("pageNo", swr.getPageNo())
                    .queryParam("dataType", swr.getDataType())
                    .queryParam("base_date", swr.getBase_date())
                    .queryParam("base_time", swr.getBase_time())
                    .queryParam("nx", swr.getNx()) //지역정보
                    .queryParam("ny", swr.getNy()) //지역정보
                    .build()) //위 쿼리들로 uri 빌드를 하고
            .retrieve() //http 요청하고
            .onStatus(HttpStatus::is4xxClientError,
                    error -> Mono.error(new RuntimeException("API not found")))
            .onStatus(HttpStatus::is5xxServerError,
                    error -> Mono.error(new RuntimeException("Server is not responding")))
            .bodyToMono(SweatherRootRes.class);//Mono로 값을 받고
    
    //여기서 type mismatch 되는 부분을 찾아야함
    
    //비동기 방식으로 약간 콜백 메소드와 같은 역할을 하는것 같다.그래서  이부분은 api 연결이 성공했을때 들어오는 부분인것 같다.
    response.subscribe(res -> {
        result.setResponse(res.getResponse());
        if(result.getResponse().getBody()!= null) {
            getTemp(result.getResponse().getBody().getItems());
            logger.info(temp.toString());
            callBack.completed(temp, null);
            cdl.countDown();
        }else {
            logger.error("http reqeust has failed");
        }
    });
    
} 

我已经使用 .doOnError().onErrorReturn()

解决了这个问题

下面是我的代码

@Override
public void run() {
    //여기서 API를 호출할거임
    DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); //UriBuilder를 생성하는 옵션을 설정하는 DefaultUriBuilderFactory 인스턴스 생성
    factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); //encoding 모드 설정

    
    HttpClient client = HttpClient.create()
            .responseTimeout(Duration.ofSeconds(60)); //http response timeout 설정을 60초로 설정함
    
    WebClient wc = WebClient.builder()
            .uriBuilderFactory(factory) //위에서 만든 uri 인코딩 설정으로 uribuilder 설정을 함
            .baseUrl(BASE_URL) //baseURI 설정하고
            .clientConnector(new ReactorClientHttpConnector(client)) //위에서 만든 타임아웃 설정을 적용시키고
            .build(); //빌드한다.
    
    result = new SweatherRootRes();
    
    //여기서 type mismatch 되는 부분을 찾아야함
    Mono<SweatherRootRes> response = wc.get()
            .uri(uriBuilder -> uriBuilder.path("/getVilageFcst")
                    .queryParam("serviceKey", 123)
                    .queryParam("numOfRows", swr.getNumOfRows())
                    .queryParam("pageNo", swr.getPageNo())
                    .queryParam("dataType", swr.getDataType())
                    .queryParam("base_date", swr.getBase_date())
                    .queryParam("base_time", swr.getBase_time())
                    .queryParam("nx", swr.getNx()) //지역정보
                    .queryParam("ny", swr.getNy()) //지역정보
                    .build()) //위 쿼리들로 uri 빌드를 하고
            .retrieve() //http 요청하고
            .onStatus(HttpStatus::is4xxClientError,
                    error -> Mono.error(new RuntimeException("API not found")))
            .onStatus(HttpStatus::is5xxServerError,
                    error -> Mono.error(new RuntimeException("Server is not responding")))
            .bodyToMono(SweatherRootRes.class)//Mono로 값을 받고
            .doOnError(e -> logger.error("ERROR OCCUR!")) //에러 발생했을때 알려줌
            .onErrorReturn(new SweatherRootRes(true));//에러 발생하면 위 객체를 return 해줌
    
    //비동기 방식으로 약간 콜백 메소드와 같은 역할을 하는것 같다.그래서  이부분은 api 연결이 성공했을때 들어오는 부분인것 같다.
    response.subscribe(res -> {
        if(res.isError()) { //에러라면 진입
            callBack.failed(null, null); //callBack.failed() 호출
        }else {
            result.setResponse(res.getResponse()); //response 값으로 설정
            if(result.getResponse().getBody()!= null) {
                getTemp(result.getResponse().getBody().getItems()); //온도 구해서 세팅
                logger.info(temp.toString());
                callBack.completed(temp, null); //온도 값을 callBack에게 전달
                cdl.countDown(); //Thread 수를 센다.
            }else {
                logger.error("http reqeust has failed");
            }               
        }

    });
}