一.Servlet简介
1.JavaServlet是和平台无关的服务器组件,它运行在Servlet容器中。Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,Servlet和客户的通信采用“请求/响应”的模式。
2.servlet主要用于处理jsp页面所请求的一些数据信息再转发给jsp页面给予客户端回应.
3.servlet是单实例的,即当服务器启动时实例就会生成,用户端访问的就一直是服务器启动第一次访问时生成的实例,直到关闭服务器重启,才会再次重新生成一次实例。
4.Servlet可完成如下功能:
-创建并返回基于客户请求的动态HTML页面。
-创建课嵌入到现有HTML页面中的部分HTML页面(HTML片段)。
-与其他服务器资源(如数据库或基于Java的应用程序)进行通信。
5.Servlet的框架是由两个Java包组成的:
-javax.servlet包:定义了所有的Servlet类都必须实现或扩展的通用接口和类。
-javax.servlet.http包:定义了采用HTTP协议通信的HttpServlet类。
6.Servlet的框架核心是javax.servlet.Servlet接口,所有Servlet都必须实现这一接口。在Servlet接口中定义了5个方法,其中有3个方法代表了Servlet的生命周期:
-init方法:负责初始化Servlet对象;
-service方法:负责响应客户端请求;
-destroy方法:当Servlet对象退出生命周期时,负责释放占用的资源。
7.每一个Servlet都必须要实现Servlet接口,GenericServlet是个通用的、不特定于任何协议的Servlet,它实现了Servlet接口,而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口,所以我们定义的Servlet只需要继承HttpServlet父类即可。
8.Servlet接口中定义了一个service方法,HttpServlet对该方法进行了实现,实现方式就是将ServletRequest与ServletResponse转换为HttpServeltRequest与HttpServletResponse
9.转换完毕后,会调用HttpServlet中自己定义的service方法,在该service方法中,首先获得到请求的方法名,然后根据方法名调用对应的doXXX方法,比如说请求方法为GET,那么就去调用doGet方法;请求方法为POST,那么就去调用doPost方法。
10.在HttpServlet类中所提供的doGet、doPost等方法都是直接返回错误信息,所以我们需要在自己定义的Servlet类中覆盖这些方法。
二.ServletRequest与ServletResponse
1.ServletRequest的子类可以为Servlet提供更多和特定协议相关的方法,例如:HttpServletRequest提供了读取HTTP Head信息的方法。
2.ServletRequest接口中封装了客户请求信息,如客户请求方式、参数名和参数值、客户端正在使用的协议,以及发出客户请求的远程主机信息等。ServletRequest接口还为Servlet提供了直接以二进制方式读取客户请求数据流的ServletInputStream。
3.ServletRequest接口中的主要方法:
-getAttribute 根据参数给定的属性名返回属性值
-getContentType 返回客户请求数据MIME类型
-getInputStream 返回以二进制方式直接读取客户请求数据的输入流
-getParameter 根据给定的参数名返回参数值
-getRemoteAddr 返回远程客户主机的IP地址
-getRemoteHost 返回远程客户主机名
-getRemotePort 返回远程客户主机的端口
4.ServletResponse接口为Servlet提供了返回响应结果的方法。它允许Servlet设置返回数据的长度和MIME类型,并且提供输出流ServletOutputSream。
5.ServletResponse子类可以提供更多和特和特定协议相关的方法。例如:HttpServletResponse提供了设定HTTP Head信息的方法。
6.ServletResponse接口的主要方法
-getOutputSteam 返回可以像客户端发送二进制数据的输出流对象ServletOutputStream
-getWriter 返回可以向客户端发送字符数据的PrintWriter对象
-getCharacter 返回Servlet发送的响应数据的字符编码
-getContentType 返回Servlet发送的响应数据的MIME类型
-setContentType 设置Servlet发送的响应数据的MIME类型
三.Servlet详解
1.Servlet的初始化阶段
在下列时刻Servlet容器装载Servlet:
-Servlet容器启动时自动装载某些Servlet
-在Servlet容器启动后,客户首次向Servlet发出请求
-Servlet的类文件被更新后,重新装载Servlet
Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化,在Servlet的整个生命在选后期中init方法只会被调用一次。
2.在web.xml文件里servlet元素子元素servlet-class下再增加一个子元素load-on-startup
如下:
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.bao.servlet.TestServlet</servlet-class>
<load-on-startup>8</load-on-startup>
</servlet>
则服务器启动时会按照元素中的数字顺序自动加载对应的servlet。
3.对于到达Servlet容器的客户请求,Servlet容器创建特定于这个请求的ServletRequest对象和ServletResponse对象,然后调用Servlet的service方法。service方法从ServletRequest对象获得客户请求信息、处理该请求,并通过ServletResponse对象想客户返回响应结果。
4.对于Tomcat来说,它会将客户传递过来的参数放在一个Hashtable中,该Hashtable的定义为:private Hashtable<String,String[]> paramHashStringArray=newHashtable<String,String[]>();
这是一个String->String[]的键值映射。
然后当调用getParameter(String)时则读取其中的参数。
而使用setAttribute(String)和getAttribute(String)时则存储于Hashmap中。两者差别不是太大,只是线程安全问题。
5.当Web应用被终止,或者Servlet容器终止运行,或者Servlet容器重新装载Servlet新实例时,Servlet容器会先调用Servlet的destroy
6.创建用户自己的HttpServlet类的步骤
.(1)扩展HttpServlet抽象类。
.(2)覆盖HttpServlet的部分方法。如覆盖doGet()或doPost()方法。
.(3)获取HTTP请求信息,例如通过HttpServletRequest对象来检索HTML表单所提交的数据或URL上的查询字符串。无论是HTML表单所提交的数据或URL上的查询字符串,在HttpServletRequest对象中都以参数名/参数值的形式存放,可以通过getParameter(String name)方法检索参数信息。
7.某些Servlet在web.xml文件中只有<servlet>元素而没有<servlet-mapping>元素,这样我们就无法通过url地址的方式访问这个Servlet了,这种Servlet通常会在<servlet>元素中配置一个<load-on-startup>子元素,让容器在启动的时候自动加载该Servlet,并且调用其init方法完成一些全局性的初始化工作。
8.Web应用何时被启动
当Servlet容器启动时,会启动所有的Web应用
通过控制台启动Web应用
9.ServletContext和Web应用关系
当Servlet容器启动Web应用时,并为每一个Web应用创建<唯一>的ServletContext对象。你可以把ServletContext看成是一个Web应用的服务器组件的共享内存。ServletContext中可以存放共享数据,它提供了读取或设置共享数据的方法:
-setAttribute(String name,Object object)把一个对象和一个属性名绑定,将这个对象存储在ServletContext中。
-getAttribute(String name)根据给定的属性名返回所绑定的对象
10.application的本质就是ServletContext。范围和生存周期都一样。
11.Servlet的多线程同步问题(重要)
由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的同步问题。如果在编写Servlet/JSP程序时不注意到多线程同步问题,这往往造成编写的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫名其妙的问题,对于这类随机性的问题调试难度也很大。
12.并发问题的原因之一----servlet是单实例的,所有的请求都只会访问一个servlet对象。
13.得到当前线程的名字:Thread.currentThread().getName()
14.解决同步问题的方案
-Servlet实现javax.servlet.SingleThreadModel(Servlet2.4中已经废弃该接口),此时Servlet容器将保证Servlet实例以单线程方式运行,也就是说,同一时刻,只会有一个线程执行Servlet的service()方法,效率过于低下。
-去除实例变量,使用局部变量。.........................<最好方案>
-使用同步代码块:synchronized{...}
15.Cookie是用户访问Web服务器时,服务器在用户硬盘上存放的信息。服务器可以根据Cookie来跟踪用户,这对于需要区别用户的场合(如电子商务)特别有用。
16.一个Cookie包含一堆Key/Value。下面的代码生成一个Cookie并将它写到用户的硬盘上:
Cookie theCookie=newCookie("cookieName","cookieValue");
response.addCookie(the Cookie);
17.服务器端处理时则用request的getCookie()方法得到Cookie数组。
18.比较Servlet和JSP
-有许多相似之处,都可以生成动态页面
-JSP的优点是擅长于网页制作,生成动态页面,比较直观。JSP的缺点是不容易跟踪与排错
-Servlet是纯Java语言,擅长于处理流程和业务逻辑。Servlet的缺点是生成动态网页不直观
19.跟踪客户端状态
Web服务器跟踪客户状态通常有四种方法
-建立含有跟踪数据的隐藏字段
-重写包含额外参数的url:?后加参数之类
-使用持续的Cookie
-使用Servlet API中的Session机制
四.Session详解
1.Session用于跟踪客户的状态。Session指的是在一段时间内,单个客户与Web服务器的一连串相关的交互过程。在一个Session中,客户可能会多次请求访问同一个网页,也有可能请求访问各种不同的服务器资源。
2.Session的运行机制
-当一个Session开始时,Servlet容器将创建一个HttpSession对象,在HttpSession对象中可以存放客户的状态信息(如购物车)
-Servlet容器为HttpSession分配一个唯一标识符,称为Session ID。Servlet容器把Session ID作为Cookie保存在客户的浏览器中
-每次客户发出HTTP请求时,Servlet容器可以从HttpServletRequest对象中读取Session ID,然后根据Session ID找到相应的HttpSession对象,从而获取客户的状态信息
3.HttpSession接口
.getId()
返回Session的ID
.invalidate()
使用当前的Session失效,Servlet容器会释放HttpSessiion对象占用的资源
.setAttribute(String name,Object value)
将一对name/value属性保存在HttpSession对象中
.getAttribute(String name)
根据name参数返回保存子啊TttpSession对象中的属性值
.isNew()
判断是否为新创建的Session,如果是则返回true,否则返回false
.setMaxInactiveInterval()
设定一个Session可以处于不活动状态的最大时间间隔,以秒为单位。如果超过这个时间,Session自动失效。如果设置为负数,表示不限制Session处于不活动状态的时间,默认为30分钟,整体修改时间则可以配置web.xml文件中的属性:
<session-config>
<session-timeout>30</session-timeout>
</session-config>
4.Session的生命周期
-当用户第一次访问Web应用中支持Session的某个网页时,就会开始一个新的Session。
-接下来当用户浏览这个Web应用的不同网页时,始终处于同一个Session中。
-默认情况下,JSP网页都是支持Session的,也可以通过以下语句显示声明支持Session:
<%@ page session = "true">
5.如何做到在浏览器关闭时删除session
-严格的讲,做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.onclose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。
-但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。
-实际上在项目中我们也不会这么做,而是让服务器在Session过期后自动删除。
6.为什么session.invalidate()使用后session.getId()仍然可以正常调用,而session.getAttribute()调用不了?
答:getId为何不报错,是因为session销毁并不意味着session对象被垃圾回收,对象还在,只是状态是销毁状态。而getId方法和是否销毁这个状态无关,它总是可以返回session对象的id。
7.利用session处理用户登陆的信息以及权限问题,灵活应用jsp,javaBean和Servlet。
8.注意网页跳转的安全问题,防止非正常访问的发生。
五.Filter
1.Servlet过滤器(Filter)
-Servlet过滤器能够对Servlet容器的请求和响应对象进行检查和修改。
-Servlet过滤器本身并不生成请求和响应对象,它只提供过滤作用。
-Servlet过滤器能够在Servlet被调用之前检查Request对象,修改RequestHeader和Request内容。
-在Servlet被调用之后检查Response对象,修改ResponseHeader和Response内容。Servlet过滤器负责过滤的Web组件可以是Servlet、jsp或html文件。
2.Filter接口:所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法:
-init(FilterConfig):这是Servlet过滤器的初始化方法,在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数。
-doFilter(ServletRequest,ServletResponse,FilterChain):这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL时,Servlet容器将会先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器。
-destroy():Servlet容器在销毁过滤器实例前调用该方法,在这个方法中可以释放Servlet过滤器占用的资源。
3.Filter中设置重定向时尽量用<绝对路径>,因为访问jsp与servlet的前置路径不同,所以不能统一转向到理想页面上。
4.web.xml中filter配置的顺序决定filter执行的顺序,请求时顺序经过web.xml中的配置顺序,响应返回时将会倒过来执行。
5.Filter的xml配置:
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.bao.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6.在filter配置的时候可以配置一些参数,在init方法中可以调用方法来获取之前配置好的参数。
7.在范围内有不想过滤的页面时则在doFilter方法中用request.getrequestURI()来获取请求的URI进行筛选。
六.Listener
1.Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听器在线的用户数量(近似)。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEvent se)方法,这样就可以给在线人数加1。
2.常见的监听接口有以下几个
-ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、新修改属性。
-ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法(优先于filter和servlet调用);当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法(在filter和servlet之后调用)。
3.listener的xml配置语句:
<listener>
<listener-class>com.xxx.xxx.xxx</listener-class>
</listener>
4.ServletContextAttributeEvent中getValue()方法调用时,如果动作为添加则返回添加值,如果动作为删除,则返回删除值,如果动作为替换,则返回<替换之前>的值。
5.HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发sessionCreated(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed(HttpSessionEvent se)方法。
6.HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se)方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se)方法。