Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet


一、Web简介

1、http请求
GET请求:请求获取由Request-URI所标识的资源
POST请求:向指定Request-URI所标识的资源提交数据进行处理请求
HEAD:请求获取由Request-URI所标识的资源的响应消息报头

浏览器打开一个页面:比如www.baidu.com
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第1张图片

1)第一次请求是/根,请求的地址是http://www.baidu.com
2)随后会把图片和脚本下载下来,这些图片和脚本也是单独请求的
3)每次下载也是一次请求
4)在浏览器F12 - 网络,里面可以看到每次请求的时间

可以尝试手工发http post请求
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第2张图片


2、http常用状态码
1)消息(1xx):代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束(HTTP1.0不支持)
2)成功(2xx):代表请求已成功被服务器接收、理解、并接受(200请求已成功)
3)重定向(3xx):代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明
4)请求错误(4xx):客户端看起来可能发生了错误,妨碍了服务器的处理(404请求的资源不存在)
5)服务器错误(5xx):服务器在处理请求的过程中有错误或者异常(500为服务端的源代码出现错误)

二、Servlet基础

1、Java Web开发环境

1.1、Java开发环境
下载并安装JDK,配置Java环境变量
Java EE版本的eclipse
http://jdk7.java.net

1.2、Servlet容器
1)用于管理Servlet类产生、服务、销毁这些过程
2)常用Servlet容器(Tomcat、Jetty)
3)下载Tomcat:tomcat.apache.org
4)运行并访问Tomcat,点击bin/startup.bat
主要使用右边这三个功能:
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第3张图片
5)Servlet容器和Java应用服务器(WebLogic、WebSphere、JBoss)
Tomcat提供简单的应用服务,如果要做集群、负载均衡,就需要前面加一层应用服务器做负载均衡
Tomcat很难做到对不同数据库事务的处理

1.3、IDE
Eclipse IDE for Java EE
IntelliJIDEA

2、Java Web介绍
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第4张图片

1)客户端(浏览器)发送http请求给服务器(tomcat)
2)服务器将请求封装成request对象
3)当tomcat得到信息后会调用对应的servlet
4)在调用对应方法的时候就会把request对象传过去

Web Components:Web组件
JavaBeans Components:JavaBeans组件

3、Servlet介绍
3.1、Java Servlet(server applet)
服务端的小程序

3.2、Java Servlet继承结构
1)Servlet接口(javax.servlet.Servlet)
init方法、service方法、destroy方法

2)GenericServlet(javax.servlet.GenericServlet)
对servlet接口的通用实现

3)HttpServlet(javax.servlet.http.HttpServlet)
用于http的servlet接口实现类

3.3、创建一个Servlet过程
继承HttpServlet类
重写service(或doGet、doPost)方法
在web.xml中配置Servlet

4、创建和部署Web应用
4.1、Web Project目录结构
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第5张图片

Root:根目录
Web pages:放web页面,用户可以直接访问
WEB-INF:里面的内容只有服务器才能访问,用户不能访问的
  1)web.xml:web应用的配置文件,类似于window里的注册表
  2)lib:引用第三方JAR包,JAR文件
  3)classes:自己写的类

4.2、手工建立一个web应用
javac -cp D:\JAVA\apache-tomcat-7.0.62\lib\servlet-api.jar -d . MyServlet.java
-cp:依赖的Jar包所在的classpath
-d:生成class文件的目录
例子程序:http://pan.baidu.com/s/1jIJWkaq

4.3、使用IDE创建web project
1)配置Tomcat:
Window - Preferences - Server - Runtime Environments
2)创建Dynamic Web project
New - Project - Web下的Dynamic Web Project
注:勾选Generate web.xml deployment descripter,因为Java EE还可以用注解的方式去配置servlet
例子程序:http://pan.baidu.com/s/1i59ORm1

4.4、在Tomcat中部署Web应用
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第6张图片

 一般是:将Web应用导出war包,拷贝到webapps目录,重启tomcat

三、Servlet生命周期

1、Servlet API
1.1、Servlet介绍
Servlet是java服务运用的小程序,由Servlet容器进行管理

1.2、Servlet关联的类
javax.servlet.Servlet
javax.servlet.ServletConfig
javax.servlet.IOException
javax.servlet.ServletException
javax.servlet.ServletRequest
javax.servlet.ServletResponse

1.3、Servlet常用方法
destory()
getServletConfig()
getServletInfo()
init(javax.servlet.ServletConfig)
service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)

2、HttpServlet
HttpServlet是基于HTTP协议的Servlet实现。用户创建Servlet一般继承HttpServlet

2.1、HttpServlet继承关系
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第7张图片

