User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • Enamiĝu al vi
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • 666资源站
    • Java 全栈知识体系
    • 尼恩架构师学习
Help?

Please contact us on our email for need any support

Support
    首页   ›   Spring   ›   正文
Spring

Spring—WebClient使用

2023-01-31 18:11:14
330  0 0

参考目录

  • 初始化WebClient
  • 方式一:通过静态工厂方法创建响应式WebClient实例
  • 方式二:使用builder(构造者)创建响应式WebClient实例
  • 方式三:WebClient实例克隆
  • 请求提交
  • GET请求
  • POST请求
  • 错误处理
  • 响应解码
  • 请求和响应过滤

阅读完需:约 9 分钟

WebClient是Spring5引入的,基于响应式编程实现的HTTP调用客户端。Spring官方推荐使用WebClient替代RestTemplate完成HTTP调用。因为WebClient是基于Reactor实现的,所以既可以支持阻塞调用也可以支持非阻塞调用,在高并发的场景下资源利用率更高。这也是官方推荐使用的重要原因之一。

WebClient 内部委托给HTTP客户端库。默认情况下,WebClient 使用 Reactor Netty

如果在工程中想要是用WebClient,在Pom文件中加入如下依赖

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

SpringBoot版本:3.0.2

初始化WebClient

方式一:通过静态工厂方法创建响应式WebClient实例

创建最简单方法WebClient是通过静态工厂方法之一:

  • WebClient.create()
  • WebClient.create(String baseUrl)
//响应式客户端
WebClient client = null;
String baseUrl = "http://127.0.0.1:1112/greeting";
client = WebClient.create(baseUrl);
/**
 * 是通过 WebClient 组件构建请求
 */
String restUrl = baseUrl + "api/demo/hello/v1";
Mono<String> stringMono = client
        // 请求方法
        .method(HttpMethod.GET)
        // 请求url 和 参数
        //.uri(restUrl, params)
        .uri(restUrl)
        // 媒体的类型
        .accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(String.class);
@Test
public void testGet() throws IOException, InterruptedException {

	Mono<String> resp = WebClient.create()
			.method(HttpMethod.GET)
			.uri("http://127.0.0.1:1112/greeting")
			.cookie("token", "jwt_token")
			.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
			.retrieve().bodyToMono(String.class);

	// 订阅结果
	resp.subscribe(responseData ->
	{
		System.out.println("qqqqq"+responseData.toString());
	}, e ->
	{
		System.out.println("error:" + e.getMessage());
	});
	//主线程等待, 一切都是为了查看到异步结果
	Thread.sleep(2000);
}

方式二:使用builder(构造者)创建响应式WebClient实例

WebClient.builder().build();

WebClient client4 = WebClient.builder()
        .baseUrl("http://localhost:8080")
        .defaultCookie("cookieKey", "cookieValue")
        .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080"))
        .build();

使用build来构建主要是为了自定义参数

还可以使用WebClient.builder()其他选项:

  • uriBuilderFactory:自定义UriBuilderFactory用作基本URL(BaseUrl)。
  • defaultHeader:每个请求的标题。
  • defaultCookie:针对每个请求的Cookie。
  • defaultRequest:Consumer自定义每个请求。
  • filter:针对每个请求的客户端过滤器。
  • exchangeStrategies:HTTP消息读取器/写入器定制。
  • clientConnector:HTTP客户端库设置。

方式三:WebClient实例克隆

一旦建立,WebClient实例是不可变的。但是,您可以克隆它并构建修改后的副本,而不会影响原始实例,如以下示例所示:

WebClient client1 = WebClient.builder().build();
WebClient client2 = client1.mutate().build();

主要是mutate()函数,返回一个构建器以创建一个新的WebClient,其设置是从当前WebClient复制的。

总结一下上面三种方式都是和DefaultWebClientBuilder类有关,本质上都是相同的。

第一种

WebClient.create()

	/**
	 * Create a new {@code WebClient} with Reactor Netty by default.
	 * @see #create(String)
	 * @see #builder()
	 */
	static WebClient create() {
		return new DefaultWebClientBuilder().build();
	}

