设为首页 加入收藏

TOP

HandlerMethodArgumentResolver(一):Controller方法入参自动封装器【享学Spring MVC】(一)
2019-09-17 16:28:33 】 浏览:100
Tags:HandlerMethodArgumentResolver Controller 方法 自动 封装 享学 Spring MVC

每篇一句

你的工作效率高,老板会认为你强度不够。你代码bug多,各种生产环境救火,老板会觉得你是团队的核心成员。

前言

在享受Spring MVC带给你便捷的时候,你是否曾经这样疑问过:Controllerhandler方法参数能够自动完成封装(有时即使没有@PathVariable@RequestParam@RequestBody等注解都可),甚至在方法参数任意位置写HttpServletRequestHttpSessionWriter...等类型的参数,它自动就有值了便可直接使用。
对此你是否想问一句:Spring MVC它是怎么办到的?那么本文就揭开它的神秘面纱,还你一片"清白"。

Spring MVC作为一个最为流行的web框架,早早已经成为了实际意义上的标准化(框架),特别是随着Struts2的突然崩塌,Spring MVC几乎一骑绝尘,因此深入了解它有着深远的意义

Spring MVC它只需要区区几个注解就能够让一个普通的java方法成为一个Handler处理器,并且还能有自动参数封装、返回值视图处理/渲染等一系列强大功能,让coder的精力更加的聚焦在自己的业务。

像JSF、Google Web Toolkit、Grails Framework等web框架至少我是没有用过的。
这里有个轻量级的web框架:Play Framework设计上我个人觉得还挺有意思,有兴趣的可以玩玩

HandlerMethodArgumentResolver

策略接口:用于在给定请求的上下文中将方法参数解析为参数值。简单的理解为:它负责处理你Handler方法里的所有入参:包括自动封装、自动赋值、校验等等。有了它才能会让Spring MVC处理入参显得那么高级、那么自动化。
Spring MVC内置了非常非常多的实现,当然若还不能满足你的需求,你依旧可以自定义和自己注册,后面我会给出自定义的示例。

有个形象的公式:HandlerMethodArgumentResolver = HandlerMethod + Argument(参数) + Resolver(解析器)
解释为:它是HandlerMethod方法的解析器,将HttpServletRequest(header + body 中的内容)解析为HandlerMethod方法的参数(method parameters)

// @since 3.1   HandlerMethod 方法中 参数解析器
public interface HandlerMethodArgumentResolver {

    // 判断 HandlerMethodArgumentResolver 是否支持 MethodParameter
    // (PS: 一般都是通过 参数上面的注解|参数的类型)
    boolean supportsParameter(MethodParameter parameter);
    
    // 从NativeWebRequest中获取数据,ModelAndViewContainer用来提供访问Model
    // MethodParameter parameter:请求参数
    // WebDataBinderFactory用于创建一个WebDataBinder用于数据绑定、校验
    @Nullable
    Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}

基于这个接口的处理器实现类不可谓不丰富,非常之多。我截图如下:
在这里插入图片描述
因为子类众多,所以我分类进行说明。我把它分为四类进行描述:

  1. 基于Name
  2. 数据类型是Map
  3. 固定参数类型
  4. 基于ContentType的消息转换器

第一类:基于Name

从URI(路径变量)、HttpServletRequest、HttpSession、Header、Cookie...等中根据名称key来获取值

这类处理器所有的都是基于抽象类AbstractNamedValueMethodArgumentResolver来实现,它是最为重要的分支(分类)

// @since 3.1  负责从路径变量、请求、头等中拿到值。(都可以指定name、required、默认值等属性)
// 子类需要做如下事:获取方法参数的命名值信息、将名称解析为参数值
// 当需要参数值时处理缺少的参数值、可选地处理解析值

//特别注意的是:默认值可以使用${}占位符,或者SpEL语句#{}是木有问题的
public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Nullable
    private final ConfigurableBeanFactory configurableBeanFactory;
    @Nullable
    private final BeanExpressionContext expressionContext;
    private final Map<MethodParameter, NamedValueInfo> namedValueInfoCache = new ConcurrentHashMap<>(256);

    public AbstractNamedValueMethodArgumentResolver() {
        this.configurableBeanFactory = null;
        this.expressionContext = null;
    }
    public AbstractNamedValueMethodArgumentResolver(@Nullable ConfigurableBeanFactory beanFactory) {
        this.configurableBeanFactory = beanFactory;
        // 默认是RequestScope
        this.expressionContext = (beanFactory != null ? new BeanExpressionContext(beanFactory, new RequestScope()) : null);
    }

    // protected的内部类  所以所有子类(注解)都是用友这三个属性值的
    protected static class NamedValueInfo {
        private final String name;
        private final boolean required;
        @Nullable
        private final String defaultValue;
        public NamedValueInfo(String name, boolean required, @Nullable String defaultValue) {
            this.name = name;
            this.required = required;
            this.defaultValue = defaultValue;
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Spring入门之AOP实践:@Aspect + .. 下一篇Java自学-类和对象 方法重载

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目