如果一个应用Servlet类特别多,有些Servlet很长时间未调用,可以把Servlet实例序列化写到磁盘保存,后面要用的化再反序列化

2.2、GenericServlet常用方法
destory()
getServletConfig()
getServletInfo()
init(javax.servlet.ServletConfig)
service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)

getInitParameter(java.lang.String) //获取web.xml中配置的键值对
getInitParameterNames()
getServletContext() //Servlet上下文,这个上下文实例在整个web应用里是全局共享的
getServletName()
init()
log(java.lang.String, java.lang.Throwable)
log(java.lang.String)

2.3、HttpServlet常用方法
doDelete(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
doHead(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
doOptions(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
doPut(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
doTrace(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)

重写doGet、doPost,或者service方法
在servlet中默认情况下,无论你是get还是post提交过来都会经过service()方法来处理,然后转向到doGet或是doPost方法
如果重写了service方法,那么get和post请求都执行重写的业务逻辑

3、Servlet生命周期
Java Web Server端的运用都是围绕着Servlet展开
Servlet生命周期需要结合Servlet接口中定义的方法来了解Servlet的加载、创建、服务及销毁的过程

3.1、Servlet生命周期演示
创建Servlet
配置Servlet
启动tomcat
观察

1)一个servlet就要配置一个标签
2)load-on-startup标签:
表示servlet被加载的时间点,越小越前面加载
不加这个标签默认值-1,小于0的数表示servlet被使用的时候加载
如果值为0表示,在应用程序部署后就立马加载servlet类并且实例化它
值大于0的情况下,是按照int型大小顺序加载
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第8张图片
可以看到在tomcat启动的时候就实例化了Servlet2类,init方法被调用
3)init初始化方法只调用一次
4)初始化后,以后每次访问都会调用service方法
5)servlct销毁,在servlet对象重新创建(web应用重新加载)或服务器停止时销毁

3.2、初始化参数标签
以键值对的形式,为servlet提供常量值

    test
    123456

获取初始化参数在init方法里直接从ServletConfig对象里取
在不带参数的init方法里用getInitParameter()方法获取

4、处理Servlet生命周期事件
在Servlet生命周期过程中涉及到其它相关对象创建、销毁或者更改其它对象的属性时提供对应的回调接口来实现特定的功能
通过Servlet生命周期中其它对象提供的回调接口来实现一些功能
所有Servlet生命周期中的对象,都是由Servlet容器创建和销毁

Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第9张图片

4.1、Web context对象
对应的接口ServletContext(用来知道有哪些方法可以调用,tomcat已经帮你实现了接口的方法了)
ServletContext对象由Servlet容器创建,ServletConfig对象里面有ServletContext对象的引用
一个Servlet对应一个ServletConfig,100个Servlet对应100个ServletConfig,所有Servlet共享一个ServletContext对象
在一个web应用里面,只有唯一的一个实例存在,其它的web组件都可以访问,相当于全局的对象

4.2、Session对象
对应的接口HttpSession

4.3、Request对象
HttpServletRequest对象

4.4、配置监听类

    com.iotek.jee.servlet.listener.WebContextListener

Servlet容器读取web.xml中配置的监听类
容器使用反射机制生成监听类的对象
容器创建WebContext对象、ServletContextEvent对象
容器调用contextInitialized方法,对WebContext对象初始化

注:重写了Servlet的init方法后一定要记得调用父类的init方法,否则在service/doGet/doPost方法中使用getServletContext()方法获取ServletContext对象时就会出现java.lang.NullPointerException异常

4.5、销毁过程
先销毁Servlet
调用ServletContextListener中的销毁方法
再销毁ServletContext
再销毁ServletContextListener

Servlet生命周期例子程序:http://pan.baidu.com/s/1eSIcPPo

四、Servlet表单处理

1、HttpServletRequest
HttpServletRequest是继承ServletRequest,并基于HTTP协议提供对用户请求信息进行统一封装的接口。一般由Servlet容器的提供者实现。

1.1、HttpServletRequest生命周期
一个HttpServletRequest对象在用户向Web服务器发送请求时,由servlet容器创建,并根据相关信息(请求头,请求主体)对其进行封装,然后传递给HttpServletRequest的使用者(通常是Servlet)。

一个HttpServletRequest对象只能存活于Servlet容器中
这个对象只能服务器端使用

在服务器响应客户后HttpServletRequest对象被销毁

1.2、ServletRequest接口
常用方法介绍
1)String getCharacterEncoding()
  返回此请求正文中使用的字符编码的名称,常见有UTF-8、GBK
2)void setCharacterEncoding(String env)
  重写此请求正文中使用的字符编码名称,一般用来处理中文乱码