第二种

WebClient.builder().build();

	/**
	 * Obtain a {@code WebClient} builder.
	 */
	static WebClient.Builder builder() {
		return new DefaultWebClientBuilder();
	}

第三种

client1.mutate().build();

	@Override
	public Builder mutate() {
		return new DefaultWebClientBuilder(this.builder);
	}

可以通过builder()方式来构建自定义参数,修改默认的超时时间

//通过HttpClient设置超时时间
HttpClient httpClient2 = HttpClient.create()
		//设置连接超时时间
		.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
		//设置响应超时时间
		.responseTimeout(Duration.ofMillis(5000))
		//分别设置读写超时时间
		.doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))     .addHandlerLast(new WriteTimeoutHandler(5000,TimeUnit.MILLISECONDS)));

WebClient client5 = WebClient.builder()
		.clientConnector(new ReactorClientHttpConnector(httpClient2))
		.build();

请求提交

GET请求

Mono<String> resp = WebClient.create()
		.method(HttpMethod.GET)
		.uri("http://127.0.0.1:1112/greeting")
		.cookie("token", "jwt_token")
		.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
		//获取结果
		.retrieve()
		//将结果转化为指定类型
		.bodyToMono(String.class);

// 通过非阻塞的方式获取响应结果 订阅结果 
resp.subscribe(responseData ->
{
	System.out.println("qqqqq"+responseData.toString());
}, e ->
{
	System.out.println("error:" + e.getMessage());
});
//主线程等待, 一切都是为了查看到异步结果
Thread.sleep(2000);

//通过阻塞的方式获取响应结果
String block = resp.block();

POST请求

提交Json Body

Mono<Person> personMono = ... ;

Mono<Void> result = client.post()
        .uri("/persons/{id}", id)
        .contentType(MediaType.APPLICATION_JSON)
        .body(personMono, Person.class)
        .retrieve()
        .bodyToMono(Void.class);

例子

@Test
public void testJSONParam() throws InterruptedException {
	LoginInfoDTO dto=new LoginInfoDTO("lisi","123456");
	Mono<LoginInfoDTO> personMono =Mono.just(dto);

	Mono<String> resp = WebClient.create().post()
			.uri("http://127.0.0.1:1112/greeting")
			.contentType(MediaType.APPLICATION_JSON)
			//.contentType(MediaType.APPLICATION_FORM_URLENCODED)
			.body(personMono,LoginInfoDTO.class)
			.retrieve()
			.bodyToMono(String.class);

	// 订阅结果
	resp.subscribe(responseData ->
	{
		System.out.println(responseData.toString());
	}, e ->
	{
		System.out.println("error:" + e.getMessage());
	});
	//主线程等待, 一切都是为了查看到异步结果
	Thread.sleep(2000);
}

提交表单

MultiValueMap<String, String> formData = ... ;

Mono<Void> result = client.post()
        .uri("/path", id)
        .bodyValue(formData)
        .retrieve()
        .bodyToMono(Void.class);

或者

import static org.springframework.web.reactive.function.BodyInserters.*;

Mono<Void> result = client.post()
        .uri("/path", id)
        .body(BodyInserters.fromFormData("k1", "v1").with("k2", "v2"))
        .retrieve()
        .bodyToMono(Void.class);

例子

MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
		formData.add("name1","value1");
		formData.add("name2","value2");
		Mono<String> resp2 = WebClient.create().post()
				.uri("http://localhost:8080/submit")
				.contentType(MediaType.APPLICATION_FORM_URLENCODED)
				.body(BodyInserters.fromFormData(formData))
				.retrieve()
				.bodyToMono(String.class);
		logger.info("result:{}",resp.block());

上传文件

