开发过web项目的同学估计会有如下几个疑问一直萦绕心头:
1)Tomcat是什么,为什么要用Tomcat啊?
2)Servlet是什么,为什么我用Spring压根没见过它?
3)Spring好神奇哦,谁能告诉我它是怎么实现的?
4)之前的人都用jsp,这个是什么东西哦?
5)为毛要用ajax啊,好像用ajax的地方就没有jsp勒耶?
如果这几个问题问到了你的心坎里了,那么请继续看!!!
1.从前后端交互原理,谈Tomcat和Servlet
首先,你肯定会想到用网络编程的知识。在服务端创建一个TcpServer,然后监听80端口。然后对Http请求进行解析。获取URL、参数列表、然后通过URL的路径找到对应的方法。执行处理逻辑。把处理结果封装成HTTP包,返回给浏览器。浏览器收到结果或者超时后自动断开TCP连接。原理图如下:
可以看到,我们的网络通信部分、协议解析和封装部分、逻辑处理部分都在一个程序中,全要开发者自己写。这显然不是好的设计模式。好的设计模式有一个原则:"封装变化,将不变和变化分离“。很显然,这里只有逻辑处理器是变化的。而网络通信、协议解析和封装都是固定的!!!
所以,我们猜想:Tomcat是什么?它会不会就是一个能够监听TCP连接请求,解析HTTP报文,将解析结果传给处理逻辑器、接收处理逻辑器的返回结果并通过TCP返回给浏览器的一个框架。
现在,我们来验证一下。下图是Tomcat的架构图(来源于网络)。
可以看到,Connector就是实现网络通信的东西。Context就是一个WEB
项目,Tomcat和Web项目中的Servlet有一根线连接在了一起。那么,这个Servlet应该就是我们的逻辑处理器了吧。
所以,Tomcat是一个Servlet容器,它将前后端交互过程中不变的东西(网络通信、协议解析等)封装了起来。而Servlet是一个逻辑处理器,它可以被Tomcat创建、调用和销毁。所以我们的web程序是基于Servlet的,一个Web项目中有一个或者多个Servlet,Web程序依靠Tomcat启动。另外,Tomcat是多线程的,每一个请求都是一个线程,而Servlet是单个的实例,所以,【敲黑板】我们必须要注意在自己的Servlet的中,尽量不要用全局变量,如果要用全局变量,一定要有同步操作。当然,如果全局变量是只读的,那么没有关系。
实际上,Tomcat通过web.xml文件获取所有Servlet类的路径,然后通过反射的方法实例化Servlet、调用Servlet的service方法。然后,service方法中会对HTTP的请求类型进行分类,调用doPost、doGet、doDelete等方法。这些方法都是抽象的。我们开发web程序的程序员通过继承HttpServlet可以覆写这些方法。另外,Tomcat会传过来两个参数:(HttpServletRequest request, HttpServletResponse response)。我们通过request对象获取请求信息,通过response对象向Tomcat返回数据。
2.Spring是一种利用了注解、反射和模板等技术的Servlet
spring是基于Servlet的,它的核心类是DispatchServlet(分发Servlet)。它继承了HttpServlet,所以它还是一个Servlet。只不过它覆写了HttpServlet的init、doPost、doGet等方法。它在init中通过类加载器检索所有的@Controller、@Service等类,然后通过反射实例化类,通过反射向类中注入实例依赖。著名顶顶的IOC是什么?其实,它就是一个HashMap!!!key=类长名,value=实例对象。在init函数中,它还会通过反射获取所有带有@RequestMapping的类和方法。然后维护一个handlerMapping的对象,key=URL,value=method。
现在假设有一个http请求来了,Tomcat首先收到了请求,并将请求的信息封装成HttpServletRequest 传给了 DispatchServlet,DispatchServlet通过URL是不是可以获取到对应的方法。然后,DispatchServlet中的doPost和doGet方法只需要对HttpServletRequest中的参数进行解析,创建一个参数列表。然后通过"method.invoke(方法所在的实例对象,通过IOC容器获取, 参数列表);"即可触发我们自己写的方法。
写的比较简单,如果您看不懂的话,推荐一个博客纯手写Spring,麻雀虽小,五脏俱全-咕泡学院Tom老师。自己动手写一个小的spring框架可以让你更好的理解spring的原理。
3.JSP也是一个Servlet
我们浏览器输入URL,Tomcat收到URL,找到相应的文件。如果是.jsp文件的话,先将.jsp解析翻译成.java文件,且这个.java文件是一个Servlet类。然后调用javac将.java编译成.class文件。最后,通过JVM加载执行。所以,JSP是Servlet没毛病吧?
可以看出,JSP在第一次需要解析、编译、加载、运行。而且JSP生成的Servlet是通过后台服务器运行的。这给服务器造成了巨大的压力,因为,每一个页面都需要一个Servlet。
最重要的是,每次请求,后台都会返回一整个页面给浏览器(页面是Servlet动态生成的)。就算只是变了一个字符,都TMD的全发一遍,多么的不合理啊!!!
4.Ajax技术淘汰了JSP,真正实现了前后端分离
Ajax全称是:Asynchronous Javascript And XML。
Ajax原理请看博客# 30分钟全面解析-图解AJAX原理