如今的Java开发人员实际上可以称为“Spring开发人员”,所有的开发流程的内部细节都由Spring框架封装好的,所以我们在实际开发中就很少考虑其中的细节。然而若想成为一名高级开发工程师,而不是码农,必须对其底层的实现逻辑了如指掌。
依鄙人所见,servlet就是Java做web开发的精髓所在,完全掌握servlet非常重要。
虽然servlet使用的技术的技术比较老旧,但是它的思想是值得牢记在心的。
两台计算机通过网络实现文件共享行为,就是互联网通信。
通信角色氛围客户端和服务端,有的节点可能既是客户端又是服务端。
客户端向指定服务端发送请求,索要资源文件,并将服务端返回的二进制数据解析展示。
服务端用于接收来自于特定的客户端发送的请求,在接收到请求之后在服务端上定位被访问的资源文件,将文件内容以二进制形式通过网络发回客户端。
C/S普遍用于个人娱乐市场,比如微信、淘宝、优酷、英雄联盟等,在企业办公应用较少。
优点是安全性较高,也能降低服务端工作压力;缺点是增加客户获得服务成本(需要下载),且更新较为繁琐。
浏览器可以向任意服务器发送请求,索要资源文件,并将服务端返回的二进制数据解析展示。
服务端可以处理任意浏览器发送的请求,在接收到请求之后在服务端上定位被访问的资源文件,将文件内容以二进制形式通过网络发回浏览器。
B/S既适用于个人娱乐市场,也适用于企业日常活动。
优点是不会增加用户获得服务成本(不用下载对应软件),也不用频繁更新浏览器,缺点是服务端计算机工作压力巨大。
可以经过网络进行传输的文件
文档、图片、视频等
可以在浏览器编译执行的命令(html、css、js)
不能在浏览器执行的命令(.class等)
动态文件被索要时,需要服务器处理逻辑,将运行结果返回给浏览器。
无论是静态还是动态,都是以二进制形式返回浏览器的。
javaee的一种规范,http服务器操作动态资源文件的规范
servlet的命令、代码都是老旧代码了,不必记住它们,只要记住思想就好了。
响应对象,主要任务是:
请求对象,主要任务是:
工作原理:用户第一次手动发送请求,浏览器处理完请求后,还需要另一个servlet完成接下来的操作,就在响应协议包的状态行写302,将第二个servlet的地址写到响应头的location属性,由浏览器自动发送第二次请求,完成剩余任务。
请求次数>=2,但是只有第一次用户手动发送,其余都是浏览器自动发送
因为浏览器发送请求默认为get方式,所以重定向请求方式一定是get
缺点:需要在浏览器与服务器之间进行多次往返,大量时间消耗在往返次数上,增加用户等待服务时间。
工作原理:用户第一次手动发送请求,浏览器处理完请求后,还需要另一个servlet完成接下来的操作,就通过当前的请求对象代替浏览器向服务器发送请求,调用其完成剩余任务。
无论涉及多少个servlet,浏览器只用发起一次请求,节省浏览器与服务器之间往返速度,提高服务处理速度。
所有servlet接收的请求方式都与浏览器发送的请求方式保持一致。
四种数据共享方案
ServletContext接口
ServletContext对象称为“全局作用域对象”,每个网站都有一个,相当于一个Map,每个servlet都可以存或取其中对象。
全局作用域对象生命周期贯穿网站整个运行期间。
Cookie类
cookie是两个来自同一网站的servlet为同一用户服务时,存放当前用户私人数据的载体,只能存储字符串数据,一个cookie对象只能存储一条数据。
服务器把cookie对象创建出来,放到响应头返回给浏览器,浏览器将cookie存到缓存中,发起下次请求时,将之前保存的cookie写到请求头发送到服务器,这样另一个servlet可以从cookie中拿到数据。
默认情况,浏览器关闭,cookie对象就被销毁掉;我们可以手动设置cookie存储在硬盘上,并设置自动销毁时间。
HttpSession接口
HttpSession对象被称为“会话作用域对象”,存储在服务器中,可以存储任意数据类型的数据,使用map集合,可以存储任意数量的数据。
Tomcat为每一个HttpSession对象设置空闲时间,默认30分钟,如果当前HttpSession对象空闲时间达到30分钟,此时Tomcat认为用户已经放弃了自己的HttpSession,就会销毁掉这个HttpSession。
HttpServletRequest接口
这个对象叫做“请求作用域对象”,只能在请求转发的时候使用,因为请求转发多个servlet共用同一个request和response。
此概念了解即可。
监听器接口用于监控【作用域对象生命周期变化时刻】以及【作用域对象共享数据变化时刻】
过滤器(filter)
拦截器(intercepter)
过滤器是在servlet学的,拦截器是在springmvc学的
过滤器:实现Filter接口,重写init()、doFilter()、destroy()三个方法
拦截器:实现HandlerInterceptor接口,重写preHandle()、postHandle()、afterCompletion()三个方法。
相比过滤器,拦截器的实现方法更不好理解
拦截器是链式调用,一个应用可以存在多个拦截器,一个请求可以触发多个拦截器,每个拦截器的调用根据声明顺序依次执行。
preHandle():在请求处理前调用,如果返回false,请求直接结束,拦截器失效。
postHandle():拦截器的处理逻辑。在多个拦截器同时作用时,postHandle()的调用顺序和preHandle()相反(先进的后出)
afterCompletion():在整个请求结束后执行的逻辑。
过滤器和拦截器都体现了AOP的编程思想。
过滤器基于函数回调
拦截器基于反射(动态代理)实现(下面的方法参数省略)
我们自定义的过滤器,实现了doFilter()方法,实际上我们处理逻辑是filterChain.doFilter(),ApplicationFilterChain是这个filterChain参数的实现类,这个类里有一个doFilter(),这就是回调方法。
每个xxxFilter执行doFliter()过滤逻辑后,执行filterChain.doFilter(),实现函数回调。
过滤器实现的javax.servlet.Filter接口,是在servlet规范中定义的,也就是说过滤器依赖Tomcat等容器,所以只能在web程序中使用。
拦截器是一个spring组件,由spring容器管理,可以单独使用,不必依赖web服务器。
过滤器几乎可以对所有进入容器中的请求起作用,而拦截器只会对controller中请求或者静态资源的访问起作用
拦截器加载的时间点在spring将对象注入容器之前,所以在拦截器类中使用@Autowired注册会失效
一个过滤器实例只能在容器初始化时调用一次
拦截器充分体现了AOP思想,例如在调用某方法前实现逻辑,在调用后实现逻辑等。
一个拦截器实例在一个controller生命周期内可以多次调用。