小架构step系列20:请求和响应的扩展点

发布于:2025-07-21 ⋅ 阅读:(11) ⋅ 点赞:(0)

1 概述

通过上一篇了解请求和响应的流程,Spring在设计上留了不少扩展点。里面通过查找接口的方式获取的地方,都可以成为一种扩展点,因为只要实现这类接口就可以成为Spring加载的一部分。本文了解一下这些扩展点,方便后面进行扩展。

2 原理

2.1 HandleInterceptor的扩展点

加载HandleInterceptor的方法getInterceptors是在各个HandlerMapping初始化的时候调用的,该方法的调用会加载所有实现了WebMvcConfigurer接口的类,通过WebMvcConfigurer提供的addInterceptors()可以自定义增加HandleInterceptor:

// 继承关系:EnableWebMvcConfiguration < DelegatingWebMvcConfiguration < WebMvcConfigurationSupport
// EnableWebMvcConfiguration在开启WebMvc后由Spring触发加载
// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
protected final Object[] getInterceptors(FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    if (this.interceptors == null) {
        InterceptorRegistry registry = new InterceptorRegistry();
        // 加载自定义HandleInterceptor,自定义的Interceptor在最前面
        addInterceptors(registry);
        registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService));
        registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider));
        this.interceptors = registry.getInterceptors();
    }
    return this.interceptors.toArray();
}
// 源码位置:org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
protected void addInterceptors(InterceptorRegistry registry) {
    // configurers为WebMvcConfigurerComposite
    this.configurers.addInterceptors(registry);
}
// org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite
public void addInterceptors(InterceptorRegistry registry) {
    // delegates里注入了所有实现了WebMvcConfigurer接口的类,
    // 也就是说如果希望自定义一个HandlerInterceptor,则可以通过实现WebMvcConfigurer接口来完成
    for (WebMvcConfigurer delegate : this.delegates) {
        delegate.addInterceptors(registry);
    }
}

2.2 HandlerMethodArgumentResolver扩展点

在初始化RequestMappingHandlerAdapter的时候,就把实现WebMvcConfigurer接口来增加的HandlerMethodArgumentResolver存放到了RequestMappingHandlerAdapter,在RequestMappingHandlerAdapter执行afterPropertiesSet()的时候,再把自定义的HandlerMethodArgumentResolver和默认的一起加到argumentResolvers中:

// RequestMappingHandlerAdapter初始化后,触发afterPropertiesSet()方法,在里面初始化HandlerMethodArgumentResolver
// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans
    initControllerAdviceCache();

    if (this.argumentResolvers == null) {
        // 加载默认的HandlerMethodArgumentResolver
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.initBinderArgumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.returnValueHandlers == null) {
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
    List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(30);
    // 创建了二十多个HandlerMethodArgumentResolver
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
    resolvers.add(new RequestParamMapMethodArgumentResolver());
    resolvers.add(new PathVariableMethodArgumentResolver());
    resolvers.add(new PathVariableMapMethodArgumentResolver());
    resolvers.add(new MatrixVariableMethodArgumentResolver());
    resolvers.add(new MatrixVariableMapMethodArgumentResolver());
    resolvers.add(new ServletModelAttributeMethodProcessor(false));
    resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new RequestHeaderMapMethodArgumentResolver());
    resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    resolvers.add(new SessionAttributeMethodArgumentResolver());
    resolvers.add(new RequestAttributeMethodArgumentResolver());
    resolvers.add(new ServletRequestMethodArgumentResolver());
    resolvers.add(new ServletResponseMethodArgumentResolver());
    resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
    resolvers.add(new RedirectAttributesMethodArgumentResolver());
    resolvers.add(new ModelMethodProcessor());
    resolvers.add(new MapMethodProcessor());
    resolvers.add(new ErrorsMethodArgumentResolver());
    resolvers.add(new SessionStatusMethodArgumentResolver());
    resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
    if (KotlinDetector.isKotlinPresent()) {
        resolvers.add(new ContinuationHandlerMethodArgumentResolver());
    }
    
    // 加载自定义的HandlerMethodArgumentResolver,注意自定义的Resolver是在中间偏后的位置
    if (getCustomArgumentResolvers() != null) {
        resolvers.addAll(getCustomArgumentResolvers());
    }

    resolvers.add(new PrincipalMethodArgumentResolver());
    resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
    resolvers.add(new ServletModelAttributeMethodProcessor(true));

    return resolvers;
}
public List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() {
    // 自定义的HandlerMethodArgumentResolver是在之前赋值的
    return this.customArgumentResolvers;
}

// 源码位置:org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.EnableWebMvcConfiguration
@Bean
@Override
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
        @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcValidator") Validator validator) {
    // 父类为WebMvcConfigurationSupport
    RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager, conversionService, validator);
    adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect());
    return adapter;
}

// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
        @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcValidator") Validator validator) {
    RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
    adapter.setContentNegotiationManager(contentNegotiationManager);
    adapter.setMessageConverters(getMessageConverters());
    adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
    // 设置自定义的HandlerMethodArgumentResolver
    adapter.setCustomArgumentResolvers(getArgumentResolvers());
    adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

    if (jackson2Present) {
        adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
        adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
    }

    AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
    if (configurer.getTaskExecutor() != null) {
        adapter.setTaskExecutor(configurer.getTaskExecutor());
    }
    if (configurer.getTimeout() != null) {
        adapter.setAsyncRequestTimeout(configurer.getTimeout());
    }
    adapter.setCallableInterceptors(configurer.getCallableInterceptors());
    adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

    return adapter;
}
protected final List<HandlerMethodArgumentResolver> getArgumentResolvers() {
    if (this.argumentResolvers == null) {
        this.argumentResolvers = new ArrayList<>();
        // addArgumentResolvers()接口由DelegatingWebMvcConfiguration实现
        addArgumentResolvers(this.argumentResolvers);
    }
    return this.argumentResolvers;
}

// 源码位置:org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    // configurers为WebMvcConfigurerComposite
    this.configurers.addArgumentResolvers(argumentResolvers);
}

// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    // delegates里注入了所有实现了WebMvcConfigurer接口的类,
    // 也就是说如果希望自定义一个HandlerMethodArgumentResolver,则可以通过实现WebMvcConfigurer接口来完成
    for (WebMvcConfigurer delegate : this.delegates) {
        delegate.addArgumentResolvers(argumentResolvers);
    }
}

2.3 RequestMappingHandlerAdapter的扩展点

在初始化RequestMappingHandlerAdapter的时候,就把实现WebMvcConfigurer接口来增加的HandlerMethodReturnValueHandler存放到了RequestMappingHandlerAdapter,在RequestMappingHandlerAdapter执行afterPropertiesSet()的时候,再把自定义的HandlerMethodReturnValueHandler和默认的一起加到returnValueHandlers中:

// RequestMappingHandlerAdapter初始化后,触发afterPropertiesSet()方法,在里面初始化HandlerMethodReturnValueHandler
// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans
    initControllerAdviceCache();

    if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.initBinderArgumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.returnValueHandlers == null) {
        // 加载默认的HandlerMethodReturnValueHandler
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);

    handlers.add(new ModelAndViewMethodReturnValueHandler());
    handlers.add(new ModelMethodProcessor());
    handlers.add(new ViewMethodReturnValueHandler());
    handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
            this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
    handlers.add(new StreamingResponseBodyReturnValueHandler());
    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));
    handlers.add(new HttpHeadersReturnValueHandler());
    handlers.add(new CallableMethodReturnValueHandler());
    handlers.add(new DeferredResultMethodReturnValueHandler());
    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
    handlers.add(new ServletModelAttributeMethodProcessor(false));
    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));
    handlers.add(new ViewNameMethodReturnValueHandler());
    handlers.add(new MapMethodProcessor());

    // 加载自定义的HandlerMethodReturnValueHandler,注意自定义的Handler是在中间偏后的位置
    if (getCustomReturnValueHandlers() != null) {
        handlers.addAll(getCustomReturnValueHandlers());
    }

    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
        handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
    }
    else {
        handlers.add(new ServletModelAttributeMethodProcessor(true));
    }

    return handlers;
}
public List<HandlerMethodReturnValueHandler> getCustomReturnValueHandlers() {
    // 自定义的HandlerMethodReturnValueHandler是在之前赋值的
    return this.customReturnValueHandlers;
}

// 初始化RequestMappingHandlerAdapter的时候,加载自定义的HandlerMethodReturnValueHandler
// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
        @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcValidator") Validator validator) {
    RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
    adapter.setContentNegotiationManager(contentNegotiationManager);
    adapter.setMessageConverters(getMessageConverters());
    adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
    adapter.setCustomArgumentResolvers(getArgumentResolvers());
    // 设置自定义的RequestMappingHandlerAdapter
    adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

    if (jackson2Present) {
        adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
        adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
    }

    AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
    if (configurer.getTaskExecutor() != null) {
        adapter.setTaskExecutor(configurer.getTaskExecutor());
    }
    if (configurer.getTimeout() != null) {
        adapter.setAsyncRequestTimeout(configurer.getTimeout());
    }
    adapter.setCallableInterceptors(configurer.getCallableInterceptors());
    adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

    return adapter;
}
protected final List<HandlerMethodReturnValueHandler> getReturnValueHandlers() {
    if (this.returnValueHandlers == null) {
        this.returnValueHandlers = new ArrayList<>();
        // addReturnValueHandlers()接口由DelegatingWebMvcConfiguration实现
        addReturnValueHandlers(this.returnValueHandlers);
    }
    return this.returnValueHandlers;
}

// 源码位置:org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
    // configurers为WebMvcConfigurerComposite
    this.configurers.addReturnValueHandlers(returnValueHandlers);
}

// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
    for (WebMvcConfigurer delegate : this.delegates) {
        // delegates里注入了所有实现了WebMvcConfigurer接口的类,
        // 也就是说如果希望自定义一个RequestMappingHandlerAdapter,则可以通过实现WebMvcConfigurer接口来完成
        delegate.addReturnValueHandlers(returnValueHandlers);
    }
}

2.4 MessageConverter的扩展点

在初始化RequestMappingHandlerAdapter的时候,就把实现WebMvcConfigurer接口来增加的MessageConverter存放到了RequestMappingHandlerAdapter,在RequestMappingHandlerAdapter执行afterPropertiesSet()的时候,再把自定义的MessageConverter加到messageConverters中:

// RequestMappingHandlerAdapter初始化后,触发afterPropertiesSet()方法,在里面初始化HandlerMethodReturnValueHandler
// 源码位置:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
public void afterPropertiesSet() {
    // Do this first, it may add ResponseBody advice beans
    initControllerAdviceCache();

    if (this.argumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
        this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.initBinderArgumentResolvers == null) {
        List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
        this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
    }
    if (this.returnValueHandlers == null) {
        // 加载默认的HandlerMethodReturnValueHandler
        List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
        this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
    }
}
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);

    handlers.add(new ModelAndViewMethodReturnValueHandler());
    handlers.add(new ModelMethodProcessor());
    handlers.add(new ViewMethodReturnValueHandler());
    // 有设置MessageConverter
    handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
            this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));
    handlers.add(new StreamingResponseBodyReturnValueHandler());
    // 有设置MessageConverter
    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));
    handlers.add(new HttpHeadersReturnValueHandler());
    handlers.add(new CallableMethodReturnValueHandler());
    handlers.add(new DeferredResultMethodReturnValueHandler());
    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
    handlers.add(new ServletModelAttributeMethodProcessor(false));
    // 有设置MessageConverter
    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
            this.contentNegotiationManager, this.requestResponseBodyAdvice));
    handlers.add(new ViewNameMethodReturnValueHandler());
    handlers.add(new MapMethodProcessor());

    if (getCustomReturnValueHandlers() != null) {
        handlers.addAll(getCustomReturnValueHandlers());
    }

    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
        handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
    }
    else {
        handlers.add(new ServletModelAttributeMethodProcessor(true));
    }

    return handlers;
}
public List<HttpMessageConverter<?>> getMessageConverters() {
    // 自定义的MessageConverter是在之前赋值的
    return this.messageConverters;
}

// 初始化RequestMappingHandlerAdapter的时候,加载自定义的MessageConverter
// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
        @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
        @Qualifier("mvcConversionService") FormattingConversionService conversionService,
        @Qualifier("mvcValidator") Validator validator) {
    RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
    adapter.setContentNegotiationManager(contentNegotiationManager);
    // 设置自定义的MessageConverter
    adapter.setMessageConverters(getMessageConverters());
    adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
    adapter.setCustomArgumentResolvers(getArgumentResolvers());
    adapter.setCustomReturnValueHandlers(getReturnValueHandlers());

    if (jackson2Present) {
        adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice()));
        adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));
    }

    AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
    if (configurer.getTaskExecutor() != null) {
        adapter.setTaskExecutor(configurer.getTaskExecutor());
    }
    if (configurer.getTimeout() != null) {
        adapter.setAsyncRequestTimeout(configurer.getTimeout());
    }
    adapter.setCallableInterceptors(configurer.getCallableInterceptors());
    adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());

    return adapter;
}
protected final List<HttpMessageConverter<?>> getMessageConverters() {
    if (this.messageConverters == null) {
        this.messageConverters = new ArrayList<>();
        // 配置自定义的MessageConverter
        configureMessageConverters(this.messageConverters);
        if (this.messageConverters.isEmpty()) {
            addDefaultHttpMessageConverters(this.messageConverters);
        }
        extendMessageConverters(this.messageConverters);
    }
    return this.messageConverters;
}

// 源码位置:org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    // configurers为WebMvcConfigurerComposite
    this.configurers.configureMessageConverters(converters);
}

// 源码位置:org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    for (WebMvcConfigurer delegate : this.delegates) {
        // delegates里注入了所有实现了WebMvcConfigurer接口的类,
        // 也就是说如果希望自定义一个MessageConverter,则可以通过实现WebMvcConfigurer接口来完成
        delegate.configureMessageConverters(converters);
    }
}

3 架构一小步

  • Controller接口处理前后要预先或者做后处理时用HandleInterceptor扩展。
  • Controller接口处理特殊参数的时候用HandlerMethodArgumentResolver扩展。
  • 请求返回值格式处理可以通过MessageConverter扩展。
  • 整个请求的处理如果需要替换则用RequestMappingHandlerAdapter扩展,这个除非有特殊请求,否则不推荐。
上面这些扩展都通过继承WebMvcConfigurer来增加扩展类。

网站公告

今日签到

点亮在社区的每一天
去签到