SpringMVC请求处理流程源码解析(第2篇):处理器执行与参数绑定

SpringMVC请求处理流程源码解析(第2篇):处理器执行与参数绑定

本文深入剖析HandlerAdapter处理器适配器的适配器模式、参数绑定核心机制(WebDataBinder)、返回值处理的完整源码流程,以及拦截器链的执行机制。

目录

  1. HandlerAdapter处理器适配器
  2. 参数解析与数据绑定核心
  3. 常用参数解析器详解
  4. 返回值处理器详解
  5. 拦截器链执行机制

1. HandlerAdapter处理器适配器

1.1 HandlerAdapter体系

<<interface>>
HandlerAdapter
+supports(handler)
+handle(request, response, handler)
<<abstract>>
AbstractHandlerMethodAdapter
+supports(handler)
+handle(request, response, handler)
RequestMappingHandlerAdapter
-ArgumentResolver[] argumentResolvers
-ReturnValueHandler[] returnValueHandlers
-WebBindingInitializer[] webBindingInitializers
+invokeHandlerMethod()
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapter

1.2 HandlerAdapter接口定义

java 复制代码
// org.springframework.web.servlet.HandlerAdapter
public interface HandlerAdapter {
    
    /**
     * 判断适配器是否支持该处理器
     */
    boolean supports(Object handler);
    
    /**
     * 执行处理器,返回ModelAndView
     */
    ModelAndView handle(HttpServletRequest request, 
                       HttpServletResponse response,
                       Object handler) throws Exception;
    
    /**
     * 判断是否需要缓存(用于HTTP缓存支持)
     */
    long getLastModified(HttpServletRequest request, Object handler);
}

1.3 AbstractHandlerMethodAdapter源码

java 复制代码
// org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter
public abstract class AbstractHandlerMethodAdapter extends 
        WebContentGenerator implements HandlerAdapter, Ordered {
    
    private int order = Ordered.LOWEST_PRECEDENCE;
    
    @Override
    public final boolean supports(Object handler) {
        return (handler instanceof HandlerMethod && 
            supportsHandler((HandlerMethod) handler));
    }
    
    /**
     * 子类实现:判断是否支持特定的HandlerMethod
     */
    protected abstract boolean supportsHandler(HandlerMethod handlerMethod);
}

1.4 RequestMappingHandlerAdapter核心源码

这是最核心的HandlerAdapter,负责调用带@RequestMapping注解的Controller方法:

java 复制代码
// org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
        implements BeanFactoryAware, InitializingBean {
    
    private ConfigurableBeanFactory beanFactory;
    
    // 参数解析器组合
    private HandlerMethodArgumentResolverComposite argumentResolvers = 
        new HandlerMethodArgumentResolverComposite();
    
    // 返回值处理器组合
    private HandlerMethodReturnValueHandlerComposite returnValueHandlers = 
        new HandlerMethodReturnValueHandlerComposite();
    
    private List<WebBindingInitializer> webBindingInitializers = new ArrayList<>();
    
    // 默认忽略的Model属性前缀
    private ModelFactory modelFactory;
    
    @Override
    public void afterPropertiesSet() {
        // 1. 初始化参数解析器
        this.argumentResolvers.addResolvers(initArgumentResolvers());
        
        // 2. 初始化返回值处理器
        this.returnValueHandlers.addHandlers(initReturnValueHandlers());
        
        // 3. 初始化ControllerAdvice
        initControllerAdviceCallbacks();
        
        // 4. 初始化ModelFactory
        initModelFactory();
    }
    
    @Override
    protected ModelAndView handleInternal(HttpServletRequest request,
                                         HttpServletResponse response,
                                          HandlerMethod handlerMethod) {
        // 1. 检查请求方法(GET/POST等)
        checkRequest(request);
        
        // 2. 如果支持异步,执行异步处理
        if (this.synchronizeOnSession) {
            HttpSession session = request.getSession(false);
            if (session != null) {
                Object mutex = WebUtils.getSessionMutex(session);
                synchronized (mutex) {
                    return invokeHandlerMethod(request, response, handlerMethod);
                }
            }
        }
        
        // 3. 执行处理器方法
        return invokeHandlerMethod(request, response, handlerMethod);
    }
    
    /**
     * 执行HandlerMethod的核心方法
     */
    @Nullable
    public final ModelAndView invokeHandlerMethod(HttpServletRequest request,
                                                  HttpServletResponse response,
                                                  HandlerMethod handlerMethod) {
        // 1. 创建ServletWebRequest
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        
        // 2. 获取WebDataBinder工厂
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        
        // 3. 获取ModelFactory
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        
        // 4. 创建ServletInvocableHandlerMethod
        ServletInvocableHandlerMethod invocableMethod = 
            createInvocableHandlerMethod(handlerMethod);
        
        // 5. 设置参数解析器和返回值处理器
        if (this.argumentResolvers != null) {
            invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        }
        if (this.returnValueHandlers != null) {
            invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        }
        
        // 6. 创建ModelAndViewContainer
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(
            RequestContextUtils.getMergedOutputAttributes(request));
        
        // 7. 处理重定向属性
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        
        // 8. 快速路径:如果请求已处理,直接返回
        if (mavContainer.isRequestHandled()) {
            return null;
        }
        
        // 9. 执行方法并处理返回值
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        
        // 10. 获取ModelAndView
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    
    /**
     * 获取ModelAndView
     */
    @Nullable
    private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
                                        ModelFactory modelFactory,
                                        ServletWebRequest webRequest) {
        // 更新Model
        modelFactory.updateModel(webRequest, mavContainer);
        
        if (mavContainer.isRequestHandled()) {
            return null;
        }
        
        ModelMap model = mavContainer.getModel();
        View view = mavContainer.getView();
        
        if (view != null) {
            return new ModelAndView(view, model);
        }
        
        String viewName = mavContainer.getViewName();
        if (viewName != null) {
            return new ModelAndView(viewName, model);
        }
        
        return null;
    }
}

