问题描述
背景:我有传统的Spring MVC应用程序(Spring Boot),该应用程序利用Spring Cloud OpenFeign(REST服务使用)和Apache CXF(SOAP服务使用)。我试图查看是否可以将这两个HTTP客户端整合到Spring的WebClient
中。
我试图找出是否有更好的方法来引用放置在RequestContextHolder
中的属性,然后在ExchangeFilterFunction
中使用/使用它们(代替各种Feign / CXF请求拦截器)。 / p>
例如,以下工作原理:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
import java.util.HashMap;
import java.util.Map;
import static java.util.Objects.requireNonNull;
@SpringBootApplication
public class DemoApplication {
private static Log logger = LogFactory.getLog(DemoApplication.class);
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class,args);
}
@Bean
RouterFunction<ServerResponse> router(WebClient.Builder webClientBuilder) {
WebClient webClient = webClientBuilder.baseUrl("https://jsonplaceholder.typicode.com").filter((req,next) -> {
Object foo = requireNonNull(RequestContextHolder.getRequestAttributes()).getAttribute("foo",WebRequest.ScopE_REQUEST);
logger.info("Foo=" + foo);
return next.exchange(ClientRequest.from(req).header("foo",foo.toString()).build());
}).build();
return RouterFunctions.route()
.before((request) -> {
logger.info("Setting foo from " + Thread.currentThread().getName());
RequestContextHolder.getRequestAttributes().setAttribute("foo","bar",WebRequest.ScopE_REQUEST);
return ServerRequest.from(request).build();
})
.GET("/test",(request) -> {
ClientResponse response = webClient.get().uri("/todos/1").exchange().block();
Map<String,Object> body = new HashMap<>();
body.put("attributes",RequestContextHolder.getRequestAttributes().getAttributeNames(WebRequest.ScopE_REQUEST));
body.put("todo",response.bodyToMono(new ParameterizedTypeReference<Map<String,Object>>() {}).block());
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(body);
})
.build();
}
}
请注意,上面仍然是一个servlet /阻塞应用程序示例。唯一的反应部分是WebClient
和ExchangeFilterFunction
。 RestTemplate
处于维护模式,建议根据the javadoc使用WebClient
2020-08-24 21:26:22.829 INFO 15212 --- [nio-8080-exec-1] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-1
2020-08-24 21:26:22.829 INFO 15212 --- [nio-8080-exec-1] com.example.demo.DemoApplication : Foo=bar
2020-08-24 21:26:22.915 INFO 15212 --- [nio-8080-exec-2] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-2
2020-08-24 21:26:22.916 INFO 15212 --- [nio-8080-exec-2] com.example.demo.DemoApplication : Foo=bar
2020-08-24 21:26:23.011 INFO 15212 --- [nio-8080-exec-3] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-3
2020-08-24 21:26:23.011 INFO 15212 --- [nio-8080-exec-3] com.example.demo.DemoApplication : Foo=bar
2020-08-24 21:26:23.118 INFO 15212 --- [nio-8080-exec-4] com.example.demo.DemoApplication : Setting foo from http-nio-8080-exec-4
2020-08-24 21:26:23.119 INFO 15212 --- [nio-8080-exec-4] com.example.demo.DemoApplication : Foo=bar
但是,由于Reactor提供了Context,而且这样做this Reactor FAQ明确地指出了以下内容(强调我的意思),因此这样做是错误的:
现在,我们已经确定MDC “正常工作”并不是在声明性API中做出的最佳假设
感谢任何帮助/指导。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)