程序猿的日常——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类,用来自动封装参数,是用的时候会方便得多。
程序猿的日常——SpringMVC系统架构与流程回顾的更多相关文章
- Java程序员的日常——SpringMVC+Mybatis开发流程、推荐系统
今天大部分时间都在写业务代码,然后算是从无到有的配置了下spring与mybatis的集成. SpringMVC+Mybatis Web开发流程 配置数据源 在applicationContext.x ...
- 程序猿的日常——Java中的集合列表
列表对于日常开发来说实在是太常见了,以至于很多开发者习惯性的用到数组,就来一个ArrayList,根本不做过多的思考.其实列表里面还是有很多玩法的,有时候玩不好,搞出来bug还得定位半天.所以这里就再 ...
- 程序猿的日常——Java基础之equals与hashCode
equals和hashCode是我们日常开发最常使用的方法,但是因为一般都使用默认的规则,因此也很少会引起关注.不过了解他们的用途和设计的原则,还是会帮助我们更好的设计代码. equals equal ...
- 程序猿的日常——Mybatis现学现卖
最近有一个小项目需求,需要用spring mvc + mybatis实现一个复杂的配置系统.其中遇到了很多不太常见的问题,在这里特意记录下: 主要涉及的内容有 事务 多表删除 插入并返回主键 1 sp ...
- 程序猿的日常——Java基础之clone、序列化、字符串、数组
其实Java还有很多其他的基础知识,在日常工作技术撕逼中也是经常被讨论的问题. 深克隆与浅克隆 在Java中创建对象有两种方式: 一种是new操作符,它创建了一个新的对象,并把对应的各个字段初始化成默 ...
- 程序猿的日常——HashMap的相关知识
背景知识 哈希冲突 哈希是指通过某种方法把数据转变成特定的数值,数值根据mod对应到不同的单元上.比如在Java中,字符串就是通过每个字符的编码来计算.数字是本身对应的值等等,不过就算是再好的哈希方法 ...
- 程序猿的日常——工作中常用的Shell脚本
工作当中总是会有很多常用的linux或者命令,这里就做一个总结 文件远程拷贝 如果想把文件从本机拷贝到远程,或者从远程下载文件到本地. # 把本地的jar拷贝到远程机器xxxip的/home/sour ...
- 程序猿的日常——Java基础之抽象类与接口、枚举、泛型
再次回顾这些基础内容,发现自己理解的又多了一点.对于一些之前很模糊的概念,渐渐的清晰起来. 抽象类与接口 抽象类通常是描述一些对象的通用方法和属性,并且默认实现一些功能,它不能被实例化.接口仅仅是描述 ...
- 程序猿的日常——JVM内存模型与垃圾回收
Java开发有个很基础的问题,虽然我们平时接触的不多,但是了解它却成为Java开发的必备基础--这就是JVM.在C++中我们需要手动申请内存然后释放内存,否则就会出现对象已经不再使用内存却仍被占用的情 ...
随机推荐
- svn回退版本/取消修改
取消对代码的修改分为两种情况: 第一种情况:改动没有被提交(commit). 这种情况下,使用svn revert就能取消之前的修改. svn revert用法如下: # svn revert [ ...
- POJ 3709 K-Anonymous Sequence - 斜率优化dp
描述 给定一个数列 $a$, 分成若干段,每段至少有$k$个数, 将每段中的数减少至所有数都相同, 求最小的变化量 题解 易得到状态转移方程 $F_i = \min(F_j + sum_i - su ...
- Python 版本之 Anaconda
https://www.anaconda.com/download/#linux Anaconda概述 Anaconda是一个用于科学计算的Python发行版,支持 Linux, Mac, Windo ...
- DataStage 八、清除日志
DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 DataStage 三.配置ODBC Da ...
- 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)
传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...
- 2018.06.30 BZOJ 3932: [CQOI2015]任务查询系统(主席树)
3932: [CQOI2015]任务查询系统 Time Limit: 20 Sec Memory Limit: 512 MB Description 最近实验室正在为其管理的超级计算机编制一套任务管理 ...
- 2018.08.28 集合堆栈机(模拟+STL)
描述 中学数学里集合的元素往往是具体的数字,比如A = {1,2,3},B = {}(空集)等等.但是要特别注意,集合的元素也可以是另一个集合,比如说C = {{}},即说明C有且仅有一个元素--空集 ...
- bootstrap模态框的调用
1.<a href="JavaScript:void(0);" class="bs-tooltip remark-item" rel="{$bi ...
- 微信小程序 获取用户openid
1,可以在小程序app.js入口文件中放入登录代码 wx.login({ success: res => { // 登录注册接口 if (res.code) { // 调用服务端登录接口,发送 ...
- python入门前的准备
为什么学习python? python是一种高级脚本解释性语言,若运行for循环等肯定不如c或fortran快,但是它是开源的,有很多特别有用的库,代码以空格强制控制格式,形式优美简洁,且特别容易实现 ...