1.5 ServletInvocableHandlerMethod执行流程

java 复制代码
// org.springframework.web.method.support.ServletInvocableHandlerMethod
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
    
    @Nullable
    private HandlerMethodArgumentResolverComposite argumentResolverComposite;
    
    @Nullable
    private HandlerMethodReturnValueHandlerComposite returnValueHandlerComposite;
    
    /**
     * 执行方法并处理返回值
     */
    public void invokeAndHandle(ServletWebRequest webRequest,
                               ModelAndViewContainer mavContainer,
                               Object... providedArgs) {
        // 1. 执行方法获取返回值
        Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
        
        // 2. 设置响应状态
        setResponseStatus(webRequest);
        
        // 3. 如果返回值为null且未设置响应状态
        if (returnValue == null) {
            if (isRequestNotModified(webRequest) || 
                hasResponseStatus() || 
                mavContainer.isRequestHandled()) {
                mavContainer.setRequestHandled(true);
                return;
            }
        }
        
        // 4. 处理返回值
        try {
            this.returnValueHandlerComposite.handleReturnValue(
                returnValue, 
                getReturnValueType(returnValue),
                mavContainer, 
                webRequest);
        } catch (Exception ex) {
            // 处理异常
        }
    }
    
    @Nullable
    public Object invokeForRequest(ServletWebRequest request,
                                   ModelAndViewContainer mavContainer,
                                   Object... providedArgs) {
        // 1. 解析方法参数
        Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
        
        // 2. 调用方法
        return doInvoke(args);
    }
    
    /**
     * 参数解析完整流程
     */
    private Object[] getMethodArgumentValues(NativeWebRequest request,
                                             ModelAndViewContainer mavContainer,
                                             Object... providedArgs) {
        MethodParameter[] parameters = getMethodParameters();
        Object[] args = new Object[parameters.length];
        
        for (int i = 0; i < parameters.length; i++) {
            MethodParameter parameter = parameters[i];
            parameter.initParameterNameDiscovery(ParameterNameDiscoverer.DEFAULT);
            
            // 1. 优先使用提供的参数(通常为null)
            args[i] = findProvidedArgument(parameter, providedArgs);
            if (args[i] != null) {
                continue;
            }
            
            // 2. 判断是否有参数解析器支持
            if (!this.argumentResolverComposite.supportsParameter(parameter)) {
                throw new IllegalStateException(
                    "Cannot resolve argument " + i + " [" + 
                    parameter.getParameterName() + "]");
            }
            
            try {
                // 3. 解析参数值
                args[i] = this.argumentResolverComposite.resolveArgument(
                    parameter, mavContainer, request, null);
            } catch (Exception ex) {
                // 处理解析异常
            }
        }
        
        return args;
    }
}

1.6 选择流程

true
false
getHandlerAdapter
遍历handlerAdapters
adapter.supports方法
返回HandlerAdapter
尝试下一个
遍历结束
抛出ServletException


2. 参数解析与数据绑定核心

2.1 参数解析体系全景图

核心组件
HandlerMethodArgumentResolver
WebDataBinderFactory
WebDataBinder
ConversionService
参数解析流程
true
false
Controller方法
遍历ArgumentResolvers
resolver.supportsParameter
resolver.resolveArgument
尝试下一个
WebDataBinder类型转换
返回参数值

2.2 HandlerMethodArgumentResolver接口

java 复制代码
// org.springframework.web.method.support.HandlerMethodArgumentResolver
public interface HandlerMethodArgumentResolver {
    
    /**
     * 判断是否支持此参数
     */
    boolean supportsParameter(MethodParameter parameter);
    
    /**
     * 解析参数值
     */
    @Nullable
    Object resolveArgument(MethodParameter parameter,
                          @Nullable ModelAndViewContainer mavContainer,
                          NativeWebRequest webRequest,
                          @Nullable WebDataBinderFactory binderFactory) throws Exception;
}

2.3 HandlerMethodArgumentResolverComposite

SpringMVC使用组合模式管理所有参数解析器:

java 复制代码
// org.springframework.web.method.support.HandlerMethodArgumentResolverComposite
public class HandlerMethodArgumentResolverComposite 
        implements HandlerMethodArgumentResolver {
    
    // 解析器列表(有序)
    private final List<HandlerMethodArgumentResolver> resolvers = 
        new ArrayList<>();
    
    // 解析器缓存(参数类型 -> 解析器)
    private final Map<MethodParameter, HandlerMethodArgumentResolver> resolverCache =
        new ConcurrentHashMap<>(256);
    
    /**
     * 添加解析器
     */
    public HandlerMethodArgumentResolverComposite addResolvers(
            HandlerMethodArgumentResolver... resolvers) {
        if (resolvers != null) {
            for (HandlerMethodArgumentResolver resolver : resolvers) {
                this.resolvers.add(resolver);
            }
        }
        return this;
    }
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return getResolver(parameter) != null;
    }
    
    @Override
    @Nullable
    public Object resolveArgument(MethodParameter parameter,
                                 @Nullable ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest,
                                 @Nullable WebDataBinderFactory binderFactory) throws Exception {
        HandlerMethodArgumentResolver resolver = getResolver(parameter);
        if (resolver == null) {
            throw new IllegalArgumentException(
                "Unknown parameter type [" + parameter.getParameterType() + "]");
        }
        return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
    }
    
    /**
     * 获取支持该参数的解析器(带缓存)
     */
    @Nullable
    private HandlerMethodArgumentResolver getResolver(MethodParameter parameter) {
        // 先从缓存获取
        HandlerMethodArgumentResolver resolver = resolverCache.get(parameter);
        if (resolver != null) {
            return resolver;
        }
        
        // 遍历查找
        for (HandlerMethodArgumentResolver r : this.resolvers) {
            if (r.supportsParameter(parameter)) {
                resolverCache.put(parameter, r);
                return r;
            }
        }
        
        return null;
    }
}

