클로드의 예시
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import com.example.model.Data;
public class WebClientExample {
public static void main(String[] args) {
WebClient webClient = WebClient.create("http://example.com");
Data data = new Data("Sample Data");
webClient.post()
.uri("/api/data")
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(data))
.retrieve()
.bodyToMono(String.class)
.map(ResponseEntity::ok)
.onErrorResume(WebClientResponseException.class,
ex -> ex.getRawStatusCode() == 404 ? Mono.just(ResponseEntity.notFound().build()) : Mono.error(ex))
.subscribe(response -> handleResponse(response));
}
private static void handleResponse(Object response) {
System.out.println("Response received: " + response);
}
}
이를 응용 하여
@Configuration 에 빈으로 등록
private HttpClient httpClientConfig(int sec){
int timeOut = sec * 1000;
return HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeOut)
.responseTimeout(Duration.ofMillis(timeOut))
.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler(timeOut, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(timeOut, TimeUnit.MILLISECONDS)));
}
private ExchangeStrategies exchangeStrategiesConfig(){
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024*1024*50))
.build();
exchangeStrategies
.messageWriters().stream()
.filter(LoggingCodecSupport.class::isInstance)
.forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));
return exchangeStrategies;
}
private ExchangeFilterFunction logRequest(){
return ExchangeFilterFunction.ofRequestProcessor(
clientRequest -> {
log.debug("Request: {} {}", clientRequest.method(), clientRequest.url());
clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value)));
return Mono.just(clientRequest);
}
);
}
private ExchangeFilterFunction logResponse(){
return ExchangeFilterFunction.ofResponseProcessor(
clientResponse -> {
log.debug("Response: {}", clientResponse.statusCode());
clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.debug("{} : {}", name, value)));
return Mono.just(clientResponse);
}
);
}
@Bean(name = "testWebClient")
public WebClient testWebClient() {
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClientConfig(15)))
.baseUrl("http://localhost:8080")
.exchangeStrategies(exchangeStrategiesConfig())
.filter(logRequest())
.filter(logResponse())
.build();
}
어쩌다보니 필터 로깅 하는 거까지 하게 됬습니다.
@Service
@RequiredArgsConstructor
@Slf4j
public class Client {
private final WebClient testWebClient;
public Mono<String> testWebClient(final MultiValueMap<String, HttpEntity<?>> formData) {
return testWebClient.post()
.uri(uriBuilder -> uriBuilder
.path("/test")
.build())
.contentType(MediaType.MULTIPART_FORM_DATA)
.bodyValue(formData)
.retrieve()
.bodyToMono(String.class)
.doOnNext(responseBody -> log.debug("Body: {}", responseBody.trim()));
}
}
빈으로 등록한 웹클라이언트를 가져와서 서비스코딩 해주고
MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
formData.add("subject", "테스트");
client.testWebClient(formData, fsr.contentLength()).subscribe(
responseString -> { //이하생략