day08
3 Web开发入门
3.1 引入
之前的程序: java桌面程序,控制台控制,socket gui界面。javase规范
现在和以后的程序:java web程序。浏览器控制。javaee规范
3.2 软件的结构
C/S (Client - Server 客户端-服务器端)
典型应用:QQ软件 ,飞秋,红蜘蛛。
特点:
1)必须下载特定的客户端程序。
2)服务器端升级,客户端升级。
B/S (Broswer -Server 浏览器端- 服务器端)
典型应用: 腾讯官方(www.qq.com) 163新闻网站, 传智官网(俗称:网站)
特点:
1)不需要安装特定的客户端(只需要安装浏览器即可!!)
2)服务器端升级,浏览器不需要升级!!!!
javaweb的程序就是b/s软件结构!!!
3.3 服务器
从物理上来说,服务器就是一台PC机器。8核,8G以上,T来计算,带宽100M
web服务器:PC机器安装一个具有web服务的软件,称之为web服务器
数据库服务器:PC机器安装一个具有数据管理件服务的软件,称之为数据库服务器。
邮件服务器:PC机器安装一个具有发送邮件服务的软件,称之为邮件服务器。
3.4 web服务软件
web服务软件的作用:把本地的资源共享给外部访问。
3.5 常见的市面上web服务软件
javase的规范,包含IO流,线程,集合,socket编程。。。。
WebLogic: BEA公司的产品。 收费的。支持JavaEE规范。
WebSphere: IBM公司的产品。收费的。支持JavaEE规范
JBoss: Redhat公司的产品。收费的。支持JavaEE规范
Tomcat: 开源组织Apache的产品。免费的。支持部分的JavaEE规范。(servlet、jsp。jdbc,但 ejb, rmi不支持)
总结下tomcat的三种部署方式:
第一种:
非常简单,直接将 web 项目文件(一般是复制生成的war包)复制到tomcat的webapps目录中。
第二种:
在本地tomcat的conf目录中,新建Catalina/localhost目录(这里要注意文件名的大小写),然后在该目录下新建一个xml文件,名字不可以随意取,要和path后 的名字一致,我这里就应该是jstore.xml文件,它的具体内容为:
<Context docBase="C:\work\jstore\web" path="/jstore" reloadable="true"/>
1
第三种:
在tomcat中的conf目录下的server.xml文件中,在<Host/>节点中添加一个context,具体为:
<Context Path="/jstore"Docbase="C:\work\jstore\WebContent" Debug="0" Privileged="True" Reloadable="True"></Context>
这里的 Reloadable= “true” 这个属性是指tomcat在运行状态下会自动检测应用程序的WEB-INF/classes和WEB-INF/lib目录下的class文件,如果监测到有class文件有改动,服务器自动加载新的web应用程序,可以在不重起tomcat的情况下改变应用程序,也就是热部署;
一般我们会在开发阶段将Reloadable属性设为true,有助于调试servlet和其它的class文件,但是由于这样会增加服务器的运行负荷,损耗系统性能,在项目运行阶段建议将它设为false。
总结:
①、第一种方法比较普通,但是我们需要将编译好的项目重新 copy 到 webapps 目录下,多出了两步操作
②、第三种方法直接在 server.xml 文件中配置,但是从 tomcat5.0版本开始后,server.xml 文件作为 tomcat 启动的主要配置文件,一旦 tomcat 启动后,便不会再读取这个文件,因此无法再 tomcat 服务启动后发布 web 项目
③、第二种方法是最好的,每个项目分开配置,tomcat 将以\conf\Catalina\localhost 目录下的 xml 文件的文件名作为 web 应用的上下文路径,而不再理会 <Context>中配置的 path 路径,因此在配置的时候,可以不写 path。
通常我们使用第三种方法
4 Tomcat基本使用
4.1 下载并按照
1)到apache官网。www.apache.org http://jakarta.apache.org(产品的主页)
2)
安装版:window (exe、msi) linux(rmp)
压缩版:window(rar,zip) linux(tar,tar.gz)学习时候使用
3)运行和关闭tomcat
3.1 启动软件
a)找到%tomcat%/bin/startup.bat ,双击这个文件
b)弹出窗口,显示信息(不要关闭次窗口)
c)打开浏览器,输出以下地址
http://localhost:8080
d)看到一只猫画面,证明软件启动成功!
3.3 关闭软件
a)找到%tomcat%/bin/shutdown.bat,双击这个文件即可!
c)打开浏览器,输出以下地址。看到“无法连接”(最好先清空浏览器缓存)
4.2 tomcat软件使用的常见问题
1)闪退问题
原因:tomcat软件是java语言开发的。 tomcat软件启动时,会默认到系统的环境变量中查找一个名称叫JAVA_HOME的变量。这个变量的作用找到tomcat启动所需的jvm。
解决办法; 到环境变量中设置JAVA_HOME的变量
JAVA_HOME= C:\Program Files\Java\jdk1.6.0_30 (注意别配置到bin目录下)
2)端口占用的错误
原因: tomcat启动所需的端口被其他软件占用了!
解决办法:
a)关闭其他软件程序,释放所需端口
b)修改tomcat软件所需端口
找到并修改%tomcat%/conf/server.xml文件
<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> |
3)CATALINA环境变量问题
原因: tomcat软件启动后,除了查找JAVA_HOME后,还会再查找一个叫CATALINA_HOME变量,这个变量的作用是设置tomcat的根目录。
解决办法:建议不要设置CATALINA_HOME变量。检查如果有的话,清除掉!!!
4.3 体验tomcat软件作用
webapps目录: tomcat共享目录。需要共享的本地资源放到此目录中。
4.4 URL
URL全名叫统一资源定位符,用于定位互联网的资源。
问题: http://localhost:8081/myweb/test.html 看到文件?
http:// 协议。http协议。
localhost 域名。为了找到IP地址。
本地域名: localhost
外部域名:www.baidu.com
8081 端口。软件监听的
8080: tomcat默认的端口
3306:mysql数据库的端口
1521: orace数据库的端口。
/myweb: web应用的名称。默认情况下,在webapps目录下找
/test.html : 资源名称。
5 Tomcat的目录结构
|-bin: 存放tomcat的命令。
catalina.bat 命令:
startup.bat -> catalina.bat start
shutdown.bat - > catalina.bat stop
|- conf: 存放tomcat的配置信息。其中server.xml文件是核心的配置文件。
|-lib:支持tomcat软件运行的jar包。其中还有技术支持包,如servlet,jsp
|-logs:运行过程的日志信息
|-temp: 临时目录
|-webapps: 共享资源目录。web应用目录。(注意不能以单独的文件进行共享)
|-work: tomcat的运行目录。jsp运行时产生的临时文件就存放在这里
6 Web应用的目录结构
|- WebRoot : web应用的根目录
|- 静态资源(html+css+js+image+vedio)
|- WEB-INF : 固定写法。
|-classes: (可选)固定写法。存放class字节码文件
|-lib: (可选)固定写法。存放jar包文件。
|-web.xml
注意:
1)WEB-INF目录里面的资源不能通过浏览器直接访问
2)如果希望访问到WEB-INF里面的资源,就必须把资源配置到一个叫web.xml的文件中。
7 手动开发动态资源
7.1 静态资源和动态资源的区别
静态资源: 当用户多次访问这个资源,资源的源代码永远不会改变的资源。
动态资源:当用户多次访问这个资源,资源的源代码可能会发送改变。
7.2 动态资源的开发技术
Servlet : 用java语言来编写动态资源的开发技术。
Servlet特点:
1)普通的java类,继承HttpServlet类,覆盖doGet方法
2)Servlet类只能交给tomcat服务器运行!!!!(开发者自己不能运行!!!)
Servlet手动编写步骤:
1)编写一个servlet程序,继承HttpServlet
/**
* 第一个servlet程序
* @author APPle
*
*/
public class HelloServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//解决中文乱码问题
resp.setContentType("text/html;charset=utf-8");
//向浏览器输出内容
resp.getWriter().write("这是第一个servlet程序。当前时间为:"+new Date());
}
}
2)找到HelloServlet类的class字节码,然后把拷贝到tomcat的一个web应用中WEB-INF/classes目录下。
3)在当前web应用下的web.xml文件配置Servlet。
<!-- 配置一个servlet程序 -->
<servlet>
<!-- servlet的内部名称 ,可以自定义-->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet类名: 包名+简单类名-->
<servlet-class>gz.itcast.d_servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<!-- servlet的内部名称,和上面的名称保持一致!!!-->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet的访问名称: /名称 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
4)启动tomcat服务器,运行访问
访问servlet: http://localhost:8080/myweb/ hello
8 工具开发动态资源
1)创建web project (javaweb工程)
2)在WebRoot下建立静态资源文件,
3)在src下建立动态资源文件
3.1 new -> Servlet( servlet的代码生成器)
3.2 写pacakge -> class名 -> 修改mapping url
4)关联tomcat服务器
4.1 window-> Preferences - > MyEcplise -> servers -> Tomcat 6.x (注意一定要enable)
5)部署web project应用。(拷贝web应用到tomcat的webapps目录下)
6)启动tomcat服务器
7)访问servlet
http://localhost:8081/day08_web/hello
DAY09
2 Http协议入门
2.1 什么是http协议
http协议: 对浏览器客户端 和 服务器端 之间数据传输的格式规范
2.2 查看http协议的工具
1)使用火狐的firebug插件(右键->firebug->网络)
2)使用谷歌的“审查元素”
3)使用系统自带的telnet工具(远程访问工具)
a)telnet localhost 8080 访问tomcat服务器
b)ctrl+] 回车 可以看到回显
c)输入请求内容
GET /day09/hello HTTP/1.1 Host: localhost:8080 |
d)回车,即可查看到服务器响应信息。
2.3 http协议内容
请求(浏览器-》服务器) GET /day09/hello HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive |
响应(服务器-》浏览器) HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Length: 24 Date: Fri, 30 Jan 2015 01:54:57 GMT
this is hello servlet!!! |
3 Http请求
GET /day09/hello HTTP/1.1 -请求行 Host: localhost:8080 --请求头(多个key-value对象) User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive --一个空行 name=eric&password=123456 --(可选)实体内容 |
3.1 请求行
GET /day09/hello HTTP/1.1
#http协议版本
http1.0:当前浏览器客户端与服务器端建立连接之后,只能发送一次请求,一次请求之后连接关闭。
http1.1:当前浏览器客户端与服务器端建立连接之后,可以在一次连接中发送多次请求。(基本都使用1.1)
#请求资源
URL: 统一资源定位符。http://localhost:8080/day09/testImg.html。只能定位互联网资源。是URI 的子集。
URI: 统一资源标记符。/day09/hello。用于标记任何资源。可以是本地文件系统,局域网的资源(//192.168.14.10/myweb/index.html), 可以是互联网。
#请求方式
常见的请求方式: GET 、 POST、 HEAD、 TRACE、 PUT、 CONNECT 、DELETE
常用的请求方式: GET 和 POST
表单提交:
<form action="提交地址" method="GET/POST">
<form>
GET vs POST 区别
1)GET方式提交
a)地址栏(URI)会跟上参数数据。以?开头,多个参数之间以&分割。
GET /day09/testMethod.html?name=eric&password=123456 HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/day09/testMethod.html Connection: keep-alive |
b)GET提交参数数据有限制,不超过1KB。
c)GET方式不适合提交敏感密码。
d)注意: 浏览器直接访问的请求,默认提交方式是GET方式
2)POST方式提交
a)参数不会跟着URI后面。参数而是跟在请求的实体内容中。没有?开头,多个参数之间以&分割。
POST /day09/testMethod.html HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/day09/testMethod.html Connection: keep-alive
name=eric&password=123456 |
b)POST提交的参数数据没有限制。
c)POST方式提交敏感数据。
3.2 请求头
Accept: text/html,image/* -- 浏览器接受的数据类型 Accept-Charset: ISO-8859-1 -- 浏览器接受的编码格式 Accept-Encoding: gzip,compress --浏览器接受的数据压缩格式 Accept-Language: en-us,zh- --浏览器接受的语言 Host: www.it315.org:80 --(必须的)当前请求访问的目标地址(主机:端口) If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT --浏览器最后的缓存时间 Referer: http://www.it315.org/index.jsp -- 当前请求来自于哪里 User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) --浏览器类型 Cookie:name=eric -- 浏览器保存的cookie信息 Connection: close/Keep-Alive -- 浏览器跟服务器连接状态。close: 连接关闭 keep-alive:保存连接。 Date: Tue, 11 Jul 2000 18:23:51 GMT -- 请求发出的时间 |
3.3 实体内容
只有POST提交的参数会放到实体内容中
3.4 HttpServletRequest对象
HttpServletRequest对象作用是用于获取请求数据。
核心的API:
请求行:
request.getMethod(); 请求方式
request.getRequetURI() / request.getRequetURL() 请求资源
request.getProtocol() 请求http协议版本
请求头:
request.getHeader("名称") 根据请求头获取请求值
request.getHeaderNames() 获取所有的请求头名称
实体内容:
request.getInputStream() 获取实体内容数据
package gz.itcast.b_request;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
注意:tomcat服务器首先会调用servlet的service方法,然后在service方法中再根据请求方式来分别调用对应的doXX方法
* (例如,如果是GET请求方式,在service方法中调用doGet方法)
*
* 因为最常的请求方式是GET 和POST,所以编写servlet程序,只需要覆盖doGet和doPost即可!!!!
/**
* 请求数据的获取
* @author APPle
*
*/
public class RequestDemo1 extends HttpServlet {
/**
* 1)tomcat服务器接收到浏览器发送的请求数据,然后封装到HttpServetRequest对象
* 2)tomcat服务器调用doGet方法,然后把request对象传入到servlet中。
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 3)从request对象取出请求数据。
*/
t1(request);
t2(request);
}
// 为了接收POST方式提交的请求
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp)
throws ServletException, IOException {
/**
* 3.3 请求的实体内容
*/
InputStream in = request.getInputStream(); //得到实体内容
byte[] buf = new byte[1024];
int len = 0;
while( (len=in.read(buf))!=-1 ){
String str = new String(buf,0,len);
System.out.println(str);
}
}
private void t2(HttpServletRequest request) {
/**
* 3.2 请求头
*/
String host = request.getHeader("Host"); //根据头名称的到头的内容
System.out.println(host);
//遍历所有请求头
Enumeration<String> enums = request.getHeaderNames(); //得到所有的请求头名称列表
while(enums.hasMoreElements()){//判断是否有下一个元素
String headerName = enums.nextElement(); //取出下一个元素
String headerValue = request.getHeader(headerName);
System.out.println(headerName+":"+headerValue);
}
}
private void t1(HttpServletRequest request) {
/**
* 3.1 请求行 格式:(GET /day09/hello HTTP/1.1)
*/
System.out.println("请求方式:"+request.getMethod());//请求方式
System.out.println("URI:"+request.getRequestURI());//请求资源
System.out.println("URL:"+request.getRequestURL());
System.out.println("http协议版本:"+request.getProtocol());//http协议
}
}
3.8 传递的请求参数如何获取
GET方式: 参数放在URI后面
POST方式: 参数放在实体内容中
获取GET方式参数:
request.getQueryString();
获取POST方式参数:
request.getInputStream();
问题:但是以上两种不通用,而且获取到的参数还需要进一步地解析。
所以可以使用统一方便的获取参数的方式:
核心的API:
request.getParameter("参数名"); 根据参数名获取参数值(注意,只能获取一个值的参数)
request.getParameterValue("参数名“);根据参数名获取参数值(可以获取多个值的参数)
request.getParameterNames(); 获取所有参数名称列表
package gz.itcast.b_request;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 获取GET方式和Post方式提交的参数
* @author APPle
*
*/
public class RequestDemo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 设置参数查询的编码
* 该方法只能对请求实体内容的数据编码起作用。POST提交的数据在实体内容中,所以该方法对POST方法有效!
* GET方法的参数放在URI后面,所以对GET方式无效!!!
*/
request.setCharacterEncoding("utf-8");
/* System.out.println("GET方式");
//接收GET方式提交的参数
String value = request.getQueryString();
System.out.println(value);*/
/**
* 统一方便地获取请求参数的方法
*/
System.out.println(request.getMethod()+"方式");
//getParameter(name): 根据参数名得到参数值(只能获取一个值的参数)
String name = request.getParameter("name");
/**
* 手动重新解码(iso-8859-1 字符串-> utf-8 字符串)
*/
/*if("GET".equals(request.getMethod())){
name = new String(name.getBytes("iso-8859-1"),"utf-8");
}*/
String password = request.getParameter("password");
/*if("GET".equals(request.getMethod())){
password = new String(password.getBytes("iso-8859-1"),"utf-8");
}*/
System.out.println(name+"="+password);
System.out.println("=============================");
Enumeration<String> enums = request.getParameterNames();
while( enums.hasMoreElements() ){
String paramName = enums.nextElement();
//如果参数名是hobit,则调用getParameterValues
if("hobit".equals(paramName)){
/**
* getParameterValues(name): 根据参数名获取参数值(可以获取多个值的同名参数)
*/
System.out.println(paramName+":");
String[] hobits = request.getParameterValues("hobit");
for(String h: hobits){
/* if("GET".equals(request.getMethod())){
h = new String(h.getBytes("iso-8859-1"),"utf-8");
}*/
System.out.print(h+",");
}
System.out.println();
//如果不是hobit,则调用getParameter
}else{
String paramValue = request.getParameter(paramName);
/*
if("GET".equals(request.getMethod())){
paramValue = new String(paramValue.getBytes("iso-8859-1"),"utf-8");
}*/
System.out.println(paramName+"="+paramValue);
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*System.out.println("POST方式");
InputStream in = request.getInputStream();
byte[] buf = new byte[1024];
int len = 0;
while( (len=in.read(buf))!=-1 ){
System.out.println(new String(buf,0,len));
}*/
/**
* 统一方便地获取请求参数的方法
*/
/*System.out.println("POST方式");
//根据参数名得到参数值
String name = request.getParameter("name");
String password = request.getParameter("password");
System.out.println(name+"="+password);
System.out.println("=============================");
Enumeration<String> enums = request.getParameterNames();
while( enums.hasMoreElements() ){
String paramName = enums.nextElement();
String paramValue = request.getParameter(paramName);
System.out.println(paramName+"="+paramValue);
}*/
//一定调用doGet方式
this.doGet(request, response);
}
}
3.9 请求参数编码问题
修改POST方式参数编码:
request.setCharacterEncoding("utf-8");
修改GET方式参数编码:
手动解码:String name = new String(name.getBytes("iso-8859-1"),"utf-8")
4 Http响应
HTTP/1.1 200 OK --响应行 Server: Apache-Coyote/1.1 --响应头(key-vaule) Content-Length: 24 Date: Fri, 30 Jan 2015 01:54:57 GMT --一个空行 this is hello servlet!!! --实体内容 |
4.1 响应行
#http协议版本
#状态码: 服务器处理请求的结果(状态)
常见的状态:
200 : 表示请求处理完成并完美返回
302: 表示请求需要进一步细化。
404: 表示客户访问的资源找不到。
500: 表示服务器的资源发送错误。(服务器内部错误)
#状态描述
4.2 常见的响应头
Location: http://www.it315.org/index.jsp -表示重定向的地址,该头和302的状态码一起使用。 Server:apache tomcat ---表示服务器的类型 Content-Encoding: gzip -- 表示服务器发送给浏览器的数据压缩类型 Content-Length: 80 --表示服务器发送给浏览器的数据长度 Content-Language: zh-cn --表示服务器支持的语言 Content-Type: text/html; charset=GB2312 --表示服务器发送给浏览器的数据类型及内容编码 Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT --表示服务器资源的最后修改时间 Refresh: 1;url=http://www.it315.org --表示定时刷新 Content-Disposition: attachment; filename=aaa.zip --表示告诉浏览器以下载方式打开资源(下载文件时用到) Transfer-Encoding: chunked Set-Cookie:SS=Q0=5Lb_nQ; path=/search --表示服务器发送给浏览器的cookie信息(会话管理用到) Expires: -1 --表示通知浏览器不进行缓存 Cache-Control: no-cache Pragma: no-cache Connection: close/Keep-Alive --表示服务器和浏览器的连接状态。close:关闭连接 keep-alive:保存连接 |
4.3 HttpServletResponse对象
HttpServletResponse对象修改响应信息:
响应行:
response.setStatus() 设置状态码
响应头:
response.setHeader("name","value") 设置响应头
实体内容:
response.getWriter().writer(); 发送字符实体内容
response.getOutputStream().writer() 发送字节实体内容
总结:
http协议: 浏览器和服务器之间数据传输的格式规范
1)http请求:
格式:
请求行
请求头
空行
实体内容(POST提交的数据在实体内容中)
重点:
使用HttpServletRequest对象: 获取请求数据
2)http响应;
格式:
响应行
响应头
空行
实体内容(浏览器看到的内容)
重点:
使用HttpServletResponse对象: 设置响应数据
DAY10
servlet编程
Servlet学习的大纲:
- 1. servlet概念及相关接口简介
- 2. servet 执行过程
- 3. servlet路径映射
- 4. 缺省servlet --应用
- 5. servlet生命周期(重点) --理解(重点)
- 6. Servlet自动加载
- 7. Servlet线程安全
- 8. servletConfig对象
- 9. Servlet相关接口详解
- 10. ServletContext对象 --知识点
1 如何开发一个Servlet
1.1 步骤:
1)编写java类,继承HttpServlet类
2)重新doGet和doPost方法
3)Servlet程序交给tomcat服务器运行!!
3.1 servlet程序的class码拷贝到WEB-INF/classes目录
3.2 在web.xml文件中进行配置
<!-- 配置一个servlet -->
<!-- servlet的配置 -->
<servlet>
<!-- servlet的内部名称,自定义。尽量有意义 -->
<servlet-name>FirstServlet</servlet-name>
<!-- servlet的类全名: 包名+简单类名 -->
<servlet-class>gz.itcast.a_servlet.FirstServlet</servlet-class>
</servlet>
<!-- servlet的映射配置 -->
<servlet-mapping>
<!-- servlet的内部名称,一定要和上面的内部名称保持一致!! -->
<servlet-name>FirstServlet</servlet-name>
<!-- servlet的映射路径(访问servlet的名称) -->
<url-pattern>/first</url-pattern>
</servlet-mapping>
问题:访问次URL: http://localhost:8080/day10/first
前提: tomcat服务器启动时,首先加载webapps中的每个web应用的web.xml配置文件。
http://: http协议
localhost: 到本地的hosts文件中查找是否存在该域名对应的IP地址
127.0.0.1
8080: 找到tomcat服务器
/day10 在tomcat的webapps目录下找 day10的目录
/first 资源名称。
1)在day10的web.xml中查找是否有匹配的url-pattern的内容(/first)
2)如果找到匹配的url-pattern,则使用当前servlet-name的名称到web.xml文件中查询是否相同名称的servlet配置
3)如果找到,则取出对应的servlet配置信息中的servlet-class内容:
字符串: gz.itcast.a_servlet.FirstServlet
通过反射:
a)构造FirstServlet的对象
b)然后调用FirstServlet里面的方法
2 Servlet的映射路径
<servlet-mapping> <!-- servlet的内部名称,一定要和上面的内部名称保持一致!! --> <servlet-name>FirstServlet</servlet-name> <!-- servlet的映射路径(访问servlet的名称) --> <url-pattern>/first</url-pattern> </servlet-mapping> |
url-pattern 浏览器输入
精确匹配 /first http://localhost:8080/day10/first
/itcast/demo1 http://localhost:8080/day10/itcast/demo1
模糊匹配 /* http://localhost:8080/day10/任意路径
/itcast/* http://localhost:8080/day10/itcast/任意路径
*.后缀名 http://localhost:8080/day10/任意路径.do
*.do
*.action
*.html(伪静态)
注意:
1)url-pattern要么以 / 开头,要么以*开头。 例如, itcast是非法路径。
2)不能同时使用两种模糊匹配,例如 /itcast/*.do是非法路径
3)当有输入的URL有多个servlet同时被匹配的情况下:
3.1 精确匹配优先。(长的最像优先被匹配)
3.2 以后缀名结尾的模糊url-pattern优先级最低!!!
3 servlet缺省路径
servlet的缺省路径(<url-pattern>/</url-pattern>)是在tomcat服务器内置的一个路径。该路径对应的是一个DefaultServlet(缺省Servlet)。这个缺省的Servlet的作用是用于解析web应用的静态资源文件。
问题: URL输入http://localhost:8080/day10/index.html 如何读取文件????
1)到当前day10应用下的web.xml文件查找是否有匹配的url-pattern。
2)如果没有匹配的url-pattern,则交给tomcat的内置的DefaultServlet处理
3)DefaultServlet程序到day10应用的根目录下查找是存在一个名称为index.html的静态文件。
4)如果找到该文件,则读取该文件内容,返回给浏览器。
5)如果找不到该文件,则返回404错误页面。
结论: 先找动态资源,再找静态资源。
4 Sevlet的生命周期(重点)
4.1 引入
Servlet的生命周期: servlet类对象什么时候创建,什么时候调用什么方法,什么时候销毁。
以前的对象: new Student(); stu.study(); stu=null;
Servlet程序的生命周期由tomcat服务器控制的!!!!
4.2 Servlet重要的四个生命周期方法
构造方法: 创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象只调用1次。证明servlet对象在tomcat是单实例的。
init方法: 创建完servlet对象的时候调用。只调用1次。
service方法: 每次发出请求时调用。调用n次。
destroy方法: 销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。 只调用1次。
4.3 伪代码演示servlet的生命周期
Tomtcat内部代码运行:
1)通过映射找到到servlet-class的内容,字符串: gz.itcast.a_servlet.FirstServlet
2)通过反射构造FirstServlet对象
2.1 得到字节码对象
Class clazz = class.forName("gz.itcast.a_servlet.FirstServlet");
2.2 调用无参数的构造方法来构造对象
Object obj = clazz.newInstance(); ---1.servlet的构造方法被调用
3)创建ServletConfig对象,通过反射调用init方法
3.1 得到方法对象
Method m = clazz.getDeclareMethod("init",ServletConfig.class);
3.2 调用方法
m.invoke(obj,config); --2.servlet的init方法被调用
4)创建request,response对象,通过反射调用service方法
4.1 得到方法对象
Methodm m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);
4.2 调用方法
m.invoke(obj,request,response); --3.servlet的service方法被调用
5)当tomcat服务器停止或web应用重新部署,通过反射调用destroy方法
5.1 得到方法对象
Method m = clazz.getDeclareMethod("destroy",null);
5.2 调用方法
m.invoke(obj,null); --4.servlet的destroy方法被调用
4.4 用时序图来演示servlet的生命周期
5 Servlet的自动加载
默认情况下,第一次访问servlet的时候创建servlet对象。如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。
改变servlet创建对象的时机: 提前到加载web应用的时候!!!
在servlet的配置信息中,加上一个<load-on-startup>即可!!
<servlet>
<servlet-name>LifeDemo</servlet-name>
<servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>
<!-- 让servlet对象自动加载 -->
<load-on-startup>1</load-on-startup> 注意: 整数值越大,创建优先级越低!!
</servlet>
7 有参的init方法和无参的init方法
package gz.itcast.d_init;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
/**
* 有参数的init和无参的init方法
* @author APPle
*
*/
public class InitDemo extends HttpServlet {
/**
* 有参数的init方法
* 该方法是servlet的生命周期方法,一定会被tomcat服务器调用
*/
/**
* 注意:如果要编写初始代码,不需要覆盖有参数的init方法
*/
/*@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("有参数的init方法");
}*/
/**
* 无参数的init方法
* 该方法是servlet的编写初始化代码的方法。是Sun公司设计出来专门给开发者进行覆盖,然后在里面编写servlet的初始逻辑代码的方法。
*/
@Override
public void init() throws ServletException {
System.out.println("无参数的init方法");
}
}
8 Servlet的多线程并发问题
注意: servlet对象在tomcat服务器是单实例多线程的。
因为servlet是多线程的,所以当多个servlet的线程同时访问了servlet的共享数据,如成员变量,可能会引发线程安全问题。
解决办法:
1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)
2)建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。
Servlet学习:
HttpServletRequest 请求对象:获取请求信息
HttpServletResponse 响应对象: 设置响应对象
ServletConfig对象 servlet配置对象
ServletContext对象; servlet的上下文对象
9.1 作用
ServletConfig对象: 主要是用于加载servlet的初始化参数。在一个web应用可以存在多个ServletConfig对象(一个Servlet对应一个ServletConfig对象)
9.2 对象创建和得到
创建时机: 在创建完servlet对象之后,在调用init方法之前创建。
得到对象: 直接从有参数的init方法中得到!!!
9.3 servlet的初始化参数配置
<servlet>
<servlet-name>ConfigDemo</servlet-name>
<servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class>
<!-- 初始参数: 这些参数会在加载web应用的时候,封装到ServletConfig对象中 -->
<init-param>
<param-name>path</param-name>
<param-value>e:/b.txt</param-value>
</init-param>
</servlet>
注意: servlet的参数只能由当前的这个sevlet获取!!!!
ServletConfig的API:
java.lang.String getInitParameter(java.lang.String name) 根据参数名获取参数值
java.util.Enumeration getInitParameterNames() 获取所有参数
ServletContext getServletContext() 得到servlet上下文对象
java.lang.String getServletName() 得到servlet的名称
package gz.itcast.f_config;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigDemo extends HttpServlet {
/**
* 以下两段代码GenericServlet已经写了,我们无需编写!!
*/
/*private ServletConfig config;*/
/**
* 1)tomcat服务器把这些参数会在加载web应用的时候,封装到ServletConfig对象中
* 2)tomcat服务器调用init方法传入ServletConfig对象
*/
/*@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 读取servlet的初始参数
*/
String path = this.getServletConfig().getInitParameter("path");
File file = new File(path);
//读取内容
BufferedReader br = new BufferedReader(new FileReader(file));
String str = null;
while( (str=br.readLine())!=null ){
System.out.println(str);
}
//查询当前servlet的所有初始化参数
Enumeration<String> enums = this.getServletConfig().getInitParameterNames();
while(enums.hasMoreElements()){
String paramName = enums.nextElement();
String paramValue = this.getServletConfig().getInitParameter(paramName);
System.out.println(paramName+"="+paramValue);
}
//得到servlet的名称
String servletName = this.getServletConfig().getServletName();
System.out.println(servletName);
}
}
10 ServletContext对象
10.1 引入
ServletContext对象 ,叫做Servlet的上下文对象。表示一个当前的web应用环境。一个web应用中只有一 个ServletContext对象。
10.2 对象创建和得到
创建时机:加载web应用时创建ServletContext对象。
得到对象: 从ServletConfig对象的getServletContext方法得到
我们设计:
创建ServletConfig对象
public void init( ServletConfig config,ServletContext context ){ 多了一个参数
得到ServletConfig对象
得到ServletContext对象;
}
Sun公司设计
1)创建ServletContext对象 ServletContext context = new ServletContext()
2)创建ServletConfig对象 ServetConfig config = new ServletConfig();
config.setServletContxt(context);
class ServletConfig{
ServletContext context;
public ServletContext getServletContxt(){
return contxt;
}
}
public void init( ServletConfig config ){
得到ServletConfig对象
从ServletConfig对象中得到ServletContext对象
SerlvetContext context = config.getServletContext();
}
10.1 ServletContext对象的核心API(作用)
java.lang.String getContextPath() --得到当前web应用的路径
java.lang.String getInitParameter(java.lang.String name) --得到web应用的初始化参数
java.util.Enumeration getInitParameterNames()
void setAttribute(java.lang.String name, java.lang.Object object) --域对象有关的方法
java.lang.Object getAttribute(java.lang.String name)
void removeAttribute(java.lang.String name)
RequestDispatcher getRequestDispatcher(java.lang.String path) --转发(类似于重定向)
java.lang.String getRealPath(java.lang.String path) --得到web应用的资源文件
java.io.InputStream getResourceAsStream(java.lang.String path)
package gz.itcast.f_context;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 得到web应用路径
* @author APPle
*
*/
public class ContextDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.得到ServletContext对象
//ServletContext context = this.getServletConfig().getServletContext();
ServletContext context = this.getServletContext(); //(推荐使用)
//2.得到web应用路径 /day10
/**
* web应用路径:部署到tomcat服务器上运行的web应用名称
*/
String contextPath = context.getContextPath();
System.out.println(contextPath);
/**
* 案例:应用到请求重定向
*/
response.sendRedirect(contextPath+"/index.html");
}
}
package gz.itcast.f_context;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 得到web应用参数
* @author APPle
*
*/
public class ContextDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到SErvletContext对象
ServletContext context = this.getServletContext();
System.out.println("参数"+context.getInitParameter("AAA"));
Enumeration<String> enums = context.getInitParameterNames();
while(enums.hasMoreElements()){
String paramName = enums.nextElement();
String paramValue =context.getInitParameter(paramName);
System.out.println(paramName+"="+paramValue);
}
//尝试得到ConfigDemo中的servlet参数
String path = this.getServletConfig().getInitParameter("path");
System.out.println("path="+path);
}
}
package gz.itcast.f_context;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 保存数据
* @author APPle
*
*/
public class ContextDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.得到域对象
ServletContext context = this.getServletContext();
//2.把数据保存到域对象中
//context.setAttribute("name", "eric");
context.setAttribute("student", new Student("jacky",20));
System.out.println("保存成功");
}
}
class Student{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
========================================================================
package gz.itcast.f_context;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 获取数据
* @author APPle
*
*/
public class ContextDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.得到域对象
ServletContext context = this.getServletContext();
//2.从域对象中取出数据
//String name = (String)context.getAttribute("name");
Student student = (Student)context.getAttribute("student");
//System.out.println("name="+name);
System.out.println(student);
}
}
10.3 得到web应用路径
java.lang.String getContextPath() 用在请求重定向的资源名称中
10.4得到web应用的初始化参数(全局)
java.lang.String getInitParameter(java.lang.String name) --得到web应用的初始化参数
java.util.Enumeration getInitParameterNames()
web应用参数可以让当前web应用的所有servlet获取!!!
10.5域对象有关的方法
域对象:作用是用于保存数据,获取数据。可以在不同的动态资源之间共享数据。
案例:
Servlet1 Servlet2
name=eric
response.sendRedirect("/Servlet2?name=eric") String request.getParameter("name");
保存到域对象中 从域对象获取
Student
方案1: 可以通过传递参数的形式,共享数据。局限:只能传递字符串类型。
方案2: 可以使用域对象共享数据,好处:可以共享任何类型的数据!!!!!
ServletContext就是一个域对象!!!!
保存数据:void setAttribute(java.lang.String name, java.lang.Object object)
获取数据: java.lang.Object getAttribute(java.lang.String name)
删除数据: void removeAttribute(java.lang.String name)
ServletContext域对象:作用范围在整个web应用中有效!!!
所有域对象:
HttpServletRequet 域对象
ServletContext域对象
HttpSession 域对象
PageContext域对象
10.6 转发
RequestDispatcher getRequestDispatcher(java.lang.String path)
1)转发
a)地址栏不会改变
b)转发只能转发到当前web应用内的资源
c)可以在转发过程中,可以把数据保存到request域对象中
2)重定向
a)地址栏会改变,变成重定向到地址。
b)重定向可以跳转到当前web应用,或其他web应用,甚至是外部域名网站。
c)不能再重定向的过程,把数据保存到request中。
结论: 如果要使用request域对象进行数据共享,只能用转发技术!!!
/**
* 保存数据到request域对象
*/
request.setAttribute("name", "rose");
//转发
/**
* 注意:不能转发当前web应用以外的资源。
*/
/*RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/GetDataServlet");
rd.forward(request, response);*/
this.getServletContext().getRequestDispatcher("/GetDateServlet").forward(request, response);
==============================================================
/**
* 保存数据到request域对象
*/
request.setAttribute("name", "rose");
//重定向
/**
* 注意:可以跳转到web应用内,或其他web应用,甚至其他外部域名。
*/
//response.sendRedirect("/day09/adv.html");
response.sendRedirect("/day10/GetDataServlet");
总结:
Servlet编程:
Servlet生命周期(重点)
其他都是应用的东西(敲代码练习)
DAY11
1 课程回顾
Servlet编程
1)Servlet生命周期(重点)
构造方法: 创建servlet对象。默认情况下,第一次访问servlet对象时。只调用1次。
init方法(有参): 创建完servlet对象后调用。只调用1次。
注意: 会调用无参的init方法。
service方法: servlet提供服务的方法。每次发出请求调用。
注意: request对象 ,response对象
destroy方法: tomcat服务器停止或web应用重新部署,servlet对象销毁,destroy方法被调用。
2)ServletConfig对象
获取servlet的初始化参数:
getInitParameter("name ");
getInitParameterNames();
3)ServletContext对象
得到web应用路径:
context.getContextPath();
request.getContextPath(); 等价于上面的代码
得到web应用参数:
context.getInitParameter("name");
context.getInitParameterNames();
域对象:
context.setAttribute("name",Object): 保存数据
context.getAttribute("name") 得到数据
context.removeAttribue("name") 清除数据
转发
context.getRequestDispatcher("路径").forward(request,response);
request.getRequestDispacher("路径").forward(request,response); 等价于上面的代码
得到web应用中的资源文件
context.getRealPath("路径")
context.getResourceAsStream("路径");
今天的目标: 会话管理
会话管理: 管理浏览器客户端 和 服务器端之间会话过程中产生的会话数据。
域对象: 实现资源之间的数据共享。
request域对象
context域对象
登录场景:
小张: 输入“张三” (保存数据: context.setAttribute("name","张三")) -> 用户主页(显示“张三”)
小李: 输入“李四”(保存数据:context.setAttribute("name","李四")) -> 用户主页(显示“李四”)
问题: context是所有用户公有的资源!!!会覆盖数据。
小张: 输入“张三”(保存数据: request.setAttribute("name","张三"))- > 用户主页(显示“张三”) 问题: 一定要使用转发技术来跳转页面!!!
解决办法: 可以使用session域对象来保存会话数据!!!
2.3 会话技术
Cookie技术:会话数据保存在浏览器客户端。
Session技术:会话数据保存在服务器端。
3 Cooke技术
3.1 特点
Cookie技术:会话数据保存在浏览器客户端。
3.2 Cookie技术核心
Cookie类:用于存储会话数据
1)构造Cookie对象
Cookie(java.lang.String name, java.lang.String value)
2)设置cookie
void setPath(java.lang.String uri) :设置cookie的有效访问路径
void setMaxAge(int expiry) : 设置cookie的有效时间
void setValue(java.lang.String newValue) :设置cookie的值
3)发送cookie到浏览器端保存
void response.addCookie(Cookie cookie) : 发送cookie
4)服务器接收cookie
Cookie[] request.getCookies() : 接收cookie
package gz.itcast.b_resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 读取web应用下的资源文件(例如properties)
* @author APPle
*/
public class ResourceDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* . 代表java命令运行目录。java运行命令在哪里?? 在tomcat/bin目录下
* 结论: 在web项目中, . 代表在tomcat/bin目录下开始,所以不能使用这种相对路径。
*/
//读取文件。在web项目下不要这样读取。因为.表示在tomcat/bin目录下
/*File file = new File("./src/db.properties");
FileInputStream in = new FileInputStream(file);*/
/**
* 使用web应用下加载资源文件的方法
*/
/**
* 1. getRealPath读取,返回资源文件的绝对路径
*/
/*String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
System.out.println(path);
File file = new File(path);
FileInputStream in = new FileInputStream(file);*/
/**
* 2. getResourceAsStream() 得到资源文件,返回的是输入流
*/
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
//读取资源文件
prop.load(in);
String user = prop.getProperty("user");
String password = prop.getProperty("password");
System.out.println("user="+user);
System.out.println("password="+password);
}
}
package gz.itcast.c_cookie;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 第一个cookie的程序
* @author APPle
*
*/
public class CookieDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.创建Cookie对象
Cookie cookie1 = new Cookie("name","eric");
//Cookie cookie2 = new Cookie("email","jacky@qq.com");
//Cookie cookie1 = new Cookie("email","eric@qq.com");
/**
* 1)设置cookie的有效路径。默认情况:有效路径在当前web应用下。 /day11
*/
//cookie1.setPath("/day11");
//cookie2.setPath("/day12");
/**
* 2)设置cookie的有效时间
* 正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。
负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!
零:表示删除同名的cookie数据
*/
//cookie1.setMaxAge(20); //20秒,从最后不调用cookie开始计算
cookie1.setMaxAge(-1); //cookie保存在浏览器内存(会话cookie)
//cookie1.setMaxAge(0);
//2.把cookie数据发送到浏览器(通过响应头发送: set-cookie名称)
//response.setHeader("set-cookie", cookie.getName()+"="+cookie.getValue()+",email=eric@qq.com");
//推荐使用这种方法,避免手动发送cookie信息
response.addCookie(cookie1);
//response.addCookie(cookie2);
//response.addCookie(cookie1);
//3.接收浏览器发送的cookie信息
/*String name = request.getHeader("cookie");
System.out.println(name);*/
Cookie[] cookies = request.getCookies();
//注意:判断null,否则空指针
if(cookies!=null){
//遍历
for(Cookie c:cookies){
String name = c.getName();
String value = c.getValue();
System.out.println(name+"="+value);
}
}else{
System.out.println("没有接收cookie数据");
}
}
}
3.3 Cookie原理
1)服务器创建cookie对象,把会话数据存储到cookie对象中。
new Cookie("name","value");
2) 服务器发送cookie信息到浏览器
response.addCookie(cookie);
举例: set-cookie: name=eric (隐藏发送了一个set-cookie名称的响应头)
3)浏览器得到服务器发送的cookie,然后保存在浏览器端。
4)浏览器在下次访问服务器时,会带着cookie信息
举例: cookie: name=eric (隐藏带着一个叫cookie名称的请求头)
5)服务器接收到浏览器带来的cookie信息
request.getCookies();
3.4 Cookie的细节
1)void setPath(java.lang.String uri) :设置cookie的有效访问路径。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。
2)void setMaxAge(int expiry) : 设置cookie的有效时间。
正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。
负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!
零:表示删除同名的cookie数据
3)Cookie数据类型只能保存非中文字符串类型的。可以保存多个cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
4 Session技术
4.1 引入
Cookie的局限:
1)Cookie只能存字符串类型。不能保存对象
2)只能存非中文。
3)1个Cookie的容量不超过4KB。
如果要保存非字符串,超过4kb内容,只能使用session技术!!!
Session特点:
会话数据保存在服务器端。(内存中)
4.2 Session技术核心
HttpSession类:用于保存会话数据
1)创建或得到session对象
HttpSession getSession()
HttpSession getSession(boolean create)
2)设置session对象
void setMaxInactiveInterval(int interval) : 设置session的有效时间
void invalidate() : 销毁session对象
java.lang.String getId() : 得到session编号
3)保存会话数据到session对象
void setAttribute(java.lang.String name, java.lang.Object value) : 保存数据
java.lang.Object getAttribute(java.lang.String name) : 获取数据
void removeAttribute(java.lang.String name) : 清除数据
4.3 Session原理
问题: 服务器能够识别不同的浏览者!!!
现象:
前提: 在哪个session域对象保存数据,就必须从哪个域对象取出!!!!
浏览器1:(给s1分配一个唯一的标记:s001,把s001发送给浏览器)
1)创建session对象,保存会话数据
HttpSession session = request.getSession(); --保存会话数据 s1
浏览器1 的新窗口(带着s001的标记到服务器查询,s001->s1,返回s1)
1)得到session对象的会话数据
HttpSession session = request.getSession(); --可以取出 s1
新的浏览器1:(没有带s001,不能返回s1)
1)得到session对象的会话数据
HttpSession session = request.getSession(); --不可以取出 s2
浏览器2:(没有带s001,不能返回s1)
1)得到session对象的会话数据
HttpSession session = request.getSession(); --不可以取出 s3
代码解读:HttpSession session = request.getSession();
1)第一次访问创建session对象,给session对象分配一个唯一的ID,叫JSESSIONID
new HttpSession();
2)把JSESSIONID作为Cookie的值发送给浏览器保存
Cookie cookie = new Cookie("JSESSIONID", sessionID);
response.addCookie(cookie);
3)第二次访问的时候,浏览器带着JSESSIONID的cookie访问服务器
4)服务器得到JSESSIONID,在服务器的内存中搜索是否存放对应编号的session对象。
if(找到){
return map.get(sessionID);
}
Map<String,HttpSession>]
<"s001", s1>
<"s001,"s2>
5)如果找到对应编号的session对象,直接返回该对象
6)如果找不到对应编号的session对象,创建新的session对象,继续走1的流程
结论:通过JSESSION的cookie值在服务器找session对象!!!!!
4.4 Sesson细节
1)java.lang.String getId() : 得到session编号
2)两个getSession方法:
getSession(true) / getSession() : 创建或得到session对象。没有匹配的session编号,自动创建新的session对象。
getSession(false): 得到session对象。没有匹配的session编号,返回null
3)void setMaxInactiveInterval(int interval) : 设置session的有效时间
session对象销毁时间:
3.1 默认情况30分服务器自动回收
3.2 修改session回收时间
3.3 全局修改session有效时间
<!-- 修改session全局有效时间:分钟 -->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
3.4.手动销毁session对象
void invalidate() : 销毁session对象
4)如何避免浏览器的JSESSIONID的cookie随着浏览器关闭而丢失的问题
/**
* 手动发送一个硬盘保存的cookie给浏览器
*/
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
总结:
1)会话管理: 浏览器和服务器会话过程中的产生的会话数据的管理。
2)Cookie技术:
new Cookie("name","value")
response.addCookie(coookie)
request.getCookies()
3)Session技术
request.getSession();
setAttrbute("name","会话数据");
getAttribute("会话数据")