2.4 WebDataBinder与类型转换体系

WebDataBinder是参数绑定的核心,负责将请求参数转换为Java对象:
DataBinder
+bind(PropertyValues)
+validate()
+getBindingResult()
WebDataBinder
+bind(jakarta.servlet.ServletRequest)
+checkFieldErrors()
ServletRequestDataBinder
+bind(ServletRequest)
ExtendedServletRequestDataBinder

java 复制代码
// org.springframework.web.bind.WebDataBinder
public class WebDataBinder {
    
    // 绑定目标对象
    private Object target;
    
    // 对象名称
    private String objectName;
    
    // 绑定结果
    private BindingResult bindingResult;
    
    // 类型转换服务
    private ConversionService conversionService;
    
    // 字段编辑器
    private final Map<Class<?>, PropertyEditor> customEditors = new LinkedHashMap<>();
    
    // 字段编辑器覆盖
    private final Map<Class<?>, PropertyEditor> customEditorForPath = new LinkedHashMap<>();
    
    /**
     * 绑定请求参数到目标对象
     */
    public void bind(ServletRequest request) {
        // 1. 获取所有请求参数
        MutablePropertyValues mpvs = new MutablePropertyValues(request);
        
        // 2. 解析 multipart 数据
        if (request instanceof MultipartRequest multipartRequest) {
            bindMultipart(multipartRequest, mpvs);
        }
        
        // 3. 添加请求参数到绑定结果
        addBindValues(mpvs, request);
        
        // 4. 执行绑定
        doBind(mpvs);
    }
    
    /**
     * 执行实际绑定
     */
    protected void doBind(MutablePropertyValues mpvs) {
        // 调用DataBinder的bind方法
        applyPropertyValues(mpvs);
    }
    
    /**
     * 应用属性值
     */
    protected void applyPropertyValues(MutablePropertyValues mpvs) {
        try {
            // 获取绑定目标
            getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), 
                isIgnoreInvalidFields());
        } catch (Exception ex) {
            // 收集绑定错误
        }
    }
}

2.5 DataBinder类型转换核心

java 复制代码
// org.springframework.validation.DataBinder
public class DataBinder {
    
    /**
     * 核心绑定方法
     */
    public void bind(PropertyValues pvs) {
        // 1. 扩展属性值
        MutablePropertyValues pvsToUse = new MutablePropertyValues();
        
        // 2. 处理DirectFieldAccessor和BeanWrapper的绑定
        doBind(pvsToUse);
    }
    
    protected void doBind(MutablePropertyValues pvs) {
        // 检查字段错误
        checkFieldErrors(pvsToUse);
        
        // 应用属性值到目标对象
        applyPropertyValues(pvsToUse);
    }
    
    /**
     * 验证绑定结果
     */
    public void validate() {
        // 获取验证器并执行验证
        for (Validator validator : getValidators()) {
            validator.validate(getTarget(), getBindingResult());
        }
    }
    
    /**
     * 使用ConversionService进行类型转换
     */
    protected Object convertIfNecessary(...) throws ConversionException {
        if (this.conversionService != null) {
            return this.conversionService.convert(value, typeDescriptor, typeDescriptor);
        }
        // 使用PropertyEditor
        ...
    }
}

2.6 ConversionService与类型转换器

java 复制代码
// org.springframework.core.convert.ConversionService
public interface ConversionService {
    boolean canConvert(Class<?> sourceType, Class<?> targetType);
    <T> T convert(Object source, Class<T> targetType);
}

// Spring Boot自动配置会注册大量转换器:
// - StringToBooleanConverter
// - StringToEnumConverterFactory
// - NumberToNumberConverterFactory
// - StringToDateConverterFactory
// - CollectionToCollectionConverter
// - ArrayToArrayConverter

2.7 ModelAndViewContainer状态容器

ModelAndViewContainer是请求处理过程中的状态容器,贯穿整个处理流程:

java 复制代码
// org.springframework.web.method.support.ModelAndViewContainer
public class ModelAndViewContainer {
    
    // 视图对象(优先级高于viewName)
    @Nullable
    private View view;
    
    // 视图名称
    @Nullable
    private String viewName;
    
    // Model数据
    private ModelMap model = new LinkedHashMap<>();
    
    // 请求是否已处理(用于@ResponseBody等无视图场景)
    private boolean requestHandled = false;
    
    // 重定向模型属性
    private ModelMap redirectModel = new LinkedHashMap<>();
    
    // 是否使用重定向模型
    private boolean redirectModelScenario = false;
    
    // 默认模型状态
    private ModelMap defaultModel = new LinkedHashMap<>();
    
    public ModelAndViewContainer() {
        this.model = this.defaultModel;
    }
    
    // 设置视图名
    public void setViewName(@Nullable String viewName) {
        this.viewName = viewName;
    }
    
    // 添加模型属性
    public ModelAndViewContainer addAttribute(String name, @Nullable Object value) {
        getModel().put(name, value);
        return this;
    }
    
    public ModelAndViewContainer addAllAttributes(
            @Nullable Map<String, ?> attributes) {
        if (attributes != null) {
            getModel().putAll(attributes);
        }
        return this;
    }
    
    // 获取合并后的模型
    public ModelMap getModel() {
        if (useDefaultModel()) {
            return this.defaultModel;
        } else {
            if (this.redirectModel == null) {
                this.redirectModel = new LinkedHashMap<>();
            }
            return this.redirectModel;
        }
    }
    
    // 是否使用默认模型
    private boolean useDefaultModel() {
        return (!this.redirectModelScenario || this.redirectModel.isEmpty());
    }
}

2.8 ModelFactory模型工厂

ModelFactory负责初始化模型属性和处理@ModelAttribute注解的方法:

