目录
Servlet的概念,JSP与Servlet的区别
Servlet的生命周期
Servlet中的session的工作原理,以及设置过期时间的方式
Servlet中的filter的应用场景
JSP的动态include和静态include
web.xml的作用
Servlet的线程安全问题
servlet是基于java技术的web组件,由容器管理并产生动态的内容,Servlet引擎作为web服务器的扩展,提供支持servlet的功能。Servlet技术带给程序员最大的优势是它可以处理客户端传来的HTTP请求,并返回一个响应。
SUN首先发展出SERVLET,其功能比较强劲,体系设计也很先进,只是,它输出HTML语句还是采用了老的CGI方式,是一句一句输出,所以,编写和修改HTML非常不方便。 后来SUN推出了类似于ASP的镶嵌型的JSP,把JSP TAG镶嵌到HTML语句中,这样,就大大简化和方便了网页的设计和修改。新型的网络语言如ASP,PHP,JSP都是镶嵌型的SCRIPT语言。
JSP与Servlet的区别:
1、JSP在本质上就是Servlet,但是两者的创建方式不一样。
2、Servlet完全是JAVA程序代码构成,擅长于流程控制和事务处理,通过Servlet来生成动态网页很不直观。
3、JSP由HTML代码和JSP标签构成,可以方便地编写动态网页。
因此在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页。在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层。JSP是Servlet技术的扩展,JSP编译后是“类servlet”,本质上就是Servlet的简易方式。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来,而JSP是Java和HTML组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。
现在基本上不会去用JSP编写页面,当然初学者应该学习一下,freemaker也用的比较较少了,现在主要使用前后端分离的技术。
Servlet遵循严格的生命周期,在每个Servlet的实例的生命中有三种类型的事件,这三种事件对应于由Servlet引擎所唤醒的三个方法:
(1)init()。当servlet第一次被装载时,Servlet引擎会调Servlet的init()方法,只调用一次。如果某个Sevlet需要特殊的初始化需要。那么Servlet编写人员可以重写该方法来执行初始化任务。这是一个可选的方法。如果某个Servlet不需要初始化,那么默认情况下将调用它父类的init方法。系统保证,在init方法成功完成以前,是不会调用Servlet去处理任何请求的。
(2)service()。这是Servlet最重要的方法,是真正处理请求的地方。对于每个请求,Servlet引擎将调用Servlet的service()方法,并把Servlet请求对象和Servlet响应对象作为参数传递给它。
(3)destroy()。这是相对于init的可选方法,当Servlet即将被卸载时由Servlet引擎来调用,这个方法用来清除并释放在init方法中所分配的资源。
Servlet的生命周期可以被归纳为以下几步:
(1) 装载Servlet,这一项操作一般是动态执行的。然而,Servlet通常会提供一个管理的选项,用于在Servlet启动时强制装载和初始化特定的Servlet;
(2) Server创建一个Servlet实例;
(3) Server调用Servlet的 init() 方法;
(4) 一个客户端请求到达Server;
(5) Server创建一个请求对象;
(6) Server创建一个响应对象;
(7) Server激活Servlet的service()方法,传递请求和响应对象作为参数;
(8) service()方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息;
(9) service()方法使用响应对象的方法。将响应传回Server,最终到达客户端。service()方法可能激活其他方法以处理请求。如doGet(),doPost()或其他程序员自己开发的方法;
(10) 对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此servlet的service()方法,将这两个对象作为参数传递给它,如此重复以上的循环,但无需再次调用init()方法,Servlet一般只初始化一次;
(11) 当Server不再需要Servlet时,比如当Server要关闭时,Server调用Servlet的destroy。
session对应的中文翻译是会话。会话指的是从用户打开浏览器访问一个网站开始,无论在这个网站中访问了多少页面,点击了多少链接,都属于同一个会话。 直到该用户关闭浏览器为止,都属于同一个会话。
session保存在服务器,而sessionId通过Cookie发送给客户端,但这个Cookie的生命不一,即只在浏览器内存中存在,也就是说如果用户关闭了浏览器,那么这个Cookie就丢失了。当用户再次打开浏览器访问服务器时,就不会有sessionId发送给服务器,那么服务器会认为你没有session,所以服务器会创建一个session,并在响应中把sessionId中到Cookie中发送给客户端。你可能会说,那原来的session对象会怎样?当一个session长时间没人使用的话,服务器会把session删除了!这个时长在Tomcat中配置是30分钟,可以在${CATALANA}/conf/web.xml找到这个配置,当然你也可以在自己的web.xml中覆盖这个配置!
web.xml
30
一般web系统都需要控制session自动失效的时间,从而控制用户访问系统超时。设置session失效有以下三种方式:
1、在主页面或者公共页面中加入:session.setMaxInactiveInterval(3600);参数单位是秒,即在没有活动1小时后,session将失效。注意:这里session设置的时间是根据服务器来计算的,而不是客户端。所以如果是在调试程序,应该是修改服务器端时间来测试,而不是客户端。
2、较通用的设置session失效时间的方法是在项目的web.xml中设置。
3、直接在应用服务器中设置,例如:若容器是tomcat,可以在tomcat目录下conf/web.xml中设置。
找到
注意:如果上述三个地方如果都设置了,有个优先级的问题,从高到低:(1)>(2)>(3)
◆ 通过配置参数encoding指定用何种字符编码,已处理参数中的中文问题;
◆ 禁止浏览器缓存所有动态页面的过滤器;
◆ 控制浏览器缓存页面中的静态资源的过滤器;
◆ 使用Filter实现URL级别的权限认证(在实际开发中我们经常把一些执行敏感操作的servlet映射到一些特殊目录中,并用filter把这些特殊目录保护起来,限制只能拥有相应访问权限的用户才能访问这些目录下的资源。);
◆ 实现用户自动登陆的过滤器,在用户登陆成功后,发送一个名称为user的cookie给客户端,cookie的值为用户名和md5加密后的密码。编写一个AutoLoginFilter,这个filter检查用户是否带有名称为user的cookie来,如果有,则调用dao查询cookie的用户名和密码是否和数据库匹配,匹配则向session中存入user对象(即用户登陆标记),以实现程序完成自动登陆。
(了解即可,现在已基本不使用jsp)
◆ 静态include 用 include 伪码实现 ,不会检查所含文件的变化,适用于包含静态页面 <%@ include file="included.htm" %> 。先将文件的代码被原封不动地加入到了主页面从而合成一个文件,然后再进行翻译;
◆ 动态 INCLUDE 用 jsp:include 动作实现
一个web中完全可以没有web.xml文件,也就是说,web.xml文件并不是web工程必须的。web.xml文件是用来配置:欢迎页、servlet、filter等的。当你的web工程没用到这些时,你可以不用web.xml文件来配置你的web工程。 而且web.xml的模式文件中定义的标签并不是定死的,模式文件也是可以改变的,一般来说,随着web.mxl模式文件的版本升级,里面定义的功能会越来越复杂,也即标签元素的种类会越来越多,但有些是不常用的,我们只需记住一些常用的就可以了。
Servlet 默认是单例模式,在web 容器中只创建一个实例,所以多个线程同时访问servlet的时候,Servlet是线程不安全的。那么 web 容器能为每个请求创建一个Servlet的实例吗?当然是可以的,只要Servlet实现SingleThreadModel接口,就可以了。
Servlet是单例多线程的。每个Servlet会根据请求来新建线程。也就是说你接到一个请求到Servlet,这个Servlet就会运行一个Thread。 Servlet存在线程安全的风险,解决servlet线程安全有如下三个方案:
1)实现 SingleThreadModel 接口(不建议)
该接口为每次请求创建一个servlet实例。此接口没有方法,跟Serializable接口一样只是一个标识接口。如果一个Servlet被这个接口指定,那么在这个Servlet中的service()方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。
注意!!!SingleThreadModel并不能解决所有的线程安全问题。例如,会话属性和静态变量仍然可以同时通过多线程的多个请求访问,即使用实现SingleThreadModel 接口的 servlet。建议开发人员采取其他方法来解决这些问题,而不是实现此接口,SingleThreadModel这个接口 Servlet API 2.4版本过时,不推荐使用,因为它存在性能问题。
2)同步对共享数据的操作
使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段;
3)避免使用实例变量
线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。