3)String getContentType()
  返回请求正文的MIME类型,如果该类型未知,则返回null
4)ServletInputStream getInputStream()
  以二进制形式获取请求正文
5)String getParameter(String name)
  以String形式返回请求参数的值,如果该参数不存在,则返回null
  参数的名称是表单中input的name的值
6)String[] getParameterValues(String name)
  返回包含给定请求参数拥有的所有值的String对象数组
  返回表单中input所有相同name的值的数组
7)RequestDispatcher getRequestDispatcher(String s)
  返回一个RequestDispatcher对象。如果该参数路径以“/”开头,那么是相对于当前上下文
  如果这个参数不是以“/”开头的,那就是相对于当前的servlet容器的根路径
8)int getContentLength()
  返回请求正文的长度(以字节为单位),如果长度未知,则返回-1。对于HttpServlet,返回的值与CGI变量CONTENT_LENGTH的值相同
9)Object getAttribute(String name)
  以Object形式返回指定属性的值,如果不存在给定名称的属性,则返回null
10)Enumeration getAttributeNames()
  返回包含此请求可用属性的名称Enumeration。如果该请求没有可用的属性,则此方法返回一个空的Enumeration

1.3、HttpServletRequest
对http协议新增加的常用方法
1)Cookie[] getCookies()
  返回包含客户端随此请求一起发送的所有Cookie对象数组
  cookie是服务器端通过浏览器唯一可以向客户端写数据的一种机制
2)String getContextPath()
  返回请求URI指示请求上下文的那一部分。请求URI中首先出现的总是上下文路径
  在localhost:8080/后面我们会加上应用的名称,斜杠后面应用的名称就是上下文的路径
3)HttpSession getSession()
  返回与此请求关联的当前回话,如果该请求没有会话,则创建一个会话
  用户请求得到响应后连接就断开了,那么如何追踪这个用户的状态,就靠session
4)HttpSession getSession(boolean flag)
  返回与此请求关联的当前HttpSession,如果没有当前会话并且create为true,则返回一个新会话
5)String getRequestIRI()
  返回此请求的URI的一部分,从协议名称一直到HTTP请求的第一行中的查询字符串
6)String getMethode()
  返回用于发出此请求的HTTP方法的名称
  GET请求还是POST请求
7)String getQueryString()
  返回包含在请求URL中路径后面的查询字符串
  GET请求问号后面的键值对
8)String getHeader(String s)
  以String的形式返回指定请求头的值
9)Enumeration getHeaderNames()
  返回此请求包含的所有头名称的枚举
10)boolean isRequestedSessionIdValid()
  检查请求的会话ID是否仍然有效
11)boolean isRequestedSessionIdFormCookie()
  检查请求的会话ID是否是作为cookie进入的
  检查当前的session id是不是用cookie传进来的
12)boolean isRequestedSessionIdFromURL()
  检查请求的会话ID是否作为请求URL的一部分进入的
  检查session id是否作为URL的一部分传进来的

2、表单处理
2.1、HttpServletRequest获取客户请求信息
在Servlet的doGet或doPost方法中,通过HttpServletRequest对象获取用户信息。一般主要处理由超链接或者表单传递的数据
我们在客户端也可以通过AJAX技术来提交信息,这里是普通处理方式

2.2、超链接传参
1)超链接
超链接是一个小型的表单,它请求的方法是get方法
点击超链接和在浏览器地址栏输入一个地址是一样的,都是get请求

超链接路径前加“/”,相当于容器的根路径
办法一是把斜杠去掉
办法二是写webapp的绝对路径

2)超链接传参数

3)超链接中文乱码问题
控制台输出乱码问题
get请求通过调用请求对象设置编码是解决不了中文乱码的
req.setCharacterEncoding("UTF-8");

要通过String类的方法去转换字符编码
String name = req.getParameter("name");
//将字符串转为字符数组,再转换字符编码
name = new String(name.getBytes("ISO8859-1"), "UTF-8");

注:get请求的字符集都是ISO8859-1

2.3、普通表单
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第10张图片
method:提交的方式get或post,不写默认方法是get
action:提交的路径,调用servlet
input:输入方式,由type定义不同的类型

注:post请求通过调用请求对象设置编码可以解决中文乱码问题
req.setCharacterEncoding("UTF-8");

2.4、带有文件上传的表单
在表单里面上传文件,一般不要太大,大文件可以通过ftp协议来传输
form表单中有enctype="multipart/form-data",multipart/form-data表示,表单的数据是分成几个部分的

表单处理例子程序:http://pan.baidu.com/s/1eRRW2tG

2.5、获取Request中的其他信息
其他form表单类型

性别:
课程:C Java JavaEE
城市:
获取Request中的其他信息例子程序: http://pan.baidu.com/s/1qXKk6KW