@Test
public void testUploadFile()
{
	HttpHeaders headers = new HttpHeaders();
	headers.setContentType(MediaType.IMAGE_PNG);
	HttpEntity<ClassPathResource> entity =
			new HttpEntity<>(new ClassPathResource("logback-spring.xml"), headers);
	MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
	parts.add("file", entity);
	Mono<String> resp = WebClient.create().post()
			.uri("http://127.0.0.1:1112/greeting")
			.contentType(MediaType.MULTIPART_FORM_DATA)
			.body(BodyInserters.fromMultipartData(parts))
			.retrieve().bodyToMono(String.class);
	System.out.println("result:"+resp.block());
}

错误处理

  • 可以使用onStatus根据status code进行异常适配
  • 可以使用doOnError异常适配
  • 可以使用onErrorReturn返回默认值
@Test
public void testFormParam4xx()
{
	WebClient webClient = WebClient.builder()
			.baseUrl("https://api.github.com")
			.defaultHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.github.v3+json")
			.defaultHeader(HttpHeaders.USER_AGENT, "Spring 5 WebClient")
			.build();
	WebClient.ResponseSpec responseSpec = webClient.method(HttpMethod.GET)
			.uri("/user/repos?sort={sortField}&direction={sortDirection}", "updated", "desc")
			.retrieve();
	Mono<String> mono = responseSpec
			.onStatus(e -> e.is4xxClientError(), resp ->
			{
				log.info("error:{},msg:{}", resp.statusCode().value(), resp.statusCode().getReasonPhrase());
				return Mono.error(new RuntimeException(resp.statusCode().value() + " : " + resp.statusCode().getReasonPhrase()));
			})
			.bodyToMono(String.class)
			.doOnError(WebClientResponseException.class, err ->
			{
				log.info("ERROR status:{},msg:{}", err.getRawStatusCode(), err.getResponseBodyAsString());
				throw new RuntimeException(err.getMessage());
			})
			.onErrorReturn("fallback");
	String result = mono.block();
	System.out.print(result);
}

响应解码

有两种对响应的处理方法:

  • retrieveretrieve方法是直接获取响应body。
  • exchange但是,如果需要响应的头信息、Cookie等,可以使用exchange方法,exchange方法可以访问整个ClientResponse。

异步转同步:

由于响应的得到是异步的,所以都可以调用 block 方法来阻塞当前程序,等待获得响应的结果。

retrieve

该retrieve()方法是获取响应主体并对其进行解码的最简单方法。

Mono<Person> result = client.get()
		.uri("/persons/{id}", id)
		.accept(MediaType.APPLICATION_JSON)
		.retrieve()
		.onStatus(HttpStatus::is4xxClientError, response -> ...)
		.onStatus(HttpStatus::is5xxServerError, response -> ...)
		.bodyToMono(Person.class);

默认情况下,4XX或5xx状态代码的应答导致 WebClientResponseException或它的HTTP状态的具体子类之一,比如 WebClientResponseException.BadRequest,WebClientResponseException.NotFound和其他人。还可以使用该onStatus方法来自定义所产生的异常

exchange()

该exchange()方法比该方法提供更多的控制retrieve。以下示例等效于retrieve()但也提供对的访问ClientResponse:

Mono<ResponseEntity<Person>> result = client.get()
        .uri("/persons/{id}", id)
        .accept(MediaType.APPLICATION_JSON)
        .exchange()
        .flatMap(response -> response.toEntity(Person.class));

请注意与不同retrieve(),对于exchange(),没有4xx和5xx响应的自动错误信号。您必须检查状态码并决定如何进行。

与相比retrieve(),当使用时exchange(),应用程序有责任使用任何响应内容,而不管情况如何(成功,错误,意外数据等),否则会导致内存泄漏.

例子

/**
 * 测试用例: Exchange
 */
