web开拓经历了很漫长的韶光,在海内也快有十几年的韶光了。
从最开始的进程级到现在的MVC经历了很多的改进和优化,本篇就紧张复习理解下Spring MVC干系的知识。

发展进程

第一阶段 CGI进程相应

后段jsp华为技巧总监经验分享SpringMVC体系架构与流程回想 Python

这一阶段,做事器比较弱,要求也很大略,便是用户发一个要求,做事器吸收后新建进程,然后返回结果。

这种办法一看代价就很大,每次都新建进程,很麻烦。

第二阶段 Servlet线程级别相应

Servlet构造跟上面差不多,只不过每次都只是新建一个线程,这样代价就小很多了。

Servlet的生命周期有四个阶段:

1 加载和实例化:启动Tomcat这种Servlet容器,容器会根据配置文件加载Servlet类,并通过new方法进行实例化

2 初始化:然后调用init()方法初始化,每个Servlet只会初始化一次,可以理解为单例模式

3 要求处理:当做事器吸收要求后,吸收要求的线程找到对应的Servlet,调用service()方法相应。
因此会存在多个线程同时掉用一个Servlet实例的情形,因此这里会有线程安全问题的!

4 销毁:Tomcat关闭时,调用destroy()销毁容器。

那么整体的流程是这样的:

1 客户端发送要求,Tomcat做事器吸收要求后,封装HttpRequest工具和HttpResponse工具

2 根据配置文件xml去查找匹配的servlet-name,并加载对应的servlet

3 如果之前没有加载过,那么加载并进行实例化和初始化;如果加载过,则直接调用service方法处理

4 把处理的结果封装到HttpResponse中返回

那么如何回答Serlet到底是不是线程安全呢?可以说它本身是无状态的,如果没有在里面自己新增一个什么count++的操作,就不会存在线程安全问题。

如果想要避免线程安全问题,可以采取下面的思路:

1 避免利用实例变量

2 避免利用非线程安全的凑集

3 访问外部可写文件须要加锁

总结来说,这里只要把稳Servlet的生命周期以及线程安全问题即可。

第三阶段 JSP+Model1

这个阶段引入了JSP技能,即Java Server Page,它是一种把HTML和Java稠浊在一起的技能措辞。
我记得我刚学习Java的时候,便是用这种JSP的技能,如果页面轻微繁芜一点,代码就会特殊混乱。

不过这种办法也引入了一种前后端分离开拓的互助模式,即会有专门的开拓静态页面的人,开拓完后把页面交给后段程序猿,增量的开拓Java干系的后端处理和数据展现干系的功能。

大体的流程是

1 用户发送要求给做事器,做事器对应的JSP页面吸收到要求。

2 JSP会被编译成Servlet,模式就跟之前一样了

3 末了填充数据,返回即可。
也便是说,它实在便是把之前页面视图的部分和Servlet的部分领悟到一起而已。

现在基本上已经看不到这种技能模式了。

第四阶段 前后端分离+Spring MVC

现在大部分的模式便是这样的,只是在后段展现上略有不同。
这种模式紧张的关键是那个掌握器,它负任务务的分发要求,以及数据的返回。

架构模型就如上面所示,不过在SpringMVC中,掌握器有两种,一种是前端掌握器,一种是运用掌握器。

大致的流程为:

1 用户发送要求,前端掌握器统一吸收

2 然后根据不同的规则分发到对应的运用掌握器,比如根据URL

3 运用掌握器在调用逻辑代码处理

4 末了层层返回。

目前一样平常的公司,都是采取前后端分离的技能构造。

1 前端是Vue.js或者AngularJS再或者是JQuery,通过Http的办法发送到后端。

2 后端吸收要求后按照一定的业务规则处理,然后把数据返回给前端。

3 前端通过JavaScript代码进行解析,浏览器渲染展现。

源码细节

经由上面的描述,对SpringMVC的整体流程该当有了大致的理解。
但是经典的那句话,talk is cheap, show me your code。

这个Dispacther分发器是怎么实现的呢?实在它便是一个普通的Servlet而已,只不过Servlet拦截的要求时所有的要求而已:

<servlet> <servlet-name>test</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

然后这个Servlet会调用doDispatch方法,紧张的内容都在这里

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 省略代码 try { doDispatch(request, response); } finally { 省略代码 }}

doDispatch方法则包含了刚才描述的各类步骤:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 省略 try { 省略 try { // Determine handler for the current request.得到处理器映射 mappedHandler = getHandler(processedRequest); // Determine handler adapter for the current request.得到适配器工具 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Actually invoke the handler.实际处理 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //末了返回结果 } }}

常用的履历

1 如果时开拓Restful风格的后端程序,即通过Http以及GET、POST、PUT、DELETE等进行数据的增编削查,那么可以直策应用 @RestController 表明

2 常日工程设计都会分为几层, Controller , Service , Mapper 如果有分层,可以用 @Service 和 @Autowired 表明搭配自动注入

3 如果利用 @Service ,最好直接写上Service的名字,如 @Service(value = \"大众myService\"大众) 不然如果你的名字是ABCService,默认的Service名字大小写会随意马虎引发BUG,尤其是须要手动查找某个bean时。

4 一样平常为了让代码简洁,Controller参数列表可以封装一个JavaBean类,用来自动封装参数,是用的时候会方便得多。

须要的Java架构师方面的资料可以关注之后私信哈,回答“资料”领取免费架构视频资料,记得要点赞转发噢!