3、RequestDispatcher
请求转发
是由Servlet容器创建的一个Web资源的包装器,可以用来把当前的request传递到该资源,或者把新的资源包括到当前响应中

3.1、方法
1)void forward(ServletRequest request, ServletResponse response)

Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第11张图片
将请求从一个servlet转发到服务器上的另一个资源(servlet、JSP文件或HTML文件)。就是把当前的request对象和响应,交到另外一个Java的web组件里面去
此方法允许一个servlet对请求进行初步处理,并使用另一个资源生成响应。就是请求是自己处理,响应由另一个servlet返回

2)void include(ServletRequest request, ServletResponse response)
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第12张图片
包含响应中某个资源(servlet、JSP页面和HTML文件)的内容。事实上,此方法支持编程式服务器端包含

client发请求给servlet1,servlet1将请求继续通过include方法转发给servlet2
servlet2把结果发给servlet1,servlet1再发给client(这里servlet1永远是控制者)


3)使用forward方法
此时,在servlet1中设置的响应输出会被丢弃掉,servlet1的请求和响应对象会转发到servlet2
在servlet2里面,响应对象没有设置类型,但是输出中文没有乱码
也就是说servlet1和servlet2使用的request和response对象是同一个
返回用户浏览器由servlet2返回


RequestDispatcher rd = req.getRequestDispatcher("s2");
getRequestDispatcher参数里的路径,加“/”是相对于容器根路径,不加是相对于webapp的根路径

4)使用include方法
4-1)用户发送请求,容器封装成request对象和response对象,传给servlet1
4-2)servlet1在resp设置输出1
4-3)servlet1使用include方法,到servlet2去了
4-4)servlet2在resp设置输出2,在req设置属性值1
4-5)返回servlet1,取出属性值1,在resp设置输出3
4-5)resp对象返回用户浏览器
4-6)浏览器输出顺序为:输出1、输出2、输出3
先输出servlet1打印的内容,再输出servlet2打印的内容,在输出返回到servlet1后打印的内容

4、HttpServletResponse
这个接口是辅助servlet将响应发送到客户端的对象。由servlet容器创建ServletResponse对象,并将它作为参数传递给servlet的service方法

4.1、常用方法
1)void setCharacterEncoding(String s)
  设置将发送到客户端的响应的字符编码
2)void setContentType(String s)
  设置将发送到客户端的响应的内容类型。给定内容类型可能包含字符编码,如text/html;charset=UTF-8
3)void setContentLength(int len)
  设置响应的内容正文的长度
4)ServletOutputStream getOutputStream()
  返回适用于二进制数据的响应流
5)PrintWriter getWriter()
  返回适用于文本数据的响应流

4.2、常用常量
1)SC_CONTINUE
  状态代码(100),指示客户端可以继续
2)SC_OK
  状态代码(200),指示请求正常成功
3)SC_SEE_OTHER
  状态代码(303),指示可在另一个URI之下找到该请求的响应,重定向时自动会设置
4)SC_NOT_FOUND
  状态代码(404),指示请求的资源不可用
5)SC_INTERNAL_SERVER_ERROR
  状态代码(500),指示HTTP服务器内存在错误使服务器无法完成请求

4.3、http新增的常用方法
1)void addCookie(Cookie cookie)
  将指定cookie添加到响应(可加多个)
2)void addHeader(String name, String value)
  用给定名称和值添加响应头。此方法允许响应头有多个值
3)String encodeURL(String url)
  通过将会话ID包含在指定URL中并对该URL进行编码。如果不需要编码,则返回未更改的URL
  作用是将用户的会话ID加到响应的URL中,因为客户端在浏览器会禁用了cooike
4)String encodeRedirectURL(String url)
  对指定URL进行编码,以便在sendRedirect方法中使用它,如果不需要编码,则返回未更改的URL(可判断是否需要将ID加入URL)
5)void sendError(int i, String s)
  使用指定状态将错误响应发送到客户端
6)void sendError(int i)
  使用指定状态代码并清除缓冲区将错误响应发送到客户端
7)void setStatus(int i)
  设置此响应的状态代码。用于设置没有错误时的返回状态代码(例如状态代码SC_OK或SC_MOVED_TEMPORARILY)
8)void sendRedirect(String s)
  使用指定重定向位置URL将临时重定向响应发送到客户端
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第13张图片
实验说明:
从下图可以看到,第一次请求返回302重定向,浏览器发送第二次请求
Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第14张图片
Dispatcher例子程序:http://pan.baidu.com/s/1jINuPhW