@Test
public void testExchange()
{
	String baseUrl = "http://localhost:8081";
	WebClient webClient = WebClient.create(baseUrl);

	MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
	map.add("username", "u123");
	map.add("password", "p123");

	Mono<ClientResponse> loginMono = webClient.post().uri("login").syncBody(map).exchange();
	ClientResponse response = loginMono.block();
	if (response.statusCode() == HttpStatus.OK) {
		Mono<RestOut> resultMono = response.bodyToMono(RestOut.class);
		resultMono.subscribe(result -> {
			if (result.isSuccess()) {
				ResponseCookie sidCookie = response.cookies().getFirst("sid");
				Mono<LoginInfoDTO> dtoMono = webClient.get().uri("users").cookie(sidCookie.getName(), sidCookie.getValue()).retrieve().bodyToMono(LoginInfoDTO.class);
				dtoMono.subscribe(System.out::println);
			}
		});
	}
}

response body 转换响应流

将response body 转换为对象/集合

  • bodyToMono如果返回结果是一个Object,WebClient将接收到响应后把JSON字符串转换为对应的对象,并通过Mono流弹出。
  • bodyToFlux如果响应的结果是一个集合,则不能继续使用bodyToMono(),应该改用bodyToFlux(),然后依次处理每一个元素,并通过Flux流弹出。

请求和响应过滤

WebClient也提供了Filter,对应于org.springframework.web.reactive.function.client.ExchangeFilterFunction接口,其接口方法定义如下。

Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next)

在进行拦截时可以拦截request,也可以拦截response。

WebClient webClient = WebClient.builder()
		.baseUrl("http://localhost:8081")
		.defaultHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.github.v3+json")
		.filter(ExchangeFilterFunctions
				.basicAuthentication(username, token))
		.build();

例子

@Test
void filter() {
	Map<String, Object> uriVariables = new HashMap<>();
	uriVariables.put("p1", "var1");
	uriVariables.put("p2", 1);
	WebClient webClient = WebClient.builder().baseUrl("http://www.xxxxx.com")
			.filter(logResposneStatus())
			.defaultHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.github.v3+json")
			.build();
	Mono<String> resp1 = webClient
			.method(HttpMethod.GET)
			.uri("/")
			.cookie("token","xxxx")
			.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
			.retrieve().bodyToMono(String.class);
	String re=  resp1.block();
	System.out.print("result:" +re);

}

private ExchangeFilterFunction logResposneStatus() {
	return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
		log.info("Response Status {}", clientResponse.statusCode());
		return Mono.just(clientResponse);
	});
}

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
一个人若有一百只羊,一只走迷了路,你们的意思如何?他岂不撇下这九十九只,往山里去找那只迷路的羊吗?
513文章 67评论 170点赞 294554浏览

默认版本~SpringBoot2.0~2.3
  • Redis—注解接口限流
  • SpringBoot—数据库读写分离
  • Netty—初探与核心
  • Netty—NIO基础
  • Spring—WebClient使用
  • SpringCloud—LoadBalanced负载均衡
  • Spring—ApplicationEvent事件驱动机制
随便看看
ActiveMQ (4) Ajax (13) Docker (7) ElasticSearch (13) Enamiĝu al vi (1) Eureka (2) Feign (6) Freemarker (5) Gateway (6) Git (5) Hystrix (7) Java (72) Java Notes (111) JavaScript (1) jQuery (2) Kotlin Notes (47) Maven (2) More (2) MyBatis (42) MySQL (5) Netty (2) NOSQL (1) OAuth2 (11) PostgreSQL (4) RabbitMQ (6) Redis (18) Ribbon (6) Servlet (3) Spring (70) SpringBoot (85) SpringCloud (14) SpringJPA (4) SpringMVC (46) Spring Notes (43) SpringSecurity (49) SQL (15) SQL Notes (9) SQL Server (2) Thymeleaf (4) Vue (9) Web (12) Web Notes (18) WebSocket (9) XML (1) Zuul (3)
随便看看
  • 2023年2月 (4)
  • 2023年1月 (3)
  • 2022年12月 (1)
  • 2022年11月 (3)
  • 2022年10月 (5)
  • 2022年9月 (8)
  • 2022年8月 (1)
  • 2022年7月 (2)
  • 2022年6月 (4)
  • 2022年5月 (5)
  • 2022年4月 (3)
  • 2022年3月 (7)
  • 2022年2月 (4)
  • 2022年1月 (15)
  • 2021年12月 (16)
  • 2021年11月 (3)
  • 2021年10月 (3)
  • 2021年9月 (3)
  • 2021年8月 (2)
  • 2021年7月 (4)
  • 2021年6月 (16)
  • 2021年5月 (3)
  • 2021年4月 (2)
  • 2021年3月 (13)
  • 2021年2月 (2)
  • 2021年1月 (33)
  • 2020年12月 (13)
  • 2020年11月 (6)
  • 2020年10月 (17)
  • 2020年9月 (26)
  • 2020年8月 (46)
  • 2020年7月 (28)
  • 2020年6月 (4)
  • 2020年5月 (16)
  • 2020年4月 (88)
  • 2020年3月 (104)
