从 http 协议出发去理解 springmvc 和页面端的交互与前后端分离的意义

写在最前面,这篇文章中对涉及到的各种源码不会进行进一步探讨,只是对整个的处理过程有一个相应的解释,从而去理解 springmvc 和页面端的交互和前后端分离的意义。

Part1  http协议

当你在浏览器输入某个网址,按下回车,到浏览器展示页面,中间发生了什么?

很简单,浏览器把你想要访问某个资源的想法转发给了你访问的网站服务器,网站服务器把你可以访问的资源返回给了浏览器。那么这双向的数据交互就用到了 http 协议。

http 协议是基于 TCP/IP协议 的应用层协议,是浏览器和服务器之间数据交换的一种规范。我们可以把浏览器请求服务器的过程称为 http 请求报文,把服务器响应浏览器的请求的过程称为 http 响应报文。http 请求报文和 http 响应报文从结构上来讲差不多,都可以分为报文头部和报文正文(也就是请求头,请求体,响应头,响应体)。具体结构如下图:

请求报文
响应报文头
响应报文体

报文头部携带了请求的地址,时间,格式及字符集等等信息(某些情况下传输后乱码的问题可以通过设置这里的字符集解决)。报文正文携带了请求的参数和响应的内容,在早期版本的 http 协议中,传输的内容就是 html ,后续的版本中对此进行了升级,可以传输图片、视频等(详细的可以自己百度)。

另外,http 协议是无状态的,也就是说两次连接是独立的,连接一次就要三次握手校验,并不能保存现在常用的登录状态。

Part2   springmvc 是如何处理 http 请求的

首先,我们回忆一下不使用框架情况下的 javaWeb 是怎么处理的 。如下图:

此外还需要在 web.xml 中配置哪个请求地址进入到那个 servlet 中。也就是说,javaWeb 为我们做了网址映射,当我们访问某个地址的时候可以进入到指定的 servlet 中进行处理。

我们接下来看一下 doGet 和 doPost 的入参:

查看接口中的这些方法,对照 http 请求和响应报文中的内容,我们可以发现 javaWeb 为我们封装了一个请求报文对象和响应报文对象,http 请求中的信息都在 HttpServletRequest 中,而服务器的响应都被封装在了 HttpServletResponse 中被返回给了浏览器。

接下来我们来看一下 springmvc 的写法。如下图:

这是一个比较常见的 springmvc 的写法,@RequestMapping 指定了这个方法用来处理哪个网址请求,接受什么方法和入参,以及返回什么数据(model)和 jsp(view),也就是 ModelAndView。

再深入一些,也就是 spring 的 DispatcherServlet 对请求进行拦截,然后根据映射信息去查找应该调用哪个 controller 的哪个 method 去执行(如果仔细看 tomcat 启动信息,可以看到 spring 生成所有的映射信息)。虽然在这里我们编写 method 的时候不需要传入 HttpServletRequest 和 HttpServletResponse ,但实际上这部分是由 spring 框架帮我们完成了,也就是对 method 所需的入参进行了绑定,如果编程的时候遇到入参一直绑定不成功的情况,直接接收 HttpServletRequest 作为入参进行获取所需的数据,当然你需要确定你所需的数据确实在请求报文中。

Part3   springmvc 返回 http 响应

首先看下 spring 配置:

所以,springmvc 会通过我们配置的 ViewResolver 去解析我们指定的视图,找到 jsp 页面,组装数据,然后经容器一系列的处理后进行返回。那么,这里返回给响应报文的就是我们指定的 jsp 么?并不是。

我们编写的 jsp 文件中经常会有很多 <c> 标签来对传入的 model 进行渲染,有些甚至还会有 java 代码(非常不推荐这种方式),这些东西,浏览器是无法进行执行和渲染的,还需要进行进一步的处理。这时候就要去看 tomcat 工作目录了:

我们可以看到,我们的 jsp 页面被处理成了一个 java 文件和 一个 class 文件,让我们来打开看一下:

我们写的 jsp 文件在这里通过 out.write() 被翻译成了 html ,包括 model 里的数据,最后被放入到 response 中,也就是 http 响应报文。

Part4   前后端分离的意义

通过上面三步,我们大致了解了 springmvc 处理 http 请求和进行 http 响应的过程。这个过程有个特点,我们的后端代码和页面都需要被放在 tomcat 容器中(大部分情况下是同一个 tomcat 中),我们即使是只想访问一个 jsp 页面也需要每次都进行 index_jsp.java 和 index_jsp.class 和编译,注意是每次!这个时候,如果有大量用户访问你的 jsp,都还没到实际的服务呢,可能服务器已经趴下了。

那么,我们提出一个设想,我做一个集群,横向对服务进行扩展,这样也可以。但是对于单台服务器,服务能力并没有任何的提升,还是访问一次 jsp,所有事情都做一遍,该趴下继续趴下。

另外一个设想,既然浏览器接受的是 html 页面,那我们就把浏览器不能直接用的 jsp 换成能直接用的 html ,这样就可以避免每访问一次编译一次,让服务器的处理能力更多的用到我们的服务上去,而且页面间的跳转也交给页面去完成好了,完全不需要后端的参与。更进一步,tomcat 容器其实对于静态资源的处理能力要比 nginx 低不少,用 nginx 去处理静态资源更合适,而且也更方便横向扩展。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值