小结
HttpServletRequest继承ServletRequest,由Servlet容器的提供者实现;在用户请求服务器时,将请求信息封装在一个请求对象中
HttpServletResponse继承ServletResponse,也是由Servlet容器的提供者实现;根据用户请求将服务器对应的内容返回给用户
要注意RequestDispatcher的forword、include方法和HttpServletResponse的sendRedirect方法的区别

五、会话跟踪

1、HttpSession介绍
1.1、为什么需要会话跟踪
HTTP协议是一种无状态的协议(一般情况下,在响应客户后,服务器就与客户断开连接)
需要对用户在访问同一web应用时对用户进行跟踪(如:是否登陆等)
基于Cookie的会话:需要将会话ID写到cookie里,用户每次访问服务器时,浏览器会自动将该域名下的cookie发送到服务器

2、HttpSession
1)HttpSession是java web对用户进行会话跟踪的一个接口
2)HttpSession由Servlet容器的提供者实现
3)HttpSession通过HttpServletRequest的getSession()或getSession(boolean)方法获取
  getSession() 如果会话没有被创建则创建并返回
  getSession(boolean) 如果参数是false,如果会话存在则返回,否则返回null

2.1、常用方法
1)String getId()
  返回包含分配给此会话的唯一标识符的字符串
2)void invalidate()
  使会话无效,然后取消对任何绑定到此会话的对象的绑定
3)void setAttribute(String name, Object value)
  使用指定名称将对象绑定到此会话
4)Object getAttribute(String name)
  返回与此会话中的指定名称绑定在一起的对象
5)void removeAttribute(String name)
  从此会话中移除与指定名称绑定在一起的对象
6)void setMaxInactiveInterval(int interval)
  设置servlet容器在客户端访问之间,保持此会话最大时间间隔
7)int getMaxInactiveInterval()
  返回servlet容器在客户端访问之间,将使此会话保持打开状态的最大时间间隔
8)ServletContext getServletContext()
  返回此会话的ServletContext
9)boolean isNew()
  如果客户端还不知道该会话,或者客户端选择不加入该会话,则返回true。
  例如,如果服务器仅使用基于Cooike的会话,而客户端已经禁止了Cookie的使用,则每个请求上的会话都将是新会话
  返回true表示会话是新建立的会话

3、使用HttpSession完成登陆验证
3.1、用户没有登陆不能访问除登陆之外的Servlet
  创建index.html
  创建login.html
  创建LoginServlet和TestServlet(TestServlet需要登陆后才能访问)
  Web.xml

WEB-INF下面的内容用户不能直接访问,只有servlet容器可以访问
Session的本质是什么,是tomcat维护的一个对象,如果服务器关闭会被序列化到文件中
浏览器每次请求一个URL会自动附上该URL在本地的cookie

3.2、页面访问路径问题
1)前端跳转地址
前端页面在pages/login.html
form表单提交为


那么提交路径就是http://localhost:8080/webapp名字/pages/login
如果web.xml配置的servlet是:
   
        LoginServlet
        /login
   

两边就匹配不上了

2)如果form表单改为
那么提交路径就是http://localhost:8080/SessionTrack/pages/pages/login
所以前端页面提交路径是相对于所在目录的,web.xml中配置的servlet路径是相对于webapp根目录的

3)servlet中跳转的地址
servlet中跳转地址是相对于访问这个servlet地址的
比如:
index.html页面在http://localhost:8080/SessionTrack/index.html
页面从http://localhost:8080/SessionTrack/pages/login.html
访问http://localhost:8080/SessionTrack/login 这个servlet
处理完重定向到../index.html,就会变成http://localhost:8080/index.html

实际使用中判断用户是否登陆,可以使用后面学的filter来实现

session的例子程序:http://pan.baidu.com/s/1nu7zMT7

4、Cookie
4.1、Cookie简介
1)Cookie是Servlet发送到Web浏览器的少量信息,这些信息由浏览器保存,然后发送回服务器。
  Cookie一般用来保存会话ID来实现会话跟踪(jsessionid=XXXXXXXXXX)
2)一个Cookie拥有一个名称、一个值和一些可选属性,比如注释、路径和域限定符、最大生存时间和版本号
3)Servlet通过使用HttpServletResponse的addCookie(cookie)方法将Cookie发送到浏览器,该方法将字段添加到HTTP响应头发送到浏览器。浏览器支持每台Web服务器有20个Cookie,总共有300个Cookie,每个Cookie的大小默认为4KB
4)浏览器通过向Http请求头添加字段将Cookie返回给Servlet。可使用HttpServletResponse的getCookies()方法从请求中获取Cookie
5)Cookie通过名称和路径来进行区分

4.2、Cookie常用方法
1)Cookie(String name, String value)
  构建通过key/value保存的信息
