为什么要看SpringMVC源码
工作中使用公司内部封装的框架,入参处理繁琐,响应方法还要进行XML配置,卧槽,还是多个XML的配置,这感觉完全是以前的老古董的东西,用起来心都碎了。想想以前用的SpringMVC,使用体验完爆现在使用的框架,让人好想了解其内部是如何实现的。
基于上面的疑惑,带着下面三个疑问去阅读SpringMVC框架:
请求如何映射到RequestMapping方法,参数如何传递
怎样实现方法的响应
如何返回数据
现在由于前后端分离,Jsp等视图用得相对比较少,故不深入了解
SpringMVC执行流程
在此,为了方便源码理解,先给出整个SpringMVC整体思想,然后再到源码中去去印证。
首先,先来回忆下Servlet是如何运作的,主要看有注释的三个方法。
public interface Servlet {
//初始化,当Servlet创建时,该方法进行初始化工作
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
//请求处理,该方法中实现业务处理逻辑
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
//销毁,Servlet结束时,该方法进行销毁工作
public void destroy();
}
为了简化Servlet处理,我们一般直接继承HttpServlet并在子类中重写doGet(),doPost()等进行编码的,但是doGet(),doPost()最终还是由Service()来调用的,这不就是一个模板方法么?限于篇幅,HttpServlet只给出了部分代码。
public abstract class HttpServlet extends GenericServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp){...}
protected void doPost(HttpServletRequest req, HttpServletResponse resp){...}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
...
doGet(req, resp);
...
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else {
...
}
}
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
service(request, response);
}
}
SpringMVC内部的其实是通过一个Servlet来实现的。
首先,在容器启动的时候,调用Servlet进行初始化,初始化它要做的一件事就是扫描相关的@RequestMapping,并把这个注解的相关信息以<K,V>的数据结构注册到起来,K指的是请求地址,V则是封装了这个地址对应的类、方法及参数等等,<K,V>数据结构其实也就是一个Map。
当一个请求进来时,会在service()方法进行分发这个请求的具体响应方法,通过上面的<K,V>结构找到相应的响应方法,并采用反射去调用生成结果。
最后把这个结果填充到HttpServletResponse会返回前端。
以上就是一个SpringMVC的整体运作流程。