程序猿的日常——SpringMVC系统架构与流程回顾

web开发经历了很漫长的时间,在国内也快有十几年的时间了。从最开始的进程级到现在的MVC经历了很多的改进和优化,本篇就主要复习了解下Spring MVC相关的知识。

发展历程

第一阶段 CGI进程响应

这一阶段,服务器比较弱,请求也很简单,就是用户发一个请求,服务器接收后新建进程,然后返回结果。

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

第二阶段 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类,用来自动封装参数,是用的时候会方便得多。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏飞雪无情的博客

工具 | Android Studio 2.3镜像更新,极速下载体验#2

Android Studio 2.3发布了,更新了很多不错的功能,比如WebP的支持,AppLink助手等,,因为众所周知的原因,所以就第一时间更新了镜像,让大...

933
来自专栏北京马哥教育

linux安全小贴士

对于系统管理员,让产品的系统更安全,免于骇客和黑客的攻击,一直是一项挑战。这是我们关于“如何让Linux系统更安全” 或者 “加固Linux系统“之类话题的第一...

3438
来自专栏数据和云

快速掌握:大型分布式系统中的缓存架构

CDN(Content Delivery Network 内容分发网络)的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中...

932
来自专栏Java技术栈

SpringCloud Eureka自我保护机制

自我保护背景 首先对Eureka注册中心需要了解的是Eureka各个节点都是平等的,没有ZK中角色的概念, 即使N-1个节点挂掉也不会影响其他节点的正常运行。...

40010
来自专栏张善友的专栏

CentOS 7 搭建基于携程Apollo(阿波罗)配置中心单机模式

2406
来自专栏逸鹏说道

开发人员为何需要企业服务总线?

引言 重要的应用程序很少是单独存在的;如果不能与其他的应用程序一起使用,应用程序将难以发挥很大的作用。面向服务的体系结构往往将应用程序集成在一起,这样它们就可以...

2765
来自专栏FreeBuf

挖洞经验 | 利用密码重置功能实现账号劫持

最近,我参加了某平台邀请的漏洞测试项目,在其中发现了一个独特的账号劫持漏洞,整个漏洞发现过程非常意外也非常幸运,通过密码重置功能就能实现账号劫持,在此我就把它写...

1082
来自专栏一英里广度一英寸深度的学习

Hello,Java女神

第一阶段:C++转行,开始学习Java 第二阶段:Java Web,jsp+servlet 第三阶段:Struct Spring 第四阶段:Spring ...

1315
来自专栏MoeLove

Linux上源码编译MongoDB

MongoDB的官网上是有已经编译好的二进制包的,这里选择clone MongoDB在github上的仓库

1253
来自专栏张善友的专栏

CentOS 7 搭建基于携程Apollo(阿波罗)配置中心单机模式

Apollo(阿波罗)是携程框架部门研发的配置管理平台,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理...

1.3K6

扫码关注云+社区

领取腾讯云代金券