随机文章
Kotlin-内置类型—集合框架(五)
2年前
SpringBoot—Jpa整合多数据源
3年前
SpringSecurity—OAuth 2(二)授权码模式
3年前
SpringBoot—Spring Security 中使用 JWT ( 无状态登录 )
3年前
SpringSecurity—如何将用户数据存入数据库(自带设计)
3年前
Java—字符串操作(String)
3年前
ENMAL摘要

1、Kotlin:

https://www.liuwj.me/

 

2、webflux:

https://www.cnblogs.com/lixinjie/p/a-brother-of-spring-mvc-is-spring-webflux.html

 

3、Java中的Unsafe

 

4、https://my.oschina.net/quanke/blog/1631990

 

5、https://blog.csdn.net/u013064109/article/details/78786646?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522161214257916780264022540%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=161214257916780264022540&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-11-78786646.first_rank_v2_pc_rank_v29&utm_term=kotlin

 

6、待学习除Spring之外的Web框架 — Cloudopt Next、Javalin、jfinal

https://jfinal.com/doc

 

7、kotlin设计模式——https://github.com/AboutKotlin/Design-Patterns-In-Kotlin

 

8、kotlin–ktorm+SpringBoot——https://gitee.com/tianchaohongyu/Spring-Boot-Ktor-Starter

 

9、新技术 — CQRS、jasync-sql、play!framework、akka、asyncdb

 

10、Kotlin Tips

https://gitee.com/lesliekoma/kotlin_tips?_from=gitee_search#tip5–%E6%87%92%E5%88%9D%E5%A7%8B%E5%8C%96by-lazy-%E5%92%8C-%E5%BB%B6%E8%BF%9F%E5%88%9D%E5%A7%8B%E5%8C%96lateinit

 

11、mall项目电商系统

https://github.com/macrozheng/mall

 

12、POI大量读写

https://www.cnblogs.com/swordfall/p/8298386.html

 

13、Gitee

权限RBAC:

https://gitee.com/log4j/pig

 

14、freecodecamp、pf4j

 

15、https://javadoop.com/

 

16、https://www.cnblogs.com/skywang12345/

 

17、Flyway

 

18、https://github.com/kotlin-orm/ktorm/pull/296

 

kt实体类自动生成表

 

https://github.com/tursom/TursomServer/tree/master/ts-database/src/main/kotlin/cn/tursom/database

 

19、蓝狐、支付沙盒、虚拟币

 

20、r2dbc spring强推,vertx这边是quarkus强推 redhat认证

 

21、Keycloak为Web应用和Restful服务提供了一站式的单点登录解决方案。

 

22、RSQL 的形式为 Restful API 带来了 SQL 声明性的便利

https://github.com/vineey/archelix-rsql

https://github.com/ymind/rsql-ktorm

 

23、Kotlin依赖注入

https://github.com/InsertKoinIO/koin

 

24、Kotlin– Alpas

https://github.com/alpas/alpas

一个基于 Kotlin 的 Web 框架,可让您简单快速地创建 Web 应用程序和 API。

 

25、外网学习网站,文章

https://medium.com/nerd-for-tech

 

26、Compose Multiplatform 进入 Alpha 版,统一桌面、Web 和 Android UI

https://blog.jetbrains.com/kotlin/2021/08/compose-multiplatform-goes- alpha/

 