2)void setDomain(String pattern)
  指定应在其中显示此Cookie的域
3)String getDomain()
  返回为此Cookie设置的域名
4)void setMaxAge(int expiry)
  设置Cookie的最大生存时间,以秒为单位。负值浏览器退出时删除。0值会导致删除cookie
  比如登陆论坛的时候会有设置将你的登陆信息保存一周,就是通过这个方法来设置的
5)int getMaxAge()
  返回以秒为单位指定的Cookie的最大生存时间
5)String getName()
  返回Cookie的名称。名称在创建之后不得更改
6)String getValue()
  返回Cookie的值
7)void setPath()
  指定客户端应该返回Cookie的路径。对于指定目录中的所有页面及该目录子目录中的所有页面都是可见的

5、使用Cookie
在服务器端添加Cookie(添加响应对象)
在服务器端获取Cookie(通过请求对象)
删除Cookie(Cookie生存时间)
客户端禁用Cookie(如果客户端禁用Cookie我们怎么处理)

我们在首页里面创建两个链接(读和写)

5.1、保存Cookie
程序中设置了3个Cookie:

		Cookie c1 = new Cookie("test1", "test1 cookie");
		resp.addCookie(c1);  //默认路径为webapp路径
		
		Cookie c2 = new Cookie("test2", "test2 cookie");
		c2.setPath("/");  //servlet服务器的路径
		resp.addCookie(c2);
		
		Cookie c3 = new Cookie("test3", "test3 cookie");
		c3.setPath("/temp/");
		resp.addCookie(c3);

请求头:

Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://localhost:8080/SessionTrack/
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1

响应头:

Server: Apache-Coyote/1.1
Set-Cookie: test1="test1 cookie"; Version=1
test2="test2 cookie"; Version=1; Path=/
test3="test3 cookie"; Version=1; Path=/temp/
Location: http://localhost:8080/SessionTrack/index.html
Content-Length: 0
Date: Sat, 06 May 2017 03:42:35 GMT

Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第15张图片
我们可以看到3个Cookie都保存到了电脑上