java 复制代码
// org.springframework.web.method.annotation.ModelFactory
public class ModelFactory {
    
    private final ModelAndViewContainer mavContainer;
    private final WebDataBinderFactory binderFactory;
    private final SessionAttributesHandler sessionAttributesHandler;
    
    // 初始化模型(在方法执行前调用)
    public void initModel(NativeWebRequest request, 
                         ModelAndViewContainer container,
                         HandlerMethod handlerMethod) throws Exception {
        
        // 1. 从Session加载@SessionAttributes的属性
        Map<String, ?> sessionAttributes = this.sessionAttributesHandler
            .retrieveAttributes(request);
        container.addAllAttributes(sessionAttributes);
        
        // 2. 调用@ModelAttribute注解的方法
        for (HandlerMethod attributeMethod : getModelAttributeMethods()) {
            Object attribute = attributeMethod.invokeForRequest(request, container);
            if (attribute != null) {
                String attrName = getAttributeName(attributeMethod);
                boolean bindingDisabled = 
                    getBindingDisabled(attributeMethod);
                if (!bindingDisabled) {
                    container.addAttribute(attrName, attribute);
                }
            }
        }
        
        // 3. 绑定SessionAttributes
        this.sessionAttributesHandler.storeAttributes(request, container.getModel());
    }
    
    // 更新模型(在方法执行后调用)
    public void updateModel(NativeWebRequest request, 
                           ModelAndViewContainer container) {
        container.setRedirectModel(this.redirectModel);
        
        if (container.getRedirectModel() != null) {
            // 处理重定向场景的模型
            Map<String, ?> redirectAttributes = container.getRedirectModel();
            // ...
        }
    }
}

3. 常用参数解析器详解

3.1 参数解析器总览

对应解析器
参数来源
路径变量@PathVariable
请求参数@RequestParam
请求体@RequestBody
请求头@RequestHeader
Cookie@CookieValue
Session@SessionAttribute
Model/ModelMap
@ModelAttribute
Errors/BindingResult
PathVariableMethodArgumentResolver
RequestParamMethodArgumentResolver
RequestResponseBodyMethodProcessor
RequestHeaderMethodArgumentResolver
CookieValueMethodArgumentResolver
SessionAttributeMethodArgumentResolver
ModelMethodProcessor
ModelAttributeMethodProcessor
ErrorsMethodArgumentResolver

3.2 AbstractNamedValueMethodArgumentResolver父类

PathVariable、RequestParam、RequestHeader等都继承自这个父类:

java 复制代码
// org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver
public abstract class AbstractNamedValueMethodArgumentResolver 
        implements HandlerMethodArgumentResolver {
    
    /**
     * NamedValueInfo表示一个命名值(如@RequestParam("name"))
     */
    protected static class NamedValueInfo {
        private final String name;
        private final boolean required;
        private final Object defaultValue;
        
        public NamedValueInfo(String name, boolean required, Object defaultValue) {
            this.name = name;
            this.required = required;
            this.defaultValue = defaultValue;
        }
    }
    
    @Override
    @Nullable
    public final Object resolveArgument(MethodParameter parameter,
                                       @Nullable ModelAndViewContainer mavContainer,
                                       NativeWebRequest webRequest,
                                       @Nullable WebDataBinderFactory binderFactory) 
            throws Exception {
        
        // 1. 获取命名值信息
        NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
        
        // 2. 解析参数值
        Object arg = resolveName(namedValueInfo.name, parameter, webRequest);
        
        // 3. 处理默认值
        if (arg == null) {
            if (namedValueInfo.defaultValue != null) {
                arg = namedValueInfo.defaultValue;
                // 处理默认值中的特殊值(如"#{systemProperties.myProp}")
                if ("".equals(namedValueInfo.defaultValue)) {
                    arg = "";
                }
            }
        }
        
        // 4. 处理必需参数
        if (arg == null && namedValueInfo.required) {
            throw new MissingServletRequestParameterException(
                namedValueInfo.name, 
                parameter.getNestedParameterType().getSimpleName());
        }
        
        // 5. 类型转换
        if (binderFactory != null) {
            WebDataBinder binder = binderFactory.createBinder(
                webRequest, null, namedValueInfo.name);
            arg = binder.convertIfNecessary(arg, 
                parameter.getNestedParameterType(), parameter);
        }
        
        return arg;
    }
    
    /**
     * 获取命名值信息
     */
    protected NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
        // 由子类实现
        return new NamedValueInfo("", false, null);
    }
    
    /**
     * 解析参数名
     */
    @Nullable
    protected abstract Object resolveName(String name, 
                                          MethodParameter parameter,
                                          NativeWebRequest webRequest) throws Exception;
}

3.3 PathVariableMethodArgumentResolver

处理@PathVariable注解的参数:

java 复制代码
// org.springframework.web.servlet.tag.form.PathVariableMethodArgumentResolver
public class PathVariableMethodArgumentResolver extends 
        AbstractNamedValueMethodArgumentResolver {
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(PathVariable.class);
    }
    
    @Override
    protected NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
        PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);
        Assert.state(ann != null, "No PathVariable annotation");
        
        String name = ann.value();
        if (StringUtils.isEmpty(name)) {
            // 如果未指定参数名,使用方法参数名
            name = parameter.getParameterName();
        }
        
        return new NamedValueInfo(name, false, null);
    }
    
    @Override
    @Nullable
    protected Object resolveName(String name, MethodParameter parameter,
                                NativeWebRequest webRequest) throws Exception {
        // 从请求属性中获取URI模板变量
        Map<String, String> uriTemplateVars = 
            (Map<String, String>) webRequest.getAttribute(
                HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, 
                RequestAttributes.SCOPE_REQUEST);
        
        return (uriTemplateVars != null ? uriTemplateVars.get(name) : null);
    }
}