27、Sureness

面向REST API的高性能认证鉴权框架,致力于管理保护API安全

https://gitee.com/dromara/sureness

与Javalin结合

https://javalin.io/2021/04/16/javalin-sureness-example.html

 

28、Kotlin官网合集库

https://kotlinlang.org/lp/server-side/

https://kotlinlang.org/lp/server-side/

https://kotlinlang.org/lp/server-side/

 

29、CLI知识体系

https://juejin.cn/post/6966119324478079007

 

30、面向 Web、移动和 Flutter 开发人员的安全开源后端服务器

https://appwrite.io/

 

31、Java锁

https://blog.csdn.net/hancoder/article/details/120421993

 

32、java—简单的鉴权认证

介绍 – Sa-Token (dev33.cn)

 

33、Effective Kotlin 中文翻译

GitHub – MaxzMeng/Effective-Kotlin-zh-CN: Effective Kotlin 中文翻译

 

34、Nutz—国产Web开源框架

http://www.nutzam.com/core/nutz_preface.html

 

35、Quarkus 夸克—国外开源框架

https://quarkus.io/

 

36、目前6个框架

  1. Spring Reactive → 背靠 Pivotal → 归属 VMware → 归属戴尔
  2. Quarkus 和 Vert.x → 背靠 Eclipse 基金会 → 主要由 Red Hat 支持
  3. Helidon → 背靠 Oracle
  4. Micronaut → 背靠 Object Computing(Grails、OpenDDS)
  5. Lagom → 背靠 Lightbend(Akka)
  6. Ktor → 背靠 JetBrains

 

37、XXL-JOB—–分布式任务调度平台

https://www.xuxueli.com/xxl-job/#%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6%E5%B9%B3%E5%8F%B0XXL-JOB%E3%80%8B

 

38、领域设计驱动模版

https://myddd.org

 

39、BFF— Backend For Frontend

 

40、面试突击小册

https://snailclimb.gitee.io/javaguide-interview/#/

https://javaguide.cn/

 

41、JeecgBoot 是一款基于代码生成器的低代码开发平台

http://doc.jeecg.com/2043868

 

42、

IdentityServer4 是用于 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 框架。

https://identityserver4docs.readthedocs.io/zh_CN/latest/index.html

 

43、cn.novelweb 工具类的个人博客

https://blog.novelweb.cn

 

44、分布式链路追踪SkyWalking

 

45、刷题模版

https://blog.csdn.net/fuxuemingzhu/article/details/101900729

 

46、TS中文文档

https://ts.xcatliu.com/

 

47、Rust 中文文档

https://kaisery.github.io/trpl-zh-cn/ch00-00-introduction.html

 

48、Bean Searcher 只读 ORM

https://searcher.ejlchina.com/guide/latest/start.html

 

49、K8S的学习手册

https://kuboard.cn/learning/k8s-basics/kubernetes-basics.html#%E5%AD%A6%E4%B9%A0%E7%9B%AE%E6%A0%87

 

50、fluent-mybatis, mybatis语法增强框架(关键自动生成代码JavaPoet)

https://gitee.com/fluent-mybatis/fluent-mybatis?_from=gitee_search

 

51、程序猿博客

https://qicoder.com/categories/

https://blog.hhui.top/hexblog/

https://fangshixiang.blog.csdn.net/category_7941357_2.html

https://www.zhihu.com/people/zhuo-zi-yang-93

 

52、itxiaoshen大佬的分享

https://www.cnblogs.com/itxiaoshen/

 

53、MySQL实战学习

https://funnylog.gitee.io/mysql45/

 

54、八股文

https://www.javalearn.cn/#/

 

55、两个宣传很牛的IO框架

https://gitee.com/smartboot/smart-socket

https://www.tiocloud.com/doc/taixin/?pageNumber=1

Copyright © 2023 网站备案号: 浙ICP备20017730号
主页
页面
  • 归档
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
If you get tired, learn to rest, not to quit.
513 文章 67 评论 294554 浏览
测试
测试
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付