5.2、读取Cookie
获取Cookie对象的数组:

		req.setCharacterEncoding("UTF-8");
		Cookie[] cookies = req.getCookies();
		StringBuilder sb = new StringBuilder("

Cookies信息

"); for(Cookie c : cookies) { sb.append("
  • ").append(c.getName()).append("-->").append(c.getValue()).append("
  • "); } resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().write(sb.toString());

    请求头:

    Host: localhost:8080
    User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:53.0) Gecko/20100101 Firefox/53.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:8080/SessionTrack/index.html
    Cookie: test1="test1 cookie"; test2="test2 cookie"
    DNT: 1
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1

    响应头:

    Server: Apache-Coyote/1.1
    Content-Type: text/html;charset=UTF-8
    Content-Length: 80
    Date: Sat, 06 May 2017 03:46:54 GMT

    5.3、删除Cookie

    将Cookie的生存时间设置为0:

    		Cookie c1 = new Cookie("test1", "test1 cookie");
    		c1.setMaxAge(0);
    		resp.addCookie(c1);

    请求头:

    Host: localhost:8080
    User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:53.0) Gecko/20100101 Firefox/53.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:8080/SessionTrack/index.html
    Cookie: test1="test1 cookie"; test2="test2 cookie"
    DNT: 1
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1

    响应头:

    Server: Apache-Coyote/1.1
    Set-Cookie: test1="test1 cookie"; Version=1; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:10 GMT
    Location: http://localhost:8080/SessionTrack/index.html
    Content-Length: 0
    Date: Sat, 06 May 2017 07:12:44 GMT
    删除Cookie是通过设置Cookie的生存时间来实现的,如果生存时间设置为0,浏览器会把这个Cookie移除掉

    5.4、禁用Cookie
    基于Cookie来保存数据是不确定的,比如在浏览器里面可以禁用Cookie,或者不支持Cookie的客户端
    IE浏览器Cookie是写在文件里的,火狐浏览器Cookie是写在sqlite数据库里的

    使用Cookie来保存数据:
    好处是减少了服务器端资源的占用
    坏处是Cookie的数量,大小都是有限制的,用户可以禁用Cookie

    cookie相关例子程序: http://pan.baidu.com/s/1c8cOZs

    6、URL重写
    会话跟踪的另外一种实现--URL重写

    6.1、为什么要对URL重写
    客户端不支持Cookie或者禁用Cookie
    服务器端就不能通过Cookie获取jsessionid

    6.2、URL重写
    目的是将jsessionid加入到URL之后
    使用HttpServletResponse进行重写
    1)String encodeURL(String url)
      通过将会话ID包含在指定URL中并对该URL进行编码。如果不需要编码,则返回未更改的URL
    2)String encodeRedirectURL(String url)
      对指定URL进行编码,以便在sendRedirect方法中使用它,如果不需要编码,则返回未更改的URL(可判断是否需要将ID加入URL)

    这两个方法会自动将sessionid加在作为参数的url后面
    用户登录成功后,将传回的地址加上sessionid
    在访问其他页面时带上这个jsessionid就可以了

    代码:

    resp.getWriter().write("返回首页");

    浏览器URL变成:

    http://localhost:8080/SessionTrack/index.html;jsessionid=830764AFF71A493A653A0C6D3EA03CA6

    7、小结

    HttpSession
    是基于Http协议实现的,由容器创建和管理的会话对象
    Http协议是基于请求和响应的无状态的协议,所以需要会话对象

    Cookie
    一般会话跟踪最基本的实现是使用Cookie来实现的

    URL重写
    当客户端禁用了Cookie,浏览器写不了Cookie,将会话ID作为URL一部分响应到客户端

    六、过滤器与监听器

    1、过滤器
    1.1、什么是Filter
    Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter
    一个过滤器的创建、初始化、调用、销毁也是由servlet容器管理的

    通过Filter技术,开发人员可以实现用户在访问某个目标资源前后进行拦截处理。简单说,就是可以实现web容器对某资源的访问前截获并进行相关处理,也可以在某资源向web容器返回响应前进行截获并进行相关处理

    1.2、常用过滤器
    验证过滤器
    日志记录和审计过滤器
    图像转换过滤器
    数据压缩过滤器
    加密过滤器
    标记过滤器
    触发资源访问事件的过滤器
    Mime类型链过滤器
    XS/T过滤器

    1.3、Filter常用方法
    1)void init(FilterConfig filterConfig)
      Filter被初始化时调用(实例化后调用,只调用一次)
    2)void destroy()
      此方法仅在过滤器的所在线程都退出之后调用,或在过了超时时间之后调用(由servlet容器调用,只调用一次)
    3)doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      当要访问过滤器过滤的资源前后都会通过此方法。在这个过程对请求的内容或响应的数据进行处理。此方法的典型实现遵循一下模式:
        3-1)检查请求
        3-2)有选择的将带有自定义实现的请求对象装入过滤器
        3-3)有选择的将带有自定义实现的响应对象装入过滤器
        3-4)可以使用FilterChain对象的doFilter方法调用链中的下一个实体;也可以不将请求、响应传递给过滤链中的下一个实体,从而阻塞请求处理
        3-5)在调用过滤链中的下一个实体之后直接设置响应头

    1.4、Filter执行原理
    Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第16张图片
    1)用户通过浏览器请求web容器
    2)web容器根据请求的url看看有没有对应的过滤器,加载过滤器类,实例化,调用初始化方法
    3)调用doFilter方法,处理请求方法,再调用FilterChain的doFilter方法
    4)servlet处理
    5)链式返回

    1.6、使用Filter
    实现Filter的init、doFilter、destroy方法
    配置Filter
    Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第17张图片
      url-pattern配置的是一个路径下的*号

    1.7、自定义Filter
    编码处理的EncodeFilter
    用户登录验证的LoginValidationFilter

    1)filter的生命周期
    init方法被调用,线程名称:
    init thread name:localhost-startStop-1
    doFilter方法被调用,线程名称:(每次调用都会起新线程)
    doFilter thread name:http-bio-8080-exec-4
    chain doFilter end thread name:http-bio-8080-exec-4
    doFilter thread name:http-bio-8080-exec-6
    chain doFilter end thread name:http-bio-8080-exec-6
    destroy方法被调用,线程名称:
    destroy thread name:localhost-startStop-2

    我们可以看到init、doFilter、destroy线程名称是不一样的

    Filter生命周期例子程序:http://pan.baidu.com/s/1gf9U2np

    2)过滤器定义

      
          EncodingFilter
          com.iotek.jee.filter.EncodingFilter
          
              encoding
              UTF-8
          
      
    filter只对访问servlet的请求有效果,只要满足的过滤器都会执行一遍
    静态资源的访问是不需要过滤器的


    3)过滤器只能处理post请求
    那么 get请求如何统一处理中文乱码问题,之前是通过请求对象获得字符串本身,然后转换编码

    编辑eclipse中的servers下的tomcat配置server.xml(不是tomcat的安装目录)
    Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第18张图片
    将:

    修改为:

    使用请求主体的编码作为URI的编码,如果页面的编码设置为UTF-8,那么URI也会是UTF-8编码

    4)过滤器的顺序是怎么样的
    生命周期的过滤器和字符编码的过滤器都/*

    4-1) url-pattern相同的过滤器,执行的先后顺序取决于它们配置的先后顺序
    4-2) url-pattern不同的过滤器,执行顺序取决于过滤范围,范围最广的先执行,范围最小的最后执行

    过滤器例子程序: http://pan.baidu.com/s/1c8JbNg

    2、监听器
    2.1、Servlet中的相关监听器
    在其相关对象(ServletContext、HttpSession、ServletRequest)创建、销毁或者对其属性进行操作时会触发监听(会回调)
    根据要实现的功能选择实现要监听的接口并配置
    常用的监听

    2.2、Servlet中的相关监听器
    Java基础之《Servlet+JSP(JavaEE开发进阶Ⅰ)》--Servlet_第19张图片
    哪些对象可以被监听?
    Web context对应的类型是ServletContext
    Session对应的类型是HttpSession
    Request对应ServletRequest

    2.3、创建ServletContext监听器
    实现ServletContextListener接口
    ...
    web.xml配置:

      
      	com.iotek.jee.listener.WebContextListener
      
      
      	com.iotek.jee.listener.WebContextAttrListener
      
      
      	com.iotek.jee.listener.SessionListener
      
      
      	com.iotek.jee.listener.SessionAttrListener
      
      
      	com.iotek.jee.listener.RequestListener
      
      
      	com.iotek.jee.listener.RequestAttrListener
      

    2.4、当一个web应用启动的时候

    1)
    首先创建ServletContext,跟着调用ServletContext监听类的方法(初始化方法)
    会将Tld的一个缓存放在ServletContext里面

    WebContextListener contextInitialized org.apache.catalina.core.ApplicationContextFacade@f44210
    WebContextAttrListener
     added name:org.apache.jasper.compiler.TldLocationsCache 
    value:org.apache.jasper.compiler.TldLocationsCache@1015905
    2)
    当我们通过浏览器对服务器发送一个请求的时候,就会创建请求对象
    request对象初始化时,就会调用Request监听类

    tomcat替换了里面的属性值(ASYNC_SUPPORTED)--是否支持异步操作

    当在浏览器里看到页面展示时,响应就结束了,请求对象被销毁掉了

    RequestListener initialized org.apache.catalina.connector.Request@1dbb74a
    RequestAttrListener replaced name:org.apache.catalina.ASYNC_SUPPORTED value:true
    RequestListener destroyed org.apache.catalina.connector.Request@1dbb74a
    3)

    点击超链接访问

    RequestListener initialized org.apache.catalina.connector.Request@3fb245
    RequestAttrListener replaced name:org.apache.catalina.ASYNC_SUPPORTED value:true
    ServletContext add
    WebContextAttrListener added name:context value:test...
    ServletContext added
    ServletContext replace
    WebContextAttrListener replaced name:context value:test...
    ServletContext replaced
    ServletContext remove
    WebContextAttrListener removed name:context value:test replace
    ServletContext removed
    ------------------------------
    HttpSession add
    SessionAttrListener added name:session value:session...
    HttpSession added
    HttpSession replace
    SessionAttrListener replaced name:session value:session...
    HttpSession replaced
    HttpSession remove
    SessionAttrListener removed name:session value:session replace
    HttpSession removed
    ------------------------------
    Request add
    RequestAttrListener added name:request value:req...
    Request added
    Request replace
    RequestAttrListener replaced name:request value:req...
    Request replaced
    Request remove
    RequestAttrListener removed name:request value:req replace
    Request removed
    RequestListener destroyed org.apache.catalina.connector.Request@3fb245
    监听器例子程序: http://pan.baidu.com/s/1i5OKapf

    2.5、统计网站在线客户数
    用户第一次访问时总数加一(不允许重复增加)
    在用户退出时(Session)过期时总数减一
    实现HttpSessionListener
    配置监听

    tomcat对Session默认的过期时间是30分钟,在tomcat的web.xml文件中:

    
        30
    

    有两种方式设置session的过期时间:

    1)设置session对象的属性

    session.setMaxInactiveInterval(30); //单位是秒

    2)在webapp的web.xml中覆盖tomcat的配置

      
          1 
      

    3)设置session立即过期

    session.invalidate();
    有些网站登录完成之后,有个退出,这个退出就是在调用session对象的invalidate()方法

    2.6、操作过程
    使用eclipse内置浏览器:
    当前用户数是1

    使用IE浏览器:
    当前用户数是2

    使用firefox浏览器:
    当前用户数是3

    刷新eclipse内置浏览器:
    当前用户数是3

    等30秒后再刷新:
    当前用户数是1

    统计在线数的例子程序: http://pan.baidu.com/s/1slvxGtf


    你可能感兴趣的:(JAVA基础)