系统开发模型
是指整合应用系统程序大的结构,经常提到的系统架构有两种:三层架构与MVC,这两种结构既有区别,又有联系。但这两种结构的使用,均是为了降低系统模块间的耦合度。
传统的JavaWeb项目的系统开发模型大体经历了四个阶段:纯JSP,JSP加JavaBean的Modle1,MVC的Model2,MVC+三层架构
纯JSP开发模型
将所有业务处理,数据显示功能都由JSP页面完成。其缺点是:JSP页面的代码结构很乱,显示功能与业务功能代码没有划分,维护与升级相当麻烦
JSP+JavaBean的Model1
这种开发模式将绝大数业务处理功能交给了专门的JavaBean来完成,而JSP页面主要来完成数据显示功能。已经较”纯JSP页面“的开发模式有了很大的改进,但该开发模式对于来自客户端的请求的解析,及对于JavaBean对象的选择和创建,仍是由JSP页面通过Java代码块等来完成。也就是说,JSP页面还承担着大量的请求解析,业务处理功能。
JavaBean根据具体的概念不同,可以分为两大类:广义JavaBean与狭义JavaBean
MVC的Model2
View:视图,为用户提供使用界面,与用户直接进行交互
Model:模型,承载数据,并对用户提交请求进行计算的模块。其分为两类:一类称为数据承载Bean,另一类称为业务处理Bean。所谓数据承载Bean是指实体类,专门承载业务数据的,如Student,User等。而业务处理Bean则是指Service或Dao对象,专门用于处理用户提交请求的
Controller:控制器,用于将用户请求转发给响应的Model进行处理,并根据Model的计算结果向用户提供相应响应。
三层架构
三层架构是指:视图层View,服务层Service,与持久层Dao。他们分别完成不同的功能
View层:表现层,视图层,也称Web层。用于接收用户提交请求的代码在这里编写
Service层:业务层,逻辑层,系统的业务逻辑要在这里完成。
Dao层:持久层,数据访问层,直接操作数据库的代码在这里编写。DAO,即Data Acess Object,数据访问对象。
为了更好的降低各层间的耦合度,在三层架构程序设计中,采用面向对象抽象编程。即上层对下层的调用,是通过接口实现的。而下层对上层的真正服务者,是下层接口的实现类。
MVC+三层架构的Model2开发模式
主要是指将MVC的业务处理Model分为两层:Service和Dao层,分别用于处理业务逻辑和持久化操作。该模式是传统的JavaWeb项目的最常用的开发模式。
Cookie
Cookie是一种进行网络会话状态跟踪的技术,由服务器端生成,保存在客户端的数据存储的载体,实现会话见数据传递。
会话是由一组请求和响应组成的,是围绕着一件相关事情所进行的请求和响应。所以这些请求和响应之间一定是需要有数据传递的,即是需要进行会话状态跟踪的。然而HTTP协议是一种无状态协议,在不同的请求见是无法进行数据传递的。此时就需要一种可以进行请求间数据传递的会话跟踪技术,Cookie就是一种这样的技术。
Cookie是由服务器生成,保存在客户端的一种信息载体。这种载体中存放着用户访问该站点的会话状态信息,只要Cookie没有被清空,或者Cookie没有失效,那么保存在其中的会话状态就有效。
用户在提交第一次请求后,由服务器生成Cookie,并将其封装到响应头中,以响应的形式发送到客户端。客户端接收到这个响应后,将Cookie保存到客户端,当客户端再次发送同类请求时,在请求中会携带保存在客户端的Cookie数据,发送到服务端,由服务器对会话进行跟踪。
Cookie是有若干键值对构成,这里的键一般称为name,值称为value,Cookie中的键值对都是字符串。
服务器端生成Cookie
在JavaEE中的javax.servlet.http包中存在一个类Cookie,就是用于完成会话跟踪的Cookie。其只有一个带参构造器。
此时客户端就会接收到Cookie,并在发送同类(资源路径相同)请求时携带Cookie,默认绑定
资源路径相同:
接收到响应Cookie
再次访问同类请求 携带Cookie
修改Cookie的绑定路径:使其只有在访问特定路径时携带
此时在访问“资源路径/new”时只会携带cookie,访问“资源路径/login”时只会携带cookie1
设置Cookie的有效期
这个值是一个整数值,单位为秒
该值大于0,表示将Cookie存放到客户端的硬盘
该值小于0,与不设置效果相同,会将Cookie存放到浏览器的缓存
该值等于0,表示Cookie一生成马上失效
在设置中查看Cookie的有效期
cookie1(也就是包含password的cookie)
而如果不设置有效期或有效期小于零则为会话结束时
服务器获取并解析Cookie
可以在浏览器中禁用Cookie,但是很多网站禁用了Cookie会影响使用。
浏览器禁用了Cookie,不意味着服务器端不会再生成Cookie,只是客户端不接收,也不会在发送同类请求时携带Cookie。
Session
即会话, 是Web开发中的一种会话状态跟踪技术,与Cookie不同在于Cookie是将会话状态保存在客户端,而Session则是将会话状态保存在服务器端。
什么是会话:从浏览器访问服务器开始,到访问服务器结束,浏览器关闭为止的这段时间内容产生的多次请求和响应,合起来叫做浏览器和服务器之间的一次会话。
Session的创建
当要想Session中存放数据数据,则使用getSession()或getSession(true),若当前存在Session则使用当前的,否则创建新的,因为存放数据是必须要有Session的。
若想要从Session中获取数据则一般使用getSession(false),因为如果当前没有Session,就不可能有Session中的数据了。无需创建新的Session。
对Session域属性空间的操作
Session是一个专门用于存放数据的集合,我们一般称这个用于存放数据的内存空间为域属性空间,简称域。HttpSeesion中具有三个方法,是专门用于对该域属性空间中进行写,读操作的。
在一个Servlet中编写如下,从requset域中获取用户提交参数,将其放置在Session域中
在另一个Servlet中编写如下,从Session域中读取数据,这样就实现了请求间的数据传递
Session的工作原理
在服务器中系统会为每个会话维护(创建)一个Session,不同的会话,对应不同的Session。
系统是如何识别不同的Session对象的?即:如何做到在同一会话过程中,一直使用的是同一个Session对象呢?
第一步:写入Session列表
服务器当前应用中的Session是以Map的形式进行管理的,这个Map称为Session列表。改Map的key为一个32位长度的随机串,这个随机串称为JsessionID,value则为Session对象的引用。
当用户第一次提交请求时,服务端Servlet中会执行request.getSession()方法后,会自动生成一个Map.Entry对象,key为一个根据某种算法新生成的JSessionID,value则为新创建的HttpSession对象。
第二步:服务器生成并发送Cookie
再将Session信息写入Session列表后,系统还会自动的将”JSESSIONID“作为name,这个32为长度的随机串作为value,以Cookie的形式存放到响应报头中。随着响应将该Cookie发送到客户端。
第三步:客户端接收并发送Cookie
客户端接收到Cookie后会将其存放到浏览器缓存中,即:只要客户端浏览器不关闭,浏览器缓存中的Cookie就不会消失。
当用户提交第二次请求时,会将缓存中的这个Cookie,伴随着请求的头部信息,一块发送到服务器。
第四步:从Session列表中查找
服务端从请求中读取到客户端发送来的Cookie,并根据Cookie的JSESSIONID的值,从Map中查找相应的key所对应的value,即Session对象,然后,对该对象的域属性进行读写操作。
Session的失效
Web开发中引入的Session超时的概念,Session的失效就是指Session的超时。若某个Session在指定的时间范围内一直未被访问,那么Session将会超时,即失效。
在web.xml中可以通过<session-config/>标签设置Session的超时时间,单位为分钟。默认Session的超时时间为30分钟,需要再次强调的是,这个时间并不是从Session被创建开始计时的生命周期时长,而是从最后一次被访问开始计时,在指定的时长内一直未被访问的时长。
通过invalidate方法使Session对象失效,session失效了(但失效的session并不为null)。如果在session失效后再通过setAttribute()方法向其中设置内容,那么访问该Servlet执行到此处时会报错Session already invalidated。
此时再在同一个会话中的通过另一个请求从Session对象中获取数据,是获取不到的,request.getSession(false)返回值为null。
Cookie禁用后的Session
首先禁用浏览器的Cookie,然后访问Servlet如下
在检查->网络中查找到其生成的key为JSESSIONID的Cookie的值为1DA9D9B5CD6C870833F53E1736DF3864
然后关闭浏览器,重新打开。以访问如下网址http://localhost:8080/javaweb/login;jsessionid=1DA9D9B5CD6C870833F53E1736DF3864
的方式访问上方Servlet,此时发现两次控制台输出的Session为同一个对象,即:服务器端认为两次请求是在同一个会话中。
以上结果说明:
在用户角度来说会话是:用户打开浏览器访问服务器端的一系列资源,关闭浏览器会话结束
但在对于服务器来说第一次被访问会话开始,session失效的时候会话结束
这也是为什么很多跟钱有关系的网站都会有退出的选项,而不是简单的关闭浏览器。退出会调用session.invalidate()方法,将绑定的数据解绑。
Cookie禁用后重定向跳转时Session的跟踪
编写代码如下,解决Cookie禁用后,Session的跟踪问题
LoginServlet
NewServlet
运行结果如下,可以得到session
没有禁用Cookie的情况下,依旧不会有问题。此时禁用Cookie反而不安全因为url包含了jsessionid
Cookie禁用后超链接跳转时session的跟踪
更改LoginServlet
也是在uri后面加上;jsessionid=...............
此时通过超链接跳转到NewServlet也能获取到当前Session。
三个域属性空间范围对比
ServletContext,即application,置入其中的域属性时整个应用范围,可以完成跨会话共享数据。
HttpSession,置入其中的域属性时会话范围的,可以完成跨请求共享数据。
HttpServletRequest,置入其中的域属性时请求范围的,可以完成跨Servlet共享数据,但这些请求必须在同一个请求中。
对于这三个域属性空间对象的使用原则是,在可以保证功能需求的前提下,优先使用小范围的。这样不仅可以节省服务器内存,还可以保证数据的安全。