简单的手写springmvc思路
首先,做一个简单的思考,mvc的概念是什么样的。springmvc实现了一个什么样的功能(当然,咱们不能面面俱到,只是一个简单的臆想…)
其次,技术上要用到什么,需要考虑哪方面的知识。
最后, 整个过程是依赖servlet 来完成的。
这次只探讨springmvc大致的实现过程,从请求到映射的过程。其他优秀的地方暂时不在考虑的范围之内
mvc
MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。
图片来源:菜鸟教程
具体的模型 或者 认知 建议自己百度一下。
springmvc
谈到springMVC,咱们不得不提到一个大管家DispatcherServlet 这个类在spring里面是继承自 FrameworkServlet,里面实现了ApplicationContextAware接口并继承了HttpServlet。具体的实现和作用暂时不在谈论范围之内。
图片来源:https://www.cnblogs.com/hamawep789/p/10840774.html
具体的网上也有很多类似的介绍springmvc 执行流程这一系列,在这暂不做介绍
知识点(技术性分析)
在此之前,我想说明一下,今咱们只是简单的分析一下,只要是从发送请求到接受,到处理映射 再到返回。这么一个过程。
大致流程:
在tomcat启动的时候执行初始化。
- 参照spring,自定义一个实例化类的Map.存放已经实例化好的Controller、service等(ioc)
- 参照spring DI 属性注入
- 参照处理器映射器,自定义一个映射器Map handlerMap 存放路径映射对应的controller+方法。
- 参照处理器适配器,在反射的时候根据不同的参数,有不同的处理。1)if …else if 判断 2)策略模式。
所有的前提都是在正确的把编译好的.class 文件读到内存中,在实例化之前。
细节分析
上面所讲的初始化 都应该在容器启动之前都初始化完毕。有两种方式可行
初始化
- 遵守servlet3.0规范,在类路径下 新建 META-INF\services\javax.servlet.ServletContainerInitializer 这样一个文件。里面写上一个接口,在容器启动的时候会自动扫描实现这个接口的实现类
例如 springmvc中是实现这个: org.springframework.web.SpringServletContainerInitializer
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer) waiClass.newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
具体不是今天分析的重点,可以自己去百度看看。其实跟spring 中IOC 一个模样。会自动把先加载的类事先实例化。
- 新建DispatcherServlet 继承 HttpServlet 实现init() 方法。配合web.xml 实现自动加载。
实现DI 时需要注意
在咱们开发的时候一般都是
// @Autowired
@Resource("XXX")
private XXService service;
**因为是基于反射去做,在获取到 私有属性的时候 需要 field.setAccessible(true) 把私有属性放开 **
这也就是说为什么不安全的地方。哈哈
处理器适配器
映射器简单,就是一个map key — vue 对应 /user/getById(key) ------- getById() 方法(value)
这里的适配器,只要是针对不同的请求参数做解析处理的所以需要做特殊处理。 最后把参数数据返回 method.invoke()执行就可以。
总结
好了,到这里也就阐述完毕,其实多想想很简单这个东西。就是 自定义注解、反射、可能还会涉及到IO的知识,就这些了。
这只是仅仅代表我个人的拙见,如果有什么不对的请指正,谢谢。