3.4 RequestParamMethodArgumentResolver

处理@RequestParam注解的参数,同时也处理简单类型的参数:

java 复制代码
// org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
public class RequestParamMethodArgumentResolver extends 
        AbstractNamedValueMethodArgumentResolver {
    
    private final boolean useDefaultResolution;
    
    public RequestParamMethodArgumentResolver(
            List<HandlerMethodArgumentResolver> resolvers,
            boolean useDefaultResolution) {
        this.useDefaultResolution = useDefaultResolution;
    }
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.hasParameterAnnotation(RequestParam.class)) {
            return true;
        } else if (useDefaultResolution && 
            BeanUtils.isSimpleProperty(parameter.getParameterType())) {
            // 简单类型(基本类型、String、Number等)自动解析
            return true;
        }
        return false;
    }
    
    @Override
    protected NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
        RequestParam ann = parameter.getParameterAnnotation(RequestParam.class);
        String name = (ann != null ? ann.value() : null);
        boolean required = (ann != null ? ann.required() : false);
        Object defaultValue = (ann != null ? ann.defaultValue() : null);
        
        if (StringUtils.isEmpty(name)) {
            name = parameter.getParameterName();
        }
        
        return new NamedValueInfo(name, required, 
            defaultValue != RequestParam.DEFAULT_NONE ? defaultValue : null);
    }
    
    @Override
    @Nullable
    protected Object resolveName(String name, MethodParameter parameter,
                                NativeWebRequest webRequest) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        
        // multipart请求处理
        if (request instanceof MultipartRequest multipartRequest) {
            MultipartFile file = multipartRequest.getFile(name);
            if (file != null) {
                return file;
            }
        }
        
        // 普通请求参数
        String[] values = request.getParameterValues(name);
        if (values != null) {
            Class<?> paramType = parameter.getParameterType();
            if (paramType.isArray()) {
                return convertArrayParameter(paramType, values);
            }
            return (values.length > 0 ? values[0] : null);
        }
        
        return null;
    }
    
    private Object convertArrayParameter(Class<?> paramType, String[] values) {
        // 数组类型转换
        Class<?> componentType = paramType.getComponentType();
        Object array = Array.newInstance(componentType, values.length);
        for (int i = 0; i < values.length; i++) {
            Object converted = ...; // 类型转换
            Array.set(array, i, converted);
        }
        return array;
    }
}

3.5 RequestHeaderMethodArgumentResolver

处理@RequestHeader注解的参数:

java 复制代码
// org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver
public class RequestHeaderMethodArgumentResolver extends 
        AbstractNamedValueMethodArgumentResolver {
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(RequestHeader.class);
    }
    
    @Override
    protected NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
        RequestHeader ann = parameter.getParameterAnnotation(RequestHeader.class);
        String name = (ann != null ? ann.value() : null);
        boolean required = (ann != null ? ann.required() : false);
        Object defaultValue = (ann != null ? ann.defaultValue() : null);
        
        if (StringUtils.isEmpty(name)) {
            name = parameter.getParameterName();
        }
        
        return new NamedValueInfo(name, required, 
            defaultValue != RequestHeader.DEFAULT_NONE ? defaultValue : null);
    }
    
    @Override
    @Nullable
    protected Object resolveName(String name, MethodParameter parameter,
                                NativeWebRequest webRequest) throws Exception {
        // 从请求头中获取
        String[] headerValues = webRequest.getHeaderValues(name);
        if (headerValues != null) {
            Class<?> paramType = parameter.getNestedParameterType();
            
            // Map<String, String>类型,返回所有请求头
            if (Map.class.isAssignableFrom(paramType)) {
                HttpServletRequest request = 
                    webRequest.getNativeRequest(HttpServletRequest.class);
                return new HashMap<>(Collections.list(request.getHeaderNames())
                    .stream().collect(Collectors.toMap(
                        h -> h, 
                        h -> request.getHeader(h))));
            }
            
            // 数组类型
            if (paramType.isArray()) {
                return headerValues;
            }
            
            // 单值
            return (headerValues.length > 0 ? headerValues[0] : null);
        }
        
        return null;
    }
}

3.6 CookieValueMethodArgumentResolver

处理@CookieValue注解的参数:

java 复制代码
// org.springframework.web.method.annotation.CookieValueMethodArgumentResolver
public class CookieValueMethodArgumentResolver extends 
        AbstractNamedValueMethodArgumentResolver {
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(CookieValue.class);
    }
    
    @Override
    protected NamedValueInfo getNamedValueInfo(MethodParameter parameter) {
        CookieValue ann = parameter.getParameterAnnotation(CookieValue.class);
        String name = (ann != null ? ann.value() : null);
        boolean required = (ann != null ? ann.required() : false);
        Object defaultValue = (ann != null ? ann.defaultValue() : null);
        
        if (StringUtils.isEmpty(name)) {
            name = parameter.getParameterName();
        }
        
        return new NamedValueInfo(name, required,
            defaultValue != CookieValue.DEFAULT_NONE ? defaultValue : null);
    }
    
    @Override
    @Nullable
    protected Object resolveName(String name, MethodParameter parameter,
                                NativeWebRequest webRequest) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        
        // 获取Cookie
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    // 类型转换
                    String value = cookie.getValue();
                    if (parameter.getNestedParameterType().equals(Cookie.class)) {
                        return cookie;
                    }
                    // 字符串或其他类型转换
                    return value;
                }
            }
        }
        
        return null;
    }
}

3.7 ModelAttributeMethodProcessor

处理@ModelAttribute注解的参数以及命令表单对象:

java 复制代码
// org.springframework.web.method.annotation.ModelAttributeMethodProcessor
public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver {
    
    private final boolean annotationNotRequired;
    
    public ModelAttributeMethodProcessor(boolean annotationNotRequired) {
        this.annotationNotRequired = annotationNotRequired;
    }
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 支持@ModelAttribute注解的参数
        if (parameter.hasParameterAnnotation(ModelAttribute.class)) {
            return true;
        }
        // 或者启用了无注解参数处理,且参数不是简单类型
        return (this.annotationNotRequired && 
            !BeanUtils.isSimpleProperty(parameter.getParameterType()));
    }
    
    @Override
    @Nullable
    public Object resolveArgument(MethodParameter parameter,
                                 @Nullable ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest,
                                 @Nullable WebDataBinderFactory binderFactory) 
            throws Exception {
        
        String name = getNameForParameter(parameter);
        Object attribute = null;
        
        // 1. 先从模型中获取
        if (mavContainer.containsAttribute(name)) {
            attribute = mavContainer.getModel().get(name);
        } else {
            // 2. 创建新实例
            try {
                attribute = BeanUtils.instantiateClass(parameter.getParameterType());
            } catch (Exception ex) {
                throw new IllegalStateException("Cannot instantiate");
            }
        }
        
        if (binderFactory != null) {
            // 3. 创建DataBinder并绑定
            WebDataBinder binder = binderFactory.createBinder(
                webRequest, attribute, name);
            
            // 4. 绑定请求参数
            binder.bind(mavContainer);
            
            // 5. 验证
            binder.validate();
            
            // 6. 获取绑定结果
            BindingResult bindingResult = binder.getBindingResult();
            mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, 
                bindingResult);
        }
        
        return attribute;
    }
    
    /**
     * 获取参数名称
     */
    protected String getNameForParameter(MethodParameter parameter) {
        ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
        if (ann != null && !StringUtils.isEmpty(ann.value())) {
            return ann.value();
        }
        // 使用参数类型名(首字母小写)
        return Introspector.decapitalize(parameter.getParameterType().getSimpleName());
    }
}

3.8 ErrorsMethodArgumentResolver

处理BindingResultErrors参数,用于获取参数绑定和验证结果:

java 复制代码
// org.springframework.web.bind.support.ErrorsMethodArgumentResolver
public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolver {
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> paramType = parameter.getParameterType();
        return BindingResult.class.isAssignableFrom(paramType);
    }
    
    @Override
    @Nullable
    public Object resolveArgument(MethodParameter parameter,
                                 @Nullable ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest,
                                 @Nullable WebDataBinderFactory binderFactory) 
            throws Exception {
        
        String modelName = getModelName(parameter);
        
        // 从模型中获取BindingResult
        Object bindingResult = mavContainer.getModel().get(
            BindingResult.MODEL_KEY_PREFIX + modelName);
        
        if (bindingResult == null) {
            throw new IllegalStateException(
                "BindingResult not found for attribute: " + modelName);
        }
        
        return bindingResult;
    }
    
    private String getModelName(MethodParameter parameter) {
        int index = parameter.getParameterIndex();
        // 找到前一个参数(通常是命令对象)
        MethodParameter modelParam = new MethodParameter(parameter.getMethod(), index - 1);
        String name = getNameForParameter(modelParam);
        return name;
    }
}

3.9 RequestResponseBodyMethodProcessor

处理@RequestBody@ResponseBody注解:

java 复制代码
// org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
public class RequestResponseBodyMethodProcessor extends 
        AbstractMessageConverterMethodArgumentResolver {
    
    public RequestResponseBodyMethodProcessor(
            List<HttpMessageConverter<?>> converters) {
        super(converters);
    }
    
    public RequestResponseBodyMethodProcessor(
            List<HttpMessageConverter<?>> converters,
            @Nullable ContentNegotiationStrategy contentNegotiation) {
        super(converters, contentNegotiation);
    }
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(RequestBody.class);
    }
    
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        return (returnType.hasMethodAnnotation(ResponseBody.class) ||
            (returnType.getContainingClass().isAnnotationPresent(
                RestController.class)));
    }
    
    @Override
    @Nullable
    public Object resolveArgument(MethodParameter parameter,
                                 @Nullable ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest,
                                 @Nullable WebDataBinderFactory binderFactory) 
            throws Exception {
        
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        
        // 使用MessageConverter读取请求体
        Object body = readWithMessageConverters(webRequest, parameter, 
            parameter.getParameterType());
        
        // 验证
        if (binderFactory != null) {
            WebDataBinder binder = binderFactory.createBinder(
                webRequest, null, parameter.getParameterName());
            binder.validate(body, parameter);
        }
        
        return body;
    }
    
    @Override
    public void handleReturnValue(@Nullable Object returnValue,
                                 MethodParameter returnType,
                                 ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest) throws Exception {
        // 1. 标记请求已处理
        mavContainer.setRequestHandled(true);
        
        HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
        
        // 2. 使用MessageConverter写出响应
        writeWithMessageConverters(returnValue, returnType, servletRequest, response);
    }
}

3.10 参数解析决策流程











Controller方法参数
有PathVariable
PathVariableResolver
有RequestParam
RequestParamResolver
有RequestBody
RequestBodyResolver
有ModelAttribute
ModelAttributeResolver
是简单类型
RequestParamResolver
ModelAttributeResolver
WebDataBinder类型转换


4. 返回值处理器详解

4.1 ReturnValueHandler体系

<<interface>>
HandlerMethodReturnValueHandler
+supportsReturnType(returnType)
+handleReturnValue()
ModelAndViewMethodReturnValueHandler
ModelMethodProcessor
ViewNameMethodReturnValueHandler
RequestResponseBodyMethodProcessor
HttpEntityMethodProcessor
DeferredResultMethodReturnValueHandler
StreamingResponseBodyMethodReturnValueHandler

4.2 HandlerMethodReturnValueHandlerComposite

