基础接口
webflux的基础接口类似于Spring MVC的几个主要组件。
DispatcherHandler
DispatcherHandler
,它是WebFlux服务器端点处理的主要入口点,包括用于将请求映射到处理程序的关键协议,调用它们并处理结果。
该模块为反应式服务器端点提供两种编程模型。一个基于注释@Controller
,另一个基于功能路由和处理。该模块还包含一个功能性,反应式WebClient
以及客户端和服务器,反应式WebSocket
支持。
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
@Nullable
private List<HandlerMapping> handlerMappings;
@Nullable
private List<HandlerAdapter> handlerAdapters;
@Nullable
private List<HandlerResultHandler> resultHandlers;
public DispatcherHandler(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
protected void initStrategies(ApplicationContext context) {
//查找所有HandlerMapping类
Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerMapping.class, true, false);
ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
//排序
AnnotationAwareOrderComparator.sort(mappings);
this.handlerMappings = Collections.unmodifiableList(mappings);
//获取所有HandlerAdapter
Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
this.handlerAdapters = new ArrayList<>(adapterBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
//获取所有HandlerResultHandler
Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerResultHandler.class, true, false);
this.resultHandlers = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(this.resultHandlers);
}
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
return Flux.fromIterable(this.handlerMappings)
//获取对应的handler
.concatMap(mapping -> mapping.getHandler(exchange))
//返回第一个元素
.next()
//如果未找得到handler,发送error信号
.switchIfEmpty(createNotFoundError())
//使用handler处理请求
.flatMap(handler -> invokeHandler(exchange, handler))
//处理handler调用返回的结果。
.flatMap(result -> handleResult(exchange, result));
}
private <R> Mono<R> createNotFoundError() {
return Mono.defer(() -> {
Exception ex = new ResponseStatusException(HttpStatus.NOT_FOUND, "No matching handler");
return Mono.error(ex);
});
}
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
if (this.handlerAdapters != null) {
for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
if (handlerAdapter.supports(handler)) {
return handlerAdapter.handle(exchange, handler);
}
}
}
return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
return getResultHandler(result).handleResult(exchange, result)
.checkpoint("Handler " + result.getHandler() + " [DispatcherHandler]")
.onErrorResume(ex ->
result.applyExceptionHandler(ex).flatMap(exResult -> {
String text = "Exception handler " + exResult.getHandler() +
", error=\"" + ex.getMessage() + "\" [DispatcherHandler]";
return getResultHandler(exResult).handleResult(exchange, exResult).checkpoint(text);
}));
}
private HandlerResultHandler getResultHandler(HandlerResult handlerResult) {
if (this.resultHandlers != null) {
for (HandlerResultHandler resultHandler : this.resultHandlers) {
if (resultHandler.supports(handlerResult)) {
return resultHandler;
}
}
}
throw new IllegalStateException("No HandlerResultHandler for " + handlerResult.getReturnValue());
}
}
public interface WebHandler {
Mono<Void> handle(ServerWebExchange exchange);
}
HandlerMapping
查找给定请求的handler,如果找不到特定的请求,则返回一个空的Mono。
public interface HandlerMapping {
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
Mono<Object> getHandler(ServerWebExchange exchange);
}
HandlerAdapter
用获取到的handler处理请求。
public interface HandlerAdapter {
boolean supports(Object handler);
Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler);
}
HandlerResult
处理结果。
public class HandlerResult {
private final Object handler;
@Nullable
private final Object returnValue;
private final ResolvableType returnType;
private final BindingContext bindingContext;
@Nullable
private Function<Throwable, Mono<HandlerResult>> exceptionHandler;
}
HandlerResultHandler
处理 HandlerResult的handler。
public interface HandlerResultHandler {
boolean supports(HandlerResult result);
Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result);
}
handler包
AbstractHandlerMapping
AbstractHandlerMapping, ***HandlerMapping***实现的抽象基类。 类似于Spring MVC中的AbstractHandlerMapping,类继承结构基本上都差不多。
![1610453334384](https://gitee.com/demon75520/images/raw/master/csdn/2021/01/1610453334384.png)
public abstract class AbstractHandlerMapping extends ApplicationObjectSupport
implements HandlerMapping, Ordered, BeanNameAware {
private static final WebHandler REQUEST_HANDLED_HANDLER = exchange -> Mono.empty();
private final PathPatternParser patternParser;
@Nullable
private CorsConfigurationSource corsConfigurationSource;
private CorsProcessor corsProcessor = new DefaultCorsProcessor();
private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered
@Nullable
private String beanName;
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {
return getHandlerInternal(exchange).map(handler -> {
if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
}
ServerHttpRequest request = exchange.getRequest();
//如果有cors配置或者
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(exchange) : null);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, exchange);
config = (config != null ? config.combine(handlerConfig) : handlerConfig);
if (!this.corsProcessor.process(config, exchange) || CorsUtils.isPreFlightRequest(request)) {
return REQUEST_HANDLED_HANDLER;
}
}
return handler;
});
}
/*由子类实现*/
protected abstract Mono<?> getHandlerInternal(ServerWebExchange exchange);
getHandler,在CORS 预先请求中,该方法应该返回一个匹配,而不是预先请求的请求,而是基于URL路径的预期实际请求,从“Access-Control-Request-Method”头,以及“Access-Control-Request-Headers”头的HTTP方法,通过 getcorsconfiguration获得CORS配置来允许通过。
AbstractUrlHandlerMapping
基于URL映射的HandlerMapping实现的抽象基类。
支持直接匹配,例如注册的“/ test”匹配“/ test”,以及各种ant样式匹配,例如, “/ test *”匹配“/ test”和“/ team”,“/ test / *”匹配“/ test”下的所有路径。
包含注册handler方法。
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
private boolean lazyInitHandlers = false;
/*url与handler映射*/
private final Map<PathPattern, Object> handlerMap = new LinkedHashMap<>();
@Override
public Mono<Object> getHandlerInternal(ServerWebExchange exchange) {
//从request获取path
PathContainer lookupPath = exchange.getRequest().getPath().pathWithinApplication();
Object handler;
try {
handler = lookupHandler(lookupPath, exchange);
}
catch (Exception ex) {
return Mono.error(ex);
}
return Mono.justOrEmpty(handler);
}
protected Object lookupHandler(PathContainer lookupPath, ServerWebExchange exchange) throws Exception {
//是否匹配
List<PathPattern> matches = this.handlerMap.keySet().stream()
.filter(key -> key.matches(lookupPath))
.collect(Collectors.toList());
if (matches.isEmpty()) {
return null;
}
//查找到多个,则排序,选择最优
if (matches.size() > 1) {
matches.sort(PathPattern.SPECIFICITY_COMPARATOR);
if (logger.isTraceEnabled()) {
logger.debug(exchange.getLogPrefix() + "Matching patterns " + matches);
}
}
PathPattern pattern = matches.get(0);
//抽取path
PathContainer pathWithinMapping = pattern.extractPathWithinPattern(lookupPath);
return handleMatch(this.handlerMap.get(pattern), pattern, pathWithinMapping, exchange);
}
//处理匹配的handler,因为有的是beanName,有的是handler。
private Object handleMatch(Object handler, PathPattern bestMatch, PathContainer pathWithinMapping,
ServerWebExchange exchange) {
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
validateHandler(handler, exchange);
exchange.getAttributes().put(BEST_MATCHING_HANDLER_ATTRIBUTE, handler);
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatch);
exchange.getAttributes().put(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
return handler;
}
}
SimpleUrlHandlerMapping
AbstractUrlHandlerMapping的实现, 把url请求映射到对应的request handler
的bean 。 支持映射到bean实例和映射到bean名称;非单例的handler需要映射到bean名称。
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
/*映射
url 加前缀/, beanName做trim*/
private final Map<String, Object> urlMap = new LinkedHashMap<>();
}
config包
config包内主要是一些用于辅助设置属性的类。
EnableWebFlux
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebFluxConfiguration.class)
public @interface EnableWebFlux {
}
WebFluxConfigurer
类似于Spring-Security 的Configurer。配置一些处理方式。
public interface WebFluxConfigurer {
//配置如何解决响应请求的内容类型。
default void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
}
default void addCorsMappings(CorsRegistry registry) {
}
default void configurePathMatching(PathMatchConfigurer configurer) {
}
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
default void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
}
default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
}
default void addFormatters(FormatterRegistry registry) {
}
@Nullable
default Validator getValidator() {
return null;
}
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
default void configureViewResolvers(ViewResolverRegistry registry) {
}
}
DelegatingWebFluxConfiguration
组合configurers的配置。
@Configuration(proxyBeanMethods = false)
public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {
private final WebFluxConfigurerComposite configurers = new WebFluxConfigurerComposite();
}
PathMatchConfigurer
协助配置HandlerMapping的路径匹配选项。
public class PathMatchConfigurer {
@Nullable
private Boolean trailingSlashMatch;
@Nullable
private Boolean caseSensitiveMatch;
@Nullable
private Map<String, Predicate<Class<?>>> pathPrefixes;
}
CorsRegistration
协助创建映射到路径模式的CorsConfiguration实例。默认情况下,当最大时间设置为30分钟时,允许GET,HEAD和POST请求的所有来源,标题和凭证。
public class CorsRegistration {
private final String pathPattern;
private final CorsConfiguration config;
}
CorsRegistry
CorsRegistry协助注册CorsConfiguration映射到路径模式。 为指定的路径模式启用跨域请求处理
public class CorsRegistry {
private final List<CorsRegistration> registrations = new ArrayList<>();
/**加映射*/
public CorsRegistration addMapping(String pathPattern) {
CorsRegistration registration = new CorsRegistration(pathPattern);
this.registrations.add(registration);
return registration;
}
}
ResourceHandlerRegistration
协助创建和配置静态资源处理程序。
public class ResourceHandlerRegistration {
//用于将字符串位置转换为资源的资源加载器
private final ResourceLoader resourceLoader;
//一个或多个资源URL路径模式
private final String[] pathPatterns;
private final List<String> locationValues = new ArrayList<>();
@Nullable
private CacheControl cacheControl;
@Nullable
private ResourceChainRegistration resourceChainRegistration;
//获取ResourceWebHandler
protected ResourceWebHandler getRequestHandler() {
//构造ResourceWebHandler,并设置属性。
ResourceWebHandler handler = new ResourceWebHandler();
handler.setLocationValues(this.locationValues);
handler.setResourceLoader(this.resourceLoader);
if (this.resourceChainRegistration != null) {
handler.setResourceResolvers(this.resourceChainRegistration.getResourceResolvers());
handler.setResourceTransformers(this.resourceChainRegistration.getResourceTransformers());
}
if (this.cacheControl != null) {
handler.setCacheControl(this.cacheControl);
}
return handler;
}
}
ResourceHandlerRegistry
通过Spring WebFlux存储资源处理程序的注册,以提供静态资源(如图像,css文件和其他),包括设置优化的高速缓存头,以便在Web浏览器中进行高效加载。资源可以从Web应用程序根目录下的位置,类路径和其他位置提供。
public class ResourceHandlerRegistry {
private final ResourceLoader resourceLoader;
//Registration
private final List<ResourceHandlerRegistration> registrations = new ArrayList<>();
private int order = Ordered.LOWEST_PRECEDENCE - 1;
@Nullable
private ResourceUrlProvider resourceUrlProvider;
//注册路径
public ResourceHandlerRegistration addResourceHandler(String... patterns) {
ResourceHandlerRegistration registration = new ResourceHandlerRegistration(this.resourceLoader, patterns);
this.registrations.add(registration);
return registration;
}
}
ViewResolverRegistry
协助配置一个ViewResolver的链,支持不同的模板机制。另外,还可以根据所请求的内容类型配置defaultView以进行渲染,例如, JSON,XML等
UrlBasedViewResolverRegistration
协助配置UrlBasedViewResolver的属性。
resource包
resource
包下的类主要是为静态资源提供服务的类。
HttpResource
public interface HttpResource extends Resource {
HttpHeaders getResponseHeaders();
}
ResourceResolver
处理 对服务器端资源的请求。
ublic interface ResourceResolver {
/**将提供的请求和请求路径解析为存在于其中一个给定资源位置下的资源。*/
Mono<Resource> resolveResource(@Nullable ServerWebExchange exchange, String requestPath,
List<? extends Resource> locations, ResourceResolverChain chain);
/**解析面向外部的公用URL路径,供客户端用来访问位于给定内部资源路径的资源。*/
Mono<String> resolveUrlPath(String resourcePath, List<? extends Resource> locations,
ResourceResolverChain chain);
}
ResourceResolverChain
public interface ResourceResolverChain {
/***/
Mono<Resource> resolveResource(@Nullable ServerWebExchange exchange, String requestPath,
List<? extends Resource> locations);
/***/
Mono<String> resolveUrlPath(String resourcePath, List<? extends Resource> locations);
}
ResourceTransformer
资源转换器。
public interface ResourceTransformer {
Mono<Resource> transform(ServerWebExchange exchange, Resource resource,
ResourceTransformerChain transformerChain);
}
ResourceTransformerChain
public interface ResourceTransformerChain {
ResourceResolverChain getResolverChain();
Mono<Resource> transform(ServerWebExchange exchange, Resource resource);
}