webflux
org.springframework.boot
spring-boot-starter-webflux
org.springframework.boot
spring-boot-starter-test
test
启动
@SpringBootApplication
@RestController
public class FluxWebApplication {
public static void main(String[] args) {
SpringApplication.run(FluxWebApplication.class, args);
}
@GetMapping("hello")
public String hello(){
return"hello";
}
@GetMapping("hello2")
public Mono hello2(){
return Mono.just("hello2");
}
@GetMapping("hello3")
public Flux hello3(){
String[] str = {"123","abc"};
return Flux.fromArray(str).filter(s -> "123".equals(s));
}
}
WebFluxAutoConfiguration
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass(WebFluxConfigurer.class)
//定义初始化requestmapper请求处理(fluxweb主配置)
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
//服务容器配置/序列化/反序列化/参数校验
@AutoConfigureAfter({ ReactiveWebServerFactoryAutoConfiguration.class,
CodecsAutoConfiguration.class, ValidationAutoConfiguration.class })
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebFluxAutoConfiguration {
//略去一些代码
//下面fluxweb基础配置初始,包含 beanfactory,view转换器,请求参数处器等
//这块其实跟springmvc类似
@Configuration
@EnableConfigurationProperties({ ResourceProperties.class, WebFluxProperties.class })
@Import({ EnableWebFluxConfiguration.class })
public static class WebFluxConfig implements WebFluxConfigurer {
private final ResourceProperties resourceProperties;
private final WebFluxProperties webFluxProperties;
private final ListableBeanFactory beanFactory;
//方法参数处理器
private final List argumentResolvers;
//处定义http编解码器
private final List codecCustomizers;
private final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
//视图转换器
private final List viewResolvers;
//略去一些代码
}
//略去一些代码
}
fluxweb主配置
WebFluxConfigurationSupport
/**
* The main class for Spring WebFlux configuration.
* Import directly or extend and override protected methods to customize.
*/
public class WebFluxConfigurationSupport implements ApplicationContextAware {
//跨域配置列表
@Nullable
private Map corsConfigurations;
//请求路径匹配配置器
@Nullable
private PathMatchConfigurer pathMatchConfigurer;
//视图转器注册器
@Nullable
private ViewResolverRegistry viewResolverRegistry;
//请求分发处理器,类似mvc的DispatcherServlet
@Bean
public DispatcherHandler webHandler() {
return new DispatcherHandler();
}
//响应异常处理器
@Bean
@Order(0)
public WebExceptionHandler responseStatusExceptionHandler() {
return new WebFluxResponseStatusExceptionHandler();
}
//请求mapping处理器,跟mvc的差不多,找出请求与方法的映射关系
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
mapping.setOrder(0);
mapping.setContentTypeResolver(webFluxContentTypeResolver());
mapping.setCorsConfigurations(getCorsConfigurations());
//path匹配配置
PathMatchConfigurer configurer = getPathMatchConfigurer();
Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
if (useTrailingSlashMatch != null) {
mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
}
Boolean useCaseSensitiveMatch = configurer.isUseCaseSensitiveMatch();
if (useCaseSensitiveMatch != null) {
mapping.setUseCaseSensitiveMatch(useCaseSensitiveMatch);
}
return mapping;
}
//略去一些代码
//请求media类型策略处理器,如application/jsion;text/html等对应不用处理策略
@Bean
public RequestedContentTypeResolver webFluxContentTypeResolver() {
RequestedContentTypeResolverBuilder builder = new RequestedContentTypeResolverBuilder();
configureContentTypeResolver(builder);
return builder.build();
}
//略去一些代码
//路由功能mapping ,请求路由与处理器的关系映射,跟上面的RequestMappingHandlerMapping 实现一样的功能
@Bean
public RouterFunctionMapping routerFunctionMapping() {
RouterFunctionMapping mapping = createRouterFunctionMapping();
mapping.setOrder(-1); // go before RequestMappingHandlerMapping
mapping.setMessageReaders(serverCodecConfigurer().getReaders());
mapping.setCorsConfigurations(getCorsConfigurations());
return mapping;
}
//略去一些代码
/**
* Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped
* resource handlers. To configure resource handling, override
* {@link #addResourceHandlers}.
*/
@Bean
public HandlerMapping resourceHandlerMapping() {
ResourceLoader resourceLoader = this.applicationContext;
if (resourceLoader == null) {
resourceLoader = new DefaultResourceLoader();
}
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(resourceLoader);
addResourceHandlers(registry);
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
if (handlerMapping != null) {
PathMatchConfigurer configurer = getPathMatchConfigurer();
Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
Boolean useCaseSensitiveMatch = configurer.isUseCaseSensitiveMatch();
if (useTrailingSlashMatch != null) {
handlerMapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
}
if (useCaseSensitiveMatch != null) {
handlerMapping.setUseCaseSensitiveMatch(useCaseSensitiveMatch);
}
}
else {
handlerMapping = new EmptyHandlerMapping();
}
return handlerMapping;
}
/**
* Override this method to add resource handlers for serving static resources.
* @see ResourceHandlerRegistry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
}
//mappinghandler 适配器
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setMessageReaders(serverCodecConfigurer().getReaders());
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());
adapter.setReactiveAdapterRegistry(webFluxAdapterRegistry());
ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer();
configureArgumentResolvers(configurer);
adapter.setArgumentResolverConfigurer(configurer);
return adapter;
}
/**
* http请求消息编解码器
* Return the configurer for HTTP message readers and writers.
*/
@Bean
public ServerCodecConfigurer serverCodecConfigurer() {
ServerCodecConfigurer serverCodecConfigurer = ServerCodecConfigurer.create();
configureHttpMessageCodecs(serverCodecConfigurer);
return serverCodecConfigurer;
}
/**
* Return the {@link ConfigurableWebBindingInitializer} to use for
* initializing all {@link WebDataBinder} instances.
*/
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
initializer.setConversionService(webFluxConversionService());
initializer.setValidator(webFluxValidator());
MessageCodesResolver messageCodesResolver = getMessageCodesResolver();
if (messageCodesResolver != null) {
initializer.setMessageCodesResolver(messageCodesResolver);
}
return initializer;
}
//略去一些代码
//响应结果处理器
@Bean
public ResponseEntityResultHandler responseEntityResultHandler() {
return new ResponseEntityResultHandler(serverCodecConfigurer().getWriters(),
webFluxContentTypeResolver(), webFluxAdapterRegistry());
}
//响应体处理器
@Bean
public ResponseBodyResultHandler responseBodyResultHandler() {
return new ResponseBodyResultHandler(serverCodecConfigurer().getWriters(),
webFluxContentTypeResolver(), webFluxAdapterRegistry());
}
//视图处理器
@Bean
public ViewResolutionResultHandler viewResolutionResultHandler() {
ViewResolverRegistry registry = getViewResolverRegistry();
List resolvers = registry.getViewResolvers();
ViewResolutionResultHandler handler = new ViewResolutionResultHandler(
resolvers, webFluxContentTypeResolver(), webFluxAdapterRegistry());
handler.setDefaultViews(registry.getDefaultViews());
handler.setOrder(registry.getOrder());
return handler;
}
//服务响应处理器
@Bean
public ServerResponseResultHandler serverResponseResultHandler() {
List resolvers = getViewResolverRegistry().getViewResolvers();
ServerResponseResultHandler handler = new ServerResponseResultHandler();
handler.setMessageWriters(serverCodecConfigurer().getWriters());
handler.setViewResolvers(resolvers);
return handler;
}
}
a . RequestMappingHandlerMapping
//该方法被InitializingBean 的afterPropertiesSet 调用
protected void initHandlerMethods() {
//扫描容器所有对象
String[] beanNames = obtainApplicationContext().getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class beanType = null;
try {
beanType = obtainApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
//检是是否为handler method
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
}
handlerMethodsInitialized(getHandlerMethods());
}
/**
* Initialized the router functions by detecting them in the application context.
*/
protected void initRouterFunctions() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for router functions in application context: " +
getApplicationContext());
}
//获取路由信息
List> routerFunctions = routerFunctions();
if (!CollectionUtils.isEmpty(routerFunctions) && logger.isInfoEnabled()) {
routerFunctions.forEach(routerFunction -> logger.info("Mapped " + routerFunction));
}
//转为一个组合由路信息
this.routerFunction = routerFunctions.stream()
.reduce(RouterFunction::andOther)
.orElse(null);
}
private List> routerFunctions() {
//创建rooter容器,并从beanfactory获取rooter并注入该容器
RouterFunctionMapping.SortedRouterFunctionsContainer container = new RouterFunctionMapping.SortedRouterFunctionsContainer();
obtainApplicationContext().getAutowireCapableBeanFactory().autowireBean(container);
return CollectionUtils.isEmpty(container.routerFunctions) ? Collections.emptyList() :
container.routerFunctions;
}
路由转发处理器
DispatcherHandler
//初始化
protected void initStrategies(ApplicationContext context) {
//handlermapping 包含requesthandlermapping 和 RouterFunctionMapping
Map mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerMapping.class, true, false);
ArrayList mappings = new ArrayList<>(mappingBeans.values());
AnnotationAwareOrderComparator.sort(mappings);
this.handlerMappings = Collections.unmodifiableList(mappings);
Map adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
//排一下序
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}
ReactiveWebServerFactoryConfiguration
abstract class ReactiveWebServerFactoryConfiguration {
//内置启用netty容器
@Configuration
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ HttpServer.class })
static class EmbeddedNetty {
@Bean
public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() {
return new NettyReactiveWebServerFactory();
}
}
//内置启用tomcat容器
@Configuration
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ org.apache.catalina.startup.Tomcat.class })
static class EmbeddedTomcat {
@Bean
public TomcatReactiveWebServerFactory tomcatReactiveWebServerFactory() {
return new TomcatReactiveWebServerFactory();
}
}
//内置启用webservser容器
@Configuration
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ org.eclipse.jetty.server.Server.class })
static class EmbeddedJetty {
@Bean
public JettyReactiveWebServerFactory jettyReactiveWebServerFactory() {
return new JettyReactiveWebServerFactory();
}
}
//内置启用Undertow容器
@ConditionalOnMissingBean(ReactiveWebServerFactory.class)
@ConditionalOnClass({ Undertow.class })
static class EmbeddedUndertow {
@Bean
public UndertowReactiveWebServerFactory undertowReactiveWebServerFactory() {
return new UndertowReactiveWebServerFactory();
}
}
}
http协议处理
HttpHandlerAutoConfiguration
@Configuration
@ConditionalOnClass({ DispatcherHandler.class, HttpHandler.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnMissingBean(HttpHandler.class)
@AutoConfigureAfter({ WebFluxAutoConfiguration.class })
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class HttpHandlerAutoConfiguration {
@Configuration
public static class AnnotationConfig {
private ApplicationContext applicationContext;
public AnnotationConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Bean
public HttpHandler httpHandler() {
return WebHttpHandlerBuilder.applicationContext(this.applicationContext)
.build();
}
}
}