java 复制代码
// org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite
public class HandlerMethodReturnValueHandlerComposite 
        implements HandlerMethodReturnValueHandler {
    
    private final List<HandlerMethodReturnValueHandler> handlers = 
        new ArrayList<>();
    
    public HandlerMethodReturnValueHandlerComposite addHandlers(
            List<? extends HandlerMethodReturnValueHandler> handlers) {
        if (handlers != null) {
            this.handlers.addAll(handlers);
        }
        return this;
    }
    
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        return getReturnValueHandler(returnType) != null;
    }
    
    @Override
    public void handleReturnValue(@Nullable Object returnValue,
                                 MethodParameter returnType,
                                 ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest) throws Exception {
        
        HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
        if (handler == null) {
            throw new IllegalArgumentException(
                "Unknown return value type: [" + returnType.getParameterType() + "]");
        }
        
        handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }
    
    @Nullable
    private HandlerMethodReturnValueHandler getReturnValueHandler(
            MethodParameter returnType) {
        for (HandlerMethodReturnValueHandler handler : this.handlers) {
            if (handler.supportsReturnType(returnType)) {
                return handler;
            }
        }
        return null;
    }
}

4.3 ModelAndViewMethodReturnValueHandler

处理返回ModelAndView的情况:

java 复制代码
// org.springframework.web.method.support.ModelAndViewMethodReturnValueHandler
public class ModelAndViewMethodReturnValueHandler 
        implements HandlerMethodReturnValueHandler {
    
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        Class<?> type = returnType.getParameterType();
        return ModelAndView.class.isAssignableFrom(type);
    }
    
    @Override
    public void handleReturnValue(@Nullable Object returnValue,
                                 MethodParameter returnType,
                                 ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest) throws Exception {
        
        if (returnValue == null) {
            mavContainer.setRequestHandled(true);
            return;
        }
        
        ModelAndView mav = (ModelAndView) returnValue;
        String viewName = mav.getViewName();
        
        if (viewName != null) {
            mavContainer.setViewName(viewName);
        } else {
            View view = mav.getView();
            if (view == null) {
                throw new IllegalStateException("No view or viewName");
            }
            mavContainer.setView(view);
        }
        
        // 合并模型数据
        mavContainer.addAllAttributes(mav.getModel());
    }
}

4.4 ViewNameMethodReturnValueHandler

处理返回视图名称String的情况:

java 复制代码
// org.springframework.web.method.support.ViewNameMethodReturnValueHandler
public class ViewNameMethodReturnValueHandler 
        implements HandlerMethodReturnValueHandler {
    
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        Class<?> type = returnType.getParameterType();
        return (type.equals(String.class) || 
            (type.equals(void.class) && 
             returnType.getMethodAnnotation(ResponseStatus.class) != null));
    }
    
    @Override
    public void handleReturnValue(@Nullable Object returnValue,
                                 MethodParameter returnType,
                                 ModelAndViewContainer mavContainer,
                                 NativeWebRequest webRequest) throws Exception {
        
        String viewName = (String) returnValue;
        
        // 处理重定向前缀
        if (viewName != null && viewName.startsWith("redirect:")) {
            mavContainer.setRedirectModel(...);
        }
        
        mavContainer.setViewName(viewName);
    }
}

4.5 返回值处理决策流程

ModelAndView
String
void
ResponseBody
HttpEntity
DeferredResult
Model
Controller返回值
返回类型
ModelAndViewHandler
ViewNameHandler
ViewNameHandler
ResponseBodyHandler
HttpEntityHandler
DeferredResultHandler
ModelHandler
设置View和Model
直接写入HTTP响应
异步处理

4.6 ResponseBody注解处理

@ResponseBody的返回值处理会跳过视图解析,直接将数据写入HTTP响应:

java 复制代码
// 处理流程:
// 1. Controller返回 User对象
// 2. RequestResponseBodyMethodProcessor.handleReturnValue()
// 3. mavContainer.setRequestHandled(true)  // 标记请求已处理
// 4. 使用MessageConverter将对象序列化为JSON/XML
// 5. 写入HttpServletResponse

5. 拦截器链执行机制

5.1 HandlerExecutionChain源码

java 复制代码
// org.springframework.web.servlet.HandlerExecutionChain
public class HandlerExecutionChain {
    
    private static final Log logger = LogFactory.getLog(
        HandlerExecutionChain.class);
    
    private final Object handler;  // 处理器
    private final List<HandlerInterceptor> interceptorList = new ArrayList<>(4);
    
    // preHandle的执行索引,用于afterCompletion正确清理
    private int interceptorIndex = -1;
    
    public HandlerExecutionChain(Object handler) {
        if (handler instanceof HandlerExecutionChain) {
            HandlerExecutionChain chain = (HandlerExecutionChain) handler;
            this.handler = chain.getHandler();
            this.interceptorList.addAll(chain.interceptorList);
        } else {
            this.handler = handler;
        }
    }
    
    /**
     * 添加拦截器
     */
    public void addInterceptor(HandlerInterceptor interceptor) {
        this.interceptorList.add(interceptor);
    }
    
    /**
     * 应用前置拦截器
     * 返回false表示中断处理链
     */
    boolean applyPreHandle(HttpServletRequest request,
                          HttpServletResponse response) throws Exception {
        for (int i = 0; i < this.interceptorList.size(); i++) {
            HandlerInterceptor interceptor = this.interceptorList.get(i);
            
            boolean result = interceptor.preHandle(request, response, this.handler);
            
            if (!result) {
                // 返回false,触发已完成拦截器的afterCompletion
                triggerAfterCompletion(request, response, null);
                return false;
            }
            
            this.interceptorIndex = i;
        }
        
        return true;
    }
    
