引言
在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:
这里可以看到打印的请求日志http相关的头部信息
重点截图2:
上面可以看到调用的返回已经自动载入Persion对象。
通过上面的使用不难发现使用weblcient在Java中进行http通讯是非常方便的。而且支持nio异步操作。在效率上也应该有所提升。在使用微服务的时候,是否可以考虑服务之间通讯使用weblcient?
https://www.leftso.com/article/311.html