深入理解SpringMVC 参数映射

深入理解SpringMVC 参数映射

写在前面:
由于公司目前系统07年开始开发的,完全由servlet+htm开发的,无设计模式,全if else ,while 构成,有的客户还是用JDK1.5,上过一次spring报了100多个bug,又下架了。现在开始自己写类似spring MVC ,BeanFactory,Aop,myBatis框架。在开发的过程中,对SpringMVC,myBatis等框架进行了研究。我的新框架是简单的实现,基本够用。
本次先写对SpringMVC参数映射的一点认识。

  • 一、Spring MVC请求过程
  • 二、路径到Controller方法映射
  • 三、方法参数映射
  • 四、总结

引入

http://127.0.0.1/login?username=admin&password=!# ! #!#

public String login(String username,String password){

}

SpringMVC是如何把参数名称username,password对应上,且把值传给对应方法的?
带着上面的问题,逐步来了解

一、Spring MVC请求过程

先看一下,请求过程的堆栈:
从doService 一路到 LocalVariableTableParameterNameDiscoverer.getParameterNames,再调用 ClassReader 读取class文件解析出参数名称。
深入理解SpringMVC 参数映射_第1张图片
请求概要 时序图
深入理解SpringMVC 参数映射_第2张图片
接上图
深入理解SpringMVC 参数映射_第3张图片

从图二开始解析参数,
图二中的 ParameterNameDiscoverer 是接口,LocalVariableTableParameterNameDiscoverer是其实现类。

二、路径到Controller方法映射
略……

重点开始:
三、方法参数映射
LocalVariableTableParameterNameDiscoverer.java

@Override
    public String[] getParameterNames(Method method) {
        Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
        Class declaringClass = originalMethod.getDeclaringClass();
        Map map = this.parameterNamesCache.get(declaringClass);
        if (map == null) {
            map = inspectClass(declaringClass);
            this.parameterNamesCache.put(declaringClass, map);
        }
        if (map != NO_DEBUG_INFO_MAP) {
            return map.get(originalMethod);
        }
        return null;
    }

先从参数缓存中查找,

MapString[]> map = this.parameterNamesCache.get(declaringClass);

如果没有解析过(本次重点方法)

map = inspectClass(declaringClass);

详细方法如下:(我去掉了注释和异常日志打印)

private Map inspectClass(Class clazz) {
        InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz));
        if (is == null) {           
            return NO_DEBUG_INFO_MAP;
        }
        try {
            ClassReader classReader = new ClassReader(is);
            Map map = new ConcurrentHashMap(32);
            classReader.accept(new ParameterNameDiscoveringVisitor(clazz, map), 0);
            return map;
        } catch (IOException ex) {}
          catch (IllegalArgumentException ex) {}
        finally {
            is.close();         
        }
        return NO_DEBUG_INFO_MAP;
    }

分析:
1 加载class文件流
2 构造ClassReader
3 调用ClassReader.accept
具体对应方法:
public void accept(final ClassVisitor classVisitor,final Attribute[] attrs, final int flags)

接着调用 :
private int readMethod(final ClassVisitor classVisitor,final Context context, int u)
这个方法中,读取class文件,根据java规范解析该文件,获取方法名称,参数类型,参数名称
至此,获取到对应的Controller对应方法的参数名称 如:username,password,
再调用request.getParameter(“username”)获取参数值
一路返回至 InvocableHandlerMethod.doInvoke(),MappingRequest对应的方法

四、总结
由于时间紧迫,语言表达能力有限,仅供参考。
等稍空闲再写 ClassReader读取过程。

你可能感兴趣的:(java-spring-mvc,spring-实战,springmvc,spring,mvc)