    /**
     * 应用后置拦截器(逆序)
     */
    void applyPostHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        @Nullable ModelAndView mav) throws Exception {
        // 逆序遍历
        for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = this.interceptorList.get(i);
            interceptor.postHandle(request, response, this.handler, mav);
        }
    }
    
    /**
     * 触发完成回调
     */
    void triggerAfterCompletion(HttpServletRequest request,
                               HttpServletResponse response,
                               @Nullable Exception ex) {
        for (int i = this.interceptorIndex; i >= 0; i--) {
            HandlerInterceptor interceptor = this.interceptorList.get(i);
            try {
                interceptor.afterCompletion(request, response, this.handler, ex);
            } catch (Throwable t) {
                logger.error("HandlerInterceptor.afterCompletion threw", t);
            }
        }
    }
}

5.2 拦截器执行顺序

Controller Interceptor3 Interceptor2 Interceptor1 DispatcherServlet Controller Interceptor3 Interceptor2 Interceptor1 DispatcherServlet preHandle() [index=0] true preHandle() [index=1] true preHandle() [index=2] true handle() postHandle() [逆序] postHandle() postHandle() afterCompletion() [逆序] afterCompletion() afterCompletion()

5.3 preHandle返回false的处理

当某个拦截器的preHandle返回false时:
Interceptor2 Interceptor1 DispatcherServlet Interceptor2 Interceptor1 DispatcherServlet 只调用已成功preHandle的拦截器 preHandle() true preHandle() false afterCompletion(ex=null)

5.4 拦截器接口定义

java 复制代码
// org.springframework.web.servlet.HandlerInterceptor
public interface HandlerInterceptor {
    
    /**
     * 前置处理
     * @return true继续执行,false中断处理
     */
    default boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        return true;
    }
    
    /**
     * 后置处理(在视图渲染之前)
     */
    default void postHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler,
                            @Nullable ModelAndView modelAndView) throws Exception {
    }
    
    /**
     * 完成处理(始终执行,无论成功或异常)
     */
    default void afterCompletion(HttpServletRequest request,
                                 HttpServletResponse response,
                                 Object handler,
                                 @Nullable Exception ex) throws Exception {
    }
}

5.5 拦截器配置示例

java 复制代码
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 认证拦截器
        registry.addInterceptor(new AuthInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/login", "/public/**");
        
        // 日志拦截器
        registry.addInterceptor(new LoggingInterceptor())
            .addPathPatterns("/**");
        
        // 性能监控拦截器
        registry.addInterceptor(new PerformanceInterceptor())
            .addPathPatterns("/api/**");
    }
}

// 拦截器实现示例
public class AuthInterceptor extends HandlerInterceptorAdapter {
    
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        // 检查认证状态
        if (!isAuthenticated(request)) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request,
                          HttpServletResponse response,
                          Object handler,
                          ModelAndView modelAndView) throws Exception {
        // 后置处理
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request,
                               HttpServletResponse response,
                               Object handler,
                               Exception ex) throws Exception {
        // 清理资源
    }
}

5.6 MappedInterceptor精确匹配

java 复制代码
// MappedInterceptor支持URL模式匹配
@Configuration
public class WebMvcConfig {
    @Bean
    public MappedInterceptor adminInterceptor() {
        String[] includePatterns = {"/admin/**"};
        String[] excludePatterns = {"/admin/login"};
        
        return new MappedInterceptor(includePatterns, excludePatterns, 
            new AdminInterceptor());
    }
}

总结

HandlerAdapter职责

方法 说明
supports() 判断是否支持该处理器
handle() 执行处理器,返回ModelAndView
getLastModified() HTTP缓存支持

参数解析关键点

注解 解析器 说明
@PathVariable PathVariableMethodArgumentResolver 路径变量
@RequestParam RequestParamMethodArgumentResolver 请求参数
@RequestBody RequestResponseBodyMethodProcessor 请求体JSON
@RequestHeader RequestHeaderMethodArgumentResolver 请求头
@CookieValue CookieValueMethodArgumentResolver Cookie值
@ModelAttribute ModelAttributeMethodProcessor 模型属性

返回值处理关键点

返回类型 处理器 说明
ModelAndView ModelAndViewMethodReturnValueHandler 模型和视图
String ViewNameMethodReturnValueHandler 视图名
void ViewNameMethodReturnValueHandler 无视图
@ResponseBody RequestResponseBodyMethodProcessor 直接响应
Model/ModelMap ModelMethodProcessor 模型数据

拦截器执行顺序

阶段 执行顺序 说明
preHandle 正序 任何一个返回false都会中断
postHandle 逆序 在视图渲染前执行
afterCompletion 逆序 始终执行,用于清理

设计模式

  1. 适配器模式:HandlerAdapter将不同类型的Handler统一成相同接口
  2. 责任链模式:拦截器链按顺序执行
  3. 策略模式:ArgumentResolver/ReturnValueHandler支持多种实现
  4. 组合模式:HandlerMethodArgumentResolverComposite组合多个解析器

下篇预告

第三篇将讲解视图渲染与异常处理,包括:

  • ViewResolver体系与视图解析
  • HandlerExceptionResolver异常处理链
  • LocaleResolver国际化处理
  • FlashMap重定向数据传递
  • 文件上传Multipart处理
相关推荐
SamDeepThinking5 小时前
一个跑了三年没出过问题的系统,我是怎么设计的
java·后端·架构
写了20年代码的老程序员6 小时前
做接口开发最烦的,不是 JSON 深,而是它打断你思考业务
后端
逸Y 仙X6 小时前
文章十七:ElasticSearch get\search查询相关参数
java·大数据·elasticsearch·搜索引擎·全文检索
Walter先生6 小时前
Python 行情数据清洗实战:Z-Score、MAD 与分位数过滤的异常值检测
后端·websocket·架构·实时行情数据源·美股行情api
Cache技术分享6 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
前端·后端
leonidZhao6 小时前
Java25新特性:JFR CPU时间性能分析
java
千码君20166 小时前
flutter: 分享一下基于trae cn 构建的过程
java·vscode·flutter·kotlin·trae
山间小僧6 小时前
「AI学习笔记」万恶之源《Attention is all you need》
后端·openai·ai编程