Spring Cloud gateway通过WebClient异步调用微服务

1、在gateway中创建注入配置类,添加@LoadBalanced注解后才能通过服务名进行远程调用,否则只通过IP调用

@Configuration
public class WebClientConfig {
    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

2、在gateway中的调用方注入webclient,并且创建线程池

@Autowired
private WebClient.Builder webClientBuilder;
//线程池
//ExecutorService executorService = Executors.newFixedThreadPool(2);
ExecutorService executorService = Executors.newCachedThreadPool();

3、通过线程异步调用服务并获取结果,服务名以lb://方式请求,future.get()要设置超时时间,否则有可能一直被阻塞

List<String> list = new ArrayList<>();
try {
	Long id = StpUtil.getLoginIdAsLong();
	//String url = "http://127.0.0.1:802/user/" + id;
	//WebClient webClient = WebClient.create(url); //通过这种方法创建,mono处的uri节点不需要
	String url = "lb://" + ServiceNameConstants.USER_SERVICE + "/user/" + id;
	WebClient webClient = webClientBuilder.build();
	Mono<ResultData<User>> mono = webClient.get().uri(url).header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken()).retrieve().bodyToMono(new ParameterizedTypeReference<ResultData<User>>() {
	});
	Future future = executorService.submit((Callable<ResultData<User>>) () -> mono.block());
	List<Menu> menus = ((ResultData<User>) future.get(5, TimeUnit.SECONDS)).getData().getMenus();
	if (menus != null) {
		menus.stream().forEach(r -> list.add(r.getCode()));
	}
	//超级管理员权限
	if (StpUtil.hasRole("administrator")) {
		list.add("*");
	}
} catch (InterruptedException e) {
	throw new RuntimeException(e);
} catch (ExecutionException e) {
	throw new RuntimeException(e);
}
return list;

4、API详解

build().get() get请求 build().method(HttpMethod.GET)
build().post() post请求 build().method(HttpMethod.POST)
build().put() put请求 build().method(HttpMethod.PUT)
build().delete() delete请求 build().method(HttpMethod.DELETE)

响应类型

类型 描述 方法
Mono 包含0个或1个元素 bodyToMono(String.class)
Flux 包含1个或多个元素 .bodyToFlux(String.class)

5、忽略SSL证书及Bearer示例

<dependency>
   <groupId>io.projectreactor.netty</groupId>
   <artifactId>reactor-netty-http</artifactId>
</dependency>
import io.netty.handler.ssl.*
import reactor.netty.http.client.HttpClient;

String baseUrl = "https://filez.bba.com:5555/v2";
String appKey = "xxxxxxdfd";
String appSecret = "vvvvvvvxxs";
// Authorization Bearer 64位编码
//            String encodeAuthStr = Base64.getEncoder().encodeToString((appKey+":"+appSecret).getBytes());

// 忽略证书
SslContext context = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(context));

var tokenClient = WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient))
    // Authorization Bearer 64位编码
    .filter(ExchangeFilterFunctions.basicAuthentication(appKey, appSecret))
    .baseUrl(baseUrl).build();

MultiValueMap<String, String> tokenFormData = new LinkedMultiValueMap<>();
tokenFormData.add("grant_type", "client_with_su");
tokenFormData.add("scope", "all");
tokenFormData.add("slug", "admin");

JSONObject tokenJson = tokenClient.post().uri("/oauth/token")
    .contentType(MediaType.APPLICATION_FORM_URLENCODED).bodyValue(tokenFormData)
    .retrieve().bodyToMono(JSONObject.class).block();

var client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient))
    .defaultHeader("Authorization", "Bearer " + tokenJson.getString("access_token"))
    .baseUrl(baseUrl).build();

// /api/user/slug?user_slug=13800013800
JSONObject queryJson = client.get().uri(uriBuilder -> uriBuilder.path("/api/user/slug").queryParam("user_slug", mobile).build())
    .retrieve().bodyToMono(JSONObject.class).block();
log.info("查询用户结果:" + queryJson);

if (queryJson.get("uid") != null) {
    String uid = queryJson.getString("uid");
    if ("0".equals(status)) {
        JSONObject userJson = client.delete().uri("/api/user/freeze?uids=" + uid)
            .retrieve().bodyToMono(JSONObject.class).block();
        if ("0".equals(userJson.getString("errcode"))) {
            returnMap.put("flag", true);
            returnMap.put("result", "HR数据同步到File冰结成功");
        } else {
            returnMap.put("result", userJson.getString("errmsg"));
        }
    } else {
        MultiValueMap<String, String> jdFormData = new LinkedMultiValueMap<>();
        jdFormData.add("uids", uid);

        JSONObject userJson = client.post().uri("/api/user/active").contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .bodyValue(jdFormData).retrieve().bodyToMono(JSONObject.class).block();
        if ("0".equals(userJson.getString("errcode"))) {
            returnMap.put("flag", true);
            returnMap.put("result", "HR数据同步到File解结成功");
        } else {
            returnMap.put("result", userJson.getString("errmsg"));
        }
    }
} else {
    MultiValueMap<String, String> userFormData = new LinkedMultiValueMap<>();
    userFormData.add("email", email);
    userFormData.add("mobile", mobile);
    userFormData.add("password", "bxlfilez.2024");
    userFormData.add("quota", "");
    userFormData.add("status", status);
    userFormData.add("user_name", lastName);
    userFormData.add("user_slug", mobile);

    JSONObject userJson = client.post().uri("/api/user").contentType(MediaType.APPLICATION_FORM_URLENCODED)
        .bodyValue(userFormData).retrieve().bodyToMono(JSONObject.class).block();
    log.info("创建用户结果:" + userJson);
    if ("0".equals(userJson.getString("errcode"))) {
        returnMap.put("flag", true);
        returnMap.put("result", "HR数据同步到File成功");
    } else {
        returnMap.put("result", userJson.getString("errmsg"));
    }
}

6、天眼查示例

// 股权穿透455
String url1 = "http://open.api.tianyancha.com/services/v3/open/investtree?flag=4&dir=up&keyword=";
// 董监高信息855
String url2 = "http://open.api.tianyancha.com/services/open/stock/seniorExecutive/2.0?pageSize=20&keyword=";

var client = WebClient.builder()
    //修改maxInMemorySize的缓冲值,默认是256KB,修改为10MB
    .codecs(item -> item.defaultCodecs().maxInMemorySize(10 * 1024 * 1024))
    .defaultHeader("Authorization", "f56896a2-41d3-4b1f-92a9-xxxxxxx").build().get();

 String resultString = client.uri(url1 + li.getName()).retrieve().bodyToMono(String.class).block();
            resultString = resultString.replace("\"[", "[").replace("]\"", "]").replace("\\\"", "\"");
            JSONObject jsonObject = JSON.parseObject(resultString);

7、查询IP示例

JSONObject result = WebClient.builder()
    .codecs(item -> item.defaultCodecs().maxInMemorySize(10 * 1024 * 1024))
    .baseUrl("https://api.vvhan.com").build()
    .get().uri(uriBuilder -> uriBuilder.path("/api/ipInfo").queryParam("ip", ip).build())
    .retrieve().bodyToMono(JSONObject.class).block();

8、RestClient查询天气示例:

RestClient client = RestClient.create(URI.create("https://api.vvhan.com"));
JSONObject result = client.get()
    .uri("/api/weather?city={0}", city)
    .retrieve()
    .body(JSONObject.class);

 

posted @ 2023-06-18 21:12  滔天蟹  阅读(3230)  评论(0)    收藏  举报