在做Spring MVC时,我们只需用@Controllor来标记Controllor的bean,再用@RequestMapping("标记")来标记需要接受请求的方法,方法中第一个参数为HttpServletRequest类型,最后一个参数为Model类型,中间可以为任何POJO,只要符合标准,有set和get,Spring即可以根据网页请求中的参数名,自动绑定到POJO对象的属性名,这是相当方便的。其中的原理是什么呢?看下源代码就可以知道了。
首先,要知道Method对象的invoke(调用,借助)方法,看下这一段代码:
Class clazz = Class.forName("TaskProvidePropsList");//这里的类的全名 Object obj = clazz.newInstance();//获取类的实例 Field[] fields = clazz.getDeclaredFields();//获取属性列表 //写数据 for(Field f : fields) { PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);//获取属性对象,要标明是哪个类 Method wM = pd.getWriteMethod();//获得写方法,即setter wM.invoke(obj, 2);//执行obj对象的wm方法,2为参数。因为知道是int类型的属性,所以传个int过去就是了。。实际情况中需要判断下他的参数类型 } //读数据 for(Field f : fields) { PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);//获取属性对象,要标明是哪个类 Method rM = pd.getReadMethod();//获得读方法,即getter Integer num = (Integer) rM.invoke(obj);//执行obj对象的rm方法。因为知道是int类型的属性,所以转换成integer就是了。。也可以不转换直接打印 System.out.println(num); }
用法还是比较简单的。
接下来就是Spring中是怎么调用这个方法为POJO赋值的。
最先要追溯到 org.springframework.web.servlet.FrameworkServlet类中的doGet(HttpServletRequest request, HttpServletResponse response)等do方法(do方法是servlet中的基本方法,相当于Spring接管了所有do方法,然后去分发方法。若不使用框架,则需要自己去写servlet继承HttpServlet实现所有do方法,也是可以使用的,但是服务器较大时这样就太复杂了,框架就是为了这个而存在的)
这个方法中调用processRequest(request, response),processRequest中调用doService(request, response),doService是所有do方法的核心,负责把该请求根据情况分发给不同的service(@RequestMapping注解标明的方法)。
doService在FrameworkServlet的子类DispatcherServlet(Dispatch:派遣,调度)中实现,doService中又调用doDispatch(request, response),把当前请求分配给合适的Service的合适方法。
doDispatch方法中调用(HandlerAdapter)ha.handle(processedRequest, response, mappedHandler.getHandler())方法去寻找与该请求挂钩的方法(processedRequest是由checkMultipart(request)转换而来的)(注释中写的Actually invoke the handler.)。
接着HandlerAdapter中的handle方法