访问服务器的静态页面
每个Web服务器都运行着一个HTTP服务软件,用于响应web浏览器的请求,返回客户想要的页面。HTTP服务器都会有一个文件夹用于放置相关的页面文件,默认是 /user/local/apache/htdocs 。例如,服务器的域名叫 example.com。那客户端浏览器访问http://example.com/index.html 就是访问服务器上的HTTP服务器(URL如果没有指定端口,就是访问80端口,80端口绑定的是HTTP服务,80端口是默认对外开启的),那HTTP服务器就会重定向到 /user/local/apache/htdocs 文件夹,并查询是否有index.html 文件,有则返回,没有则返回错误报文。
访问服务器的动态页面
服务器只提供静态页面还不够,客户端想要更多的服务,比如动态的页面(页面上显示当前使用者信息等等),或者修改数据库内容。这时候,服务端就不能单纯地映射并返回文件来实现了,这时候就需要有可执行的脚本程序来对页面进行更改,或者其他操作。就拿动态页面来说,客户端浏览器访问 http://example.com/home?name=randy 这里用户带上了自己的用户名,希望访问的主页右上角能显示自己的名字。这里 home 通过映射到一个CGI程序,并执行。该程序通过标准I/O流,解析HTTP报文,获取到了请求参数,并通过程序生成对应的HTML文件,在通过标准I/O流,将文件返回给请求客户。
注:CGI (Common Gateway Interface)通用网关接口,CGI程序常见的由Perl,Python,C,C++ 或者任何可利用标准I/O流的语言。
Java的一种想法
一开始,人们想最理想的方式就是完全基于Java的实现方案, servlets <=> applets 。即
客户端用applet校验并发送数据,
服务端用servlet接收并处理数据。
就连这名称都是一对。
但是,并非所有浏览器都支持Java。这样就带来一个问题,那就是你搭建的网站,只有部分浏览能够访问,而且需要安装对应程序。后来,就把所有的操作都交给服务器处理,然后把最终生成的网页发给客户端浏览器。这样,只要有浏览器,就可以访问对应网站,且不需要安装任何程序。
Servlet的引入
Servlet是基于Java的CGI程序框架。首先,因为它是一个框架,所以就可以省去很多底层编写的工作。又因为是用Java实现的,Java程序运行于Java虚拟机,跨平台性好,便于网站迁移。
Servlet的体系架构
Servlet容器,如Tomcat,接收所有客户端请求,如 http://example.com:8080/project/oneServlet,根据"project"找到对应的项目(tomcat的server.xml保存项目映射信息),再根据"oneServlet"找到对应的Servlet(Web项目的web.xml保存Servlet映射信息),然后调用该Servlet对象的service()方法。service方法会根据请求的方式,委派给doGet、doPost、doDelete等方法进行处理。
注:Servlet的多数内容由容器实现,如Session的保存和获取,Tomcat实现内容在其子目录lib下的catalina相关包内。
Servlet的持久化
Servlet会保存其变量域的值,使其在多个请求之间保留相应变量值。Servlet容器会持久化Servlet对象。至于什么时候刷新,尚未考察,应该是在每次service()方法返回之后。
如果是CGI程序,则需要自己手动将数据写入到磁盘,这也是Servlet的优点之一。
Servlet的页面生成与JSP
如果单纯用Servlet生成页面,那么将会非常痛苦,因为这样代码里就会掺杂大量的 换行符、转义标识、“+”符号,字符串的构建以及代码阅读都非常困难。后来就有了JSP文件,整合了HTML和Java代码。使得文件内可以直接抒写HTML代码,而不需要用字符串拼接。也可以用有特殊标签包围的Java代码。(实际上JSP就是Servlet,它会被容器内会被转换成Servlet的.java文件,然后在编译成.class文件)但是,JSP还有问题没解决,那就是,负责维护JSP的开发人员必须既懂HTML又懂Java。而且两种语言混合在一起(一种程序语言,一种标记语言),在加上各种标签库,看起来比较吃力。
偏题内容:页面渲染的位置
早期是服务器把网页完全渲染好后,然后发给客户端浏览器,浏览器负责显示就可以了。但是这样的话,服务器的压力就比较大,而且响应时间会比较长,客户端要等到服务端把页面完全渲染好后才能看见页面。后来的做法,是这样的,服务器先把有基本内容的网页文件发给客户端浏览器,然后浏览器再异步地请求(如通过Ajax)获取数据,然后根据获取到的数据对网页进行渲染(例如获取到一个数组对象,然后根据数组生成一个表格,显示数据)。这样,服务器的压力就小多了,而且客户端也能较早地看见页面(尚不完整,部分数据还未加载)。
那浏览器有是怎么就知道发异步请求呢?是这样的,用javascript写全局代码,或者覆盖Vue对象中的created函数,这样浏览器一收到网页文件并加载的时候,这些JS代码就会被触发执行。
Servlet与多线程
Servlet容器维护有一个线程池用于分派处理客户端的请求。所以,多个请求可以并发,甚至并行处理。
Servlet处理会话(Session)—— 利用Cookie
HTTP是无状态协议,多次请求中,单纯靠HTTP协议,我们并不能辨别其是否是同一个人。但是,有处理会话的需求(例如购物车的实现需求),这时候就要追踪会话。追踪会话的方式有很多,最常见的是持久化Cookie。
Session-Cookie机制:Cookie是服务器发给客户端的一小段信息(包含Session的唯一标识符),浏览器收到Cookie后,把它写入到磁盘持久化。无论何时,如果访问与某个Cookie相关联的URL时,请求中就会带上这个Cookie。Servlet如果想要获取本次请求的会话,就调用HttpServletRequest.getSession()获取。getSession()方法获取Session的实现方式尚未考察,但猜测应该是根据请求中的Cookie,从Servlet容器内检索对应的Session。
Session的存活时间
Session即会话的存活时间默认是30min,但是具体情况,得看对应的Servlet容器。每个容器的会话存活时间都不尽相同。
Session的用途
Session对象的作用就是捕捉客户端与服务端交互的有用数据,如前面提到的购物车信息,还有就是Session对象可以用来保存认证信息(即是否已登录),这样多次请求中,Servlet只要确认"是否登录"状态即可,而不需要用户每次请求都登录。