先上一张springmvc的流程图,自己结合源码画的:
DispatcherServlet是一个Servlet,配置的是拦截所有的请求,所以发送请求的时候会进入其方法
1、protected final void doGet(HttpServletRequest request, HttpServletResponse response);
2、processRequest(HttpServletRequest request, HttpServletResponse response);
3、protected void doService(HttpServletRequest request, HttpServletResponse response) ;
4、protected void doDispatch(HttpServletRequest request, HttpServletResponse response) ;
//这一步获取处理前执行链,封装了对应的handler和拦截器集合;这个是利用处理器映射器找到的,用三个处理器映射器,使用 RequestMappingHandlerMapping;
5、protected HandlerExecutionChain getHandler(HttpServletRequest request) ;
//找到合适的处理器适配器:常规的有三个,常用的是RequestMappingHandlerAdapter;
6、protected HandlerAdapter getHandlerAdapter(Object handler);
//执行容器中的拦截器的preHandle方法
7、boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response);
8、public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler);
//用获取到的处理器适配器执行handler处理器对象,返回ModelAndView
9、protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) ;
10、protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod)
11、public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object… providedArgs) ;
//执行handler处理器
12、public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object… providedArgs)
//获取处理器参数
13、private Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
Object… providedArgs)
//利用反射,执行handler处理器
14、protected Object doInvoke(Object… args)
//l获取ModelAndView对象
15、private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) ;
//执行拦截器的postHandle方法
16、void applyPostHandle
//使用ModelAndView对象进行视图的渲染
17、protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
上面是大致的流程方法,但是细节点没有指出,
1、如何进行方法参数赋值的,这个我没有具体没有看
2、如何用request找合适的handler?
在容器加载的时候,处理器映射器中HandlerMapping对象中有一个Map对象存储了key为url, value为handler对象,所以可以通过访问的url获得对应的handler对象;
3、如何把url和handler映射关系存储到处理器映射器中?
遍历子容器中的有@controller注解的bean, 遍历当前bean的所有方法,找到有@RequestMapping注解的方法,然后把url和方法对象存储到处理器映射器中;
4、父子容器的关系:springmvc的为子容器,spring的为父容器;
父容器不能获取子容器中的对象,子容器可以获取到父容器的bean;
为什么这样设计:是为了解耦,因为不光有springmvc还有strut等框架,通常对于web层我们会使用单独的配置文件。例如在上面的案例中,一开始我们使用spring-servlet.xml来配置web层,使用applicationContext.xml来配置service、dao层。如果现在我们想把web层从spring mvc替换成struts,那么只需要将spring-servlet.xml替换成Struts的配置文件struts.xml即可,而applicationContext.xml不需要改变
如果都在spring容器中,这时的SpringMVC容器中没有对象,所以加载处理器,适配器的时候就会找不到映射对象,映射关系,因此在页面上就会出现404的错误。
因为在解析@ReqestMapping解析过程中,initHandlerMethods()函数只是对Spring MVC 容器中的bean进行处理的,并没有去查找父容器的bean。因此不会对父容器中含有@RequestMapping注解的函数进行处理,更不会生成相应的handler。所以当请求过来时找不到处理的handler,导致404。
两个容器同时扫描所有的bean ,造成两个父子IOC容器中生成大量的相同bean,这就会造成内存资源的浪费
如果把所有层放入SpringMVC的。但是事务和AOP的相关功能不能使用