spring boot webflux client实战

引言

    在spring 5.0发布的同时发布了webflux功能类似spring mvc。底层实现以及关注点不同。今天我们主要讲解spring webflux中的一个组件webclient。webclient是spring webflux的一个小组件。对于Java的http通讯来说,webclient是非常简单易用的。比起apache的httpclient组件更方便的集成到项目中

一.创建一个spring boot 项目包含webflux组件

1.1创建Spring  boot项目并加入webflux组件依赖

选择依赖

1.2项目结构图展示

项目结构图

二.创建一个间的web服务

2.1创建spring webflux基于Java的配置

WebConfig:
package net.xqlee.project.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;

/**
 * 基于Java代码配置启用Spring WebFlux
 * 
 * @author xqlee
 *
 */
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

	String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

	/****
	 * 配置常用的转换器和格式化配置(与Spring MVC 5配置方式一样)
	 */
	@Override
	public void addFormatters(FormatterRegistry registry) {
		// 添加日期格式化转换
		DateFormatter dateFormatter = new DateFormatter(DATE_FORMAT);
		registry.addFormatter(dateFormatter);

	}

	/****
	 * 资源路径映射配置(与Spring MVC 5一样,只是引入的类不同)
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/resources/**").addResourceLocations("/public", "classpath:/static/");

	}
}
通过spring 官方文档查询可以知道,spring webflux的配置使用和Spring mvc的配置使用方法基本相同。上面只是个简单的配置。

2.2创建一个controller用来做webclient的测试请求服务

TestController:
package net.xqlee.project.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import net.xqlee.project.pojo.Person;

@Controller
public class TestController {

	private static final Logger log = LoggerFactory.getLogger(TestController.class);

	@PostMapping("persion/getPersion/{id}.json")
	@ResponseBody
	public Person getPersion(@PathVariable("id") String id) {
		log.info("ID:" + id);
		return new Person("1", "leftso", 1, "重庆.大竹林");
	}
}
上面包含一个简单对象Persion:
package net.xqlee.project.pojo;

public class Person {
	public Person() {
	}

	public Person(String id, String name, int age, String address) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.address = address;
	}

	String id;
	String name;
	int age;
	String address;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

}
好了一个spring boot的webflux服务已经创建完毕。接下来将进行webclient的调用方法。

三.创建webclient

3.1创建一个测试的类
package net.xqlee.project;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;

import net.xqlee.project.pojo.Person;
import reactor.core.publisher.Mono;

/**
 * reactive webClient
 * 
 * @author xqlee
 *
 */
public class TestClient {

	private static final Logger log = LoggerFactory.getLogger(TestClient.class);

	public static void main(String[] args) {
		WebClient client = WebClient.create("http://localhost:8080/");

		Mono<Person> result = client.post()// 请求方法,get,post...
				.uri("persion/getPersion/{id}.json", "123")// 请求相对地址以及参数
				.accept(MediaType.APPLICATION_JSON).retrieve()// 请求类型
				.bodyToMono(Person.class);// 返回类型
		Person person = result.block();
		log.info(JSONObject.wrap(person).toString());
	}

}
上面已经创建了一个webclient的请求。请求的地址是刚才我们创建的一个简单的测试服务。
首先运行spring boot项目启动测试服务:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::             (v2.0.0.M6)

2017-11-19 13:53:09.290  INFO 6976 --- [           main] n.x.p.DemoSpringbootWebflux2Application  : Starting DemoSpringbootWebflux2Application on DESKTOP-2RG0A6O with PID 6976 (D:\workplace\eclipse_mvn\demo-springboot-webflux-2\target\classes started by xqlee in D:\workplace\eclipse_mvn\demo-springboot-webflux-2)
2017-11-19 13:53:09.295  INFO 6976 --- [           main] n.x.p.DemoSpringbootWebflux2Application  : No active profile set, falling back to default profiles: default
2017-11-19 13:53:09.377  INFO 6976 --- [           main] .r.c.ReactiveWebServerApplicationContext : Refreshing org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext@59402b8f: startup date [Sun Nov 19 13:53:09 CST 2017]; root of context hierarchy
2017-11-19 13:53:10.480  INFO 6976 --- [           main] s.w.r.r.m.a.RequestMappingHandlerMapping : Mapped "{[/persion/getPersion/{id}.json],methods=[POST]}" onto public net.xqlee.project.pojo.Person net.xqlee.project.controller.TestController.getPersion(java.lang.String)
2017-11-19 13:53:10.542  INFO 6976 --- [           main] o.s.w.r.handler.SimpleUrlHandlerMapping  : Mapped URL path [/resources/**] onto handler of type [class org.springframework.web.reactive.resource.ResourceWebHandler]
2017-11-19 13:53:10.611  INFO 6976 --- [           main] o.s.w.r.r.m.a.ControllerMethodResolver   : Looking for @ControllerAdvice: org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext@59402b8f: startup date [Sun Nov 19 13:53:09 CST 2017]; root of context hierarchy
2017-11-19 13:53:11.256  INFO 6976 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-11-19 13:53:11.523  INFO 6976 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext     : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2017-11-19 13:53:11.524  INFO 6976 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2017-11-19 13:53:11.530  INFO 6976 --- [           main] n.x.p.DemoSpringbootWebflux2Application  : Started DemoSpringbootWebflux2Application in 2.554 seconds (JVM running for 3.059)
通过启动日志我们可以看到。默认情况下webflux已经不是使用tomcat容器启动项目。而是替换为netty容器启动的项目。

运行我们上面创建的webclient:
重点截图1:
webclient这里可以看到打印的请求日志http相关的头部信息

重点截图2:
webclient执行结果上面可以看到调用的返回已经自动载入Persion对象。

通过上面的使用不难发现使用weblcient在Java中进行http通讯是非常方便的。而且支持nio异步操作。在效率上也应该有所提升。在使用微服务的时候,是否可以考虑服务之间通讯使用weblcient?
暂无评论