一、 HttpServletResponse 对象
1. 介绍
Web 服务器收到客户端的 http 请求,会针对每一次请求,分别创建一个用
于代表请求的 request 对象和代表响应的 response 对象。
request 和 response 对象代表请求和响应:
获取客户端数据,需要通过request 对象;
向客户端输出数据,需要通过 response 对象。
HttpServletResponse 的主要功能用于服务器对客户端的请求进行响应,将
Web 服务器处理后的结果返回给客户端。 service()方法中形参接收的是
HttpServletResponse
接口的实例化对象,这个对象中封装了向客户端发送数据、
发送响应头,发送响应状态码的方法。
2. 常用方法
3. 刷新和页面自动跳转
所有头信息都是随着请求和回应自动发送到服务器端(客户端),在
response 中一个比
较常用的头信息就是刷新的指令,可以完成定时刷新的功能。
resp.setHeader("refresh","2");
对于刷新的头信息,除了定时的功能外,还具备了定时跳转的功能,可以让
一个页面定时跳转到一个指定的页面。 (已经注册成功,两秒后跳转到登陆页面)
response.setHeader("refresh","3;URL=ok.html");
但是这种跳转不是万能的,有时候根本就无法进行跳转操作,返回后刷新不
会跳转;对于这种定时跳转的头信息,也可以采用 HTML 的方式进行设置,
HTML本身也可以设 置头信息。 (客户端跳转)
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class Servlet01 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet01...");
// 常用方法
// 设置响应头
// response.addHeader("uname", "zhangsan");
// 设置错误状态
// response.sendError(404,"由于颜值过低,无法访问!");
// 设置refresh响应头
// response.setHeader("refresh", "2"); // 2秒刷新一次
response.setHeader("refresh", "2;URL=http://www.baidu.com"); // 2秒钟后跳转到百度
}
}
4. 数据响应
接收到客户端请求后,可以通过 HttpServletResponse 对象直接进行响应,
响应时需要获取输出流,有两种形式
getWriter()获取字符流(只能响应回字符);
getOutputStream()获取字节流(能响应一切数据)。
响应回的数据到客户端被浏览
器解析。 注意:两者不能同时使用。
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 数据响应
* getWriter()获取字符流(只能响应回字符);
getOutputStream()获取字节流(能响应一切数据)。
响应回的数据到客户端被浏览器解析。
注意:两者不能同时使用。
java.lang.IllegalStateException: getWriter() has already been called for this response
* @author Lisa Li
*
*/
@SuppressWarnings("serial")
public class Servlet02 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet02...");
// 设置响应类型 默认是纯文本
response.setContentType("text/html");
// 得到输出流 字符输出流
/*PrintWriter writer = response.getWriter();
writer.write("Hello");
writer.write("Hello
");
writer.close();*/
// 得到字节输出流
ServletOutputStream out = response.getOutputStream();
out.write("Hello".getBytes());
out.write("Hello
".getBytes());
out.close();
}
}
5. 乱码解决
我们会发现在上述的响应中,如果我们响应的内容中含有中文,则有可能出
现乱码。这是因为服务器响应的数据也会经过网络传输,服务器端有一种编码方式,在客户端也存在一种编码方式,当两端使用的编码方式不同时则出现乱码。
getWriter()的字符乱码
对于 getWriter()获取到的字符流,响应中文必定出乱码,由于服务器端在进
行编码时默认会使用 ISO-8859-1
格式的编码,该编码方式并不支持中文。所以要解决该种乱码只能在服务器端告知服务器使用一种能够支持中文的编码格式,
比如我们通常用的"UTF-8"
resp.setCharacterEncoding("UTF-8");,此时还只完成了一半的工作,要保证数据正确显示,还需要指定客户端的解码方式
resp.setHeader("content-type",
"text/html;charset=UTF-8");,和服务器一致。两端指定编码后,乱码就解决了。
一句话: 保证发送端和接收端的编码一致
总结: 要想解决响应的乱码,只需要保证使用支持中文的编码格式。并且保
证服务器端 和客户端使用相同的编码方式即可。
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 数据响应
* getWriter()获取字符流(只能响应回字符);
getOutputStream()获取字节流(能响应一切数据)。
响应回的数据到客户端被浏览器解析。
注意:两者不能同时使用。
响应乱码
乱码原因:在响应时,服务器经过网络传输响应数据到客户端,服务器默认编码为ISO-8859-1,该编码不支持中文;客户端也有其默认编码。
总结:1、服务端和客户端编码不一致;2、客户端和服务端的编码不支持中文。
如何解决:1、设置客户端和服务端的编码一致;2、客户端和服务端编码都支持中文;
getWriter()乱码
响应中文必定出乱码,由于服务器端在进行编码时默认会使用 ISO-8859-1 格式的编码,该编码方式并不支持中文。
* @author Lisa Li
*
*/
@SuppressWarnings("serial")
public class Servlet04 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet04...");
// 设置服务端的编码
//response.setCharacterEncoding("UTF-8");
// 设置客户端的编码
//response.setHeader("content-type", "text/html;charset=UTF-8");
// 同时设置客户端和服务端的编码
response.setContentType("text/html;charset=UTF-8");
/*String str = "你好
";
// 得到输出流 字符输出流
PrintWriter writer = response.getWriter();
writer.write(str);
writer.close();*/
String str2 = "你好
";
// 得到字节输出流
ServletOutputStream out = response.getOutputStream();
out.write(str2.getBytes());
out.close();
}
}
响应表格与json
package com.shsxt.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 数据响应
* getWriter()获取字符流(只能响应回字符);
getOutputStream()获取字节流(能响应一切数据)。
响应回的数据到客户端被浏览器解析。
注意:两者不能同时使用。
* @author Lisa Li
*
*/
@SuppressWarnings("serial")
public class Servlet03 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet03...");
// 设置响应类型 默认是纯文本
/*response.setContentType("application/json");
String json = "{\"uanme\":\"zhangsan\",\"upwd\":\"123\"}";
// 得到输出流 字符输出流
PrintWriter writer = response.getWriter();
writer.write(json);
writer.close();*/
response.setContentType("text/html");
String form = "";
// 得到输出流 字符输出流
PrintWriter writer = response.getWriter();
writer.write(form);
writer.close();
}
}
**6. 响应图片
**在学习 HTML 的时候我们知道使用的方式可以显示图
片。但有的时候我们并不知道(或不能确定)图片的路径,需要通过请求服务器资
源动态地响应图片给客户端。这种方式和文件拷贝的理念是一致的,客户端请求服务器的资源,在服务端获取到真实的图片资源,通过输入流读取到内存,然后通过输出流写出到客户端即可。
值得注意的是,在客户端解析资源时默认是以文本(text/html)的形式,当
响应图片时 需要指定响应头信息,告知客户端响应内容为图片形式,使用一种
叫做 MIME 类型的东西来指定。 MIME 类型见 Tomcat 的 web.xml 文件。
定义某一个扩展名和某一个 MIME Type 做对应,包含两个子元素:
* 响应图片
* 1、得到图片存放的路径
* 2、通过路径得到文件对象
* 3、得到字节输出流
* 4、得到文件对象的输入流
* 5、循环读取,并写出到浏览器
package com.shsxt.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 响应图片
* 1、得到图片存放的路径
* 2、通过路径得到文件对象
* 3、得到字节输出流
* 4、得到文件对象的输入流
* 5、循环读取,并写出到浏览器
*
* @author Lisa Li
*
*/
@SuppressWarnings("serial")
public class Servlet05 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("响应图片...");
// 设置响应类型
response.setContentType("image/jpeg");
// 1、得到图片存放的路径
String realPath = request.getServletContext().getRealPath("/WEB-INF/jay.jpg"); // 得到项目在服务器中存放的真实路径
// 得到图片
// String file = realPath + "/WEB-INF/jay.jpg";
System.out.println(realPath);
// 2、通过路径得到文件对象
File file = new File(realPath);
// 3、得到字节输出流
ServletOutputStream out = response.getOutputStream();
// 4、得到文件对象的输入流
InputStream in = new FileInputStream(file);
// 5、循环读取,并写出到浏览器
byte[] bytes = new byte[1024];
int len = 0;
while((len = in.read(bytes)) != -1) {
// 写出
out.write(bytes,0,len);
}
out.flush();
in.close();
out.close();
}
}
7. 重定向跳转
重定向是一种服务器指导,客户端的行为。客户端发出第一个请求,被服务
器接收,经过处理服务器进行响应,与此同时,服务器给客户端一个地址(下次请求的地址
resp.sendRedirect("url");),当客户端接收到响应后,
立刻、马上、自动根据服务器
给的地址进行请求的发送第二个请求,服务器接收请求并作出响应,重定向完成。从描述中可以看出重定向当中有两个请求存在,并且属于客户端行为。
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 重定向
* 重定向是一种服务器指导,客户端的行为。客户端发出第一个请求,被服务器接收,经过处理服务器进行响应,与此同时,服务器给客户端一个地址(下次请求的地址 resp.sendRedirect("url");),当客户端接收到响应后,立刻、马上、
自动根据服务器 给的地址进行请求的发送第二个请求,服务器接收请求并作出 响应,重定向完成。从描述中可以看出重定向当中有两个请求存在,并且属于客户端行为。
请求转发和重定向的区别
1、请求转发是服务端跳转,重定向是客户端跳转
2、请求转发只有一次请求,重定向有两次请求
3、请求转发地址栏不发生改变,重定向地址栏会改变
4、请求转发request域对象能共享,重定向不能共享
5、请求转发只能请求当前资源下的路径,重定向可以任意地址
*
* @author Lisa Li
*
*/
@SuppressWarnings("serial")
public class Servlet06 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("重定向...");
// 请求转发
// request.getRequestDispatcher("index.html").forward(request, response);
// 重定向
//response.sendRedirect("index.html");
/*设置request域对象*/
//request.setAttribute("name", "zhangsan");
// 请求转发
//request.getRequestDispatcher("ser07").forward(request, response);
// 重定向
//response.sendRedirect("ser07");
/* 请求地址 */
//request.getRequestDispatcher("/sr02/ser01").forward(request, response);
//response.sendRedirect("/sr02/ser01");
//request.getRequestDispatcher("http://www.baidu.com").forward(request, response);
response.sendRedirect("http://www.baidu.com");
}
}
二、 请求时的路径问题
在请求资源时,必须给出正确的路径,否则是找不到资源的。 路径分为相对
路径和绝对路径, 绝对路径可简单理解为完整路径,在 web
项目中绝对路径分两种, 一种是以
http://开头的,该种绝对路径已经跨域,即任何地方的资源都能访问,另一种则是从当前域名|IP|主机后的端口号开始的,不能跨域,
也属于一种绝对路径。
相对路径则就是相对当前资源所在路径。
我们学的所有的请求可以分为客户端和服务器端请求两类(不考虑 ajax);
相对路径书写路径时,无论是哪类请求相对路径都是相对当前资源的路径
书写格式 : 直接 从 当前路径 开始写 , 目录前不 加任何 符 号 ; a.html
"/"代表的是 http://主机|IP:端口/站点名
绝对路径
使用绝对路径时则有两种方式,以 http://开头,或者以/开头,但是注意:
只有客户端跳转才能使用 http://这种方式,
此时需要写出资源的完整路径;另一种以/开头的绝对路径,则是绝对到端口后,例如本机则是:
http://localhost:8080
此时则是 / 代表以上一串字符。 /helloworld/a.html
http://localhost:8080/helloworld/a.html
现在对于我们来说,只有请求转发属于服务器跳转,其他都是客户端跳转。
通过观察地址栏状态也可判定跳转类型(请求类型)
地址栏不变服务器端跳转;
地址栏改变客户端跳转。
- 请求转发:
* 带"/"的绝对路径,定位的位置是在站点名之后
- 重定向:
*带"/"的绝对路径,定位的位置是在端口之后
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 请求是的路径问题
*
* http://loaclhsot:8080/s01/ser01
* 注:ser01和ser02s是两个同级的servlet
* 相对路径
* 相对于的当前资源所在路径 ser02(重定向) ser02(请求转发)
* 绝对路径
* 完整路径
* 1、以http://开头的路径,已经跨域,可以访问任意地址 http://loaclhsot:8080/s01/ser02 (重定向) (请求转发不可以)
* 2、以/开头,定位在端口之后 /s01/ser02(重定向) /ser02(在请求转发时,"/"代表的含义是从http开始到站点名后)
*
* 请求转发:
* 带"/"的绝对路径,定位的位置是在站点名之后
* 重定向:
* 带"/"的绝对路径,定位的位置是在端口之后
*
* @author Lisa Li
*
*/
@SuppressWarnings("serial")
public class Servlet08 extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Servlet08...");
// "/"代表的是http://localhost:8080/sr03/
// 相对路径:http://localhost:8080/sr03/
//request.getRequestDispatcher("index.html").forward(request, response); // OK
//request.getRequestDispatcher("/index.html").forward(request, response); // OK
//request.getRequestDispatcher("sr03/index.html").forward(request, response); // 404
//request.getRequestDispatcher("/sr03/index.html").forward(request, response); // 404
//request.getRequestDispatcher("htpp://localhost:8080/sr03/index.html").forward(request, response); // 404
// "/"代表的是http://localhost:8080/
// 相对路径:http://localhost:8080/sr03/
//response.sendRedirect("index.html"); // OK
//response.sendRedirect("/index.html"); // 404
//response.sendRedirect("sr03/index.html"); // 404
//response.sendRedirect("/sr03/index.html"); // OK
//response.sendRedirect("htpp://localhost:8080/sr03/index.html");
}
}
**三、 Cookie
**Cookie 是浏览器提供的一种技术,通过服务器的程序能将一些只须保存在客
户端,或者 在客户端进行处理的数据,放在本地的计算机上,不需要通过网络
传输,因而提高网页处理的效率,并且能够减少服务器的负载,但是由于
Cookie是服务器端保存在客户端的信息,
所以其安全性也是很差的。例如常见的记住密码则可以通过 Cookie 来实现。
有一个专门操作 Cookie 的类
javax.servlet.http.Cookie。随着服务器端的响应
发送给客户端,保存在浏览器。当下次再访问服务器时把 Cookie
再带回服务器。
Cookie 的格式:键值对用"="链接,多个键值对间通过"; "隔开。
1. Cookie 的创建和发送
通过 new Cookie("key","value");来创建一个 Cookie 对象,要想将 Cookie 随
响应发送到客户端,需要先添加到 response 对象中,
resp.addCookie(cookie);此时该 cookie
对象则随着响应发送至了客户端。在浏览器上可以看见。
package com.shsxt.servlet;
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的创建和发送
*/
public class Cookie01 extends HttpServlet {
private static final long serialVersionUID = 1L;
public Cookie01() {
super();
}
/**
* Service方法会自动区分GET请求或Post请求
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie对象
Cookie cookie = new Cookie("uname","admin");
// 创建Cookie对象
Cookie cookie2 = new Cookie("uname2","zhangsan");
// 发送Cookie对象(响应cookie)
resp.addCookie(cookie);
resp.addCookie(cookie2);
}
/**
* GET请求
*/
/*protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}*/
/**
* POST请求
*/
/*protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}*/
}
2. Cookie 的获取
在服务器端只提供了一个 getCookies()的方法用来获取客户端回传的所有
cookie 组成的一个数组,如果需要获取单个 cookie 则需要通过遍历,
getName()获取 Cookie 的名称, getValue()获取 Cookie 的值。
package com.shsxt.servlet;
import java.io.IOException;
import java.net.URLDecoder;
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对象
* 提供了一个 getCookies()的方法用来获取客户端回传的所有cookie 组成的一个数组,
* 如果需要获取单个 cookie 则需要通过遍历,getName()获取 Cookie 的名称,getValue()获取 Cookie 的值。
*/
public class Cookie02 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取cookie数组
Cookie[] cookies = request.getCookies();
// 判断cookie数组是否为空
if (cookies != null && cookies.length > 0) {
// 遍历Cookie数组
for (Cookie cookie : cookies) {
// 得到cookie的名称和值
String name = cookie.getName();
String value = cookie.getValue();
// 获取时通过 URLDecoder.decode()来进行解码
name = URLDecoder.decode(name);
value = URLDecoder.decode(value);
System.out.println("名称:" + name + ",值:" + value);
// 得到指定名称的value
if ("uname".equals(name)) {
System.out.println(value);
}
}
}
}
}
3.Cookie 到期时间的设定
从图中除了看到 Cookie 的名称和内容外,我们还需要关心一个信息, 到期
时间,到期时间用来指定该 cookie 何时失效。默认为当前浏览器关闭即失效。
我们可以手动设定 cookie 的有效时间(通过到期时间计算),通过
setMaxAge(int time);方法设定 cookie 的最大有效时间,以秒为单位。
大于 0 的整数,表示存储的秒数;
若为负数,则表示不存储该 cookie;
若为 0,则删 除该 cookie。
负整数: cookie 的 maxAge 属性的默认值就是-1,表示只在浏览器内存中
存活,一旦关闭浏览器窗口,那么 cookie 就会消失。
正整数:表示 cookie 对象可存活指定的秒数。当生命大于 0 时,浏览器
会把 Cookie 保存到硬盘上,就算关闭浏览器,就算重启客户端电脑, cookie
也会存活相应的时间。
零: cookie 生命等于 0 是一个特殊的值,它表示 cookie 被作废!也就是
说,如果原来浏览器已经保存了这个 Cookie,那么可以通过 Cookie 的
setMaxAge(0)来删除这个 Cookie。 无论是在浏览器内存中,还是在客户端硬盘
上都会删除这个 Cookie。
package com.shsxt.servlet;
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到期时间的设定
* 到期时间,到期时间用来指定该 cookie 何时失效。默认为当前浏览器关闭即失效。
可以手动设定 cookie 的有效时间(通过到期时间计算),通过 setMaxAge(int time);方法设定 cookie 的最大有效时间,以秒为单位。
大于 0 的整数,表示存储的秒数;
若为负数,则表示不存储该 cookie;
若为 0,则删 除该 cookie。
负整数:cookie 的 maxAge 属性的默认值就是-1,表示只在浏览器内存中存活,一旦关闭浏览器窗口,那么 cookie 就会消失。
正整数:表示 cookie 对象可存活指定的秒数。当生命大于 0 时,浏览器会把 Cookie 保存到硬盘上,就算关闭浏览器,就算重启客户端电脑,cookie 也会存活相应的时间。
零:cookie 生命等于 0 是一个特殊的值,它表示 cookie 被作废!也就是说,如果原来浏览器已经保存了这个 Cookie,那么可以通过 Cookie 的setMaxAge(0)来删除这个 Cookie。 无论是在浏览器内存中,还是在客户端硬盘上都会删除这个 Cookie
*/
public class Cookie03 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建Cookie对象
Cookie cookie = new Cookie("upwd","123456");
// 设置cookie到期时间
// 1、 默认值,只在当前浏览器中存活,关闭浏览器即失效
// cookie.setMaxAge(-1);
// 2、存活指定时间,单位是秒
// cookie.setMaxAge(20); // 存活15秒
// 3、设置为0,表示即刻删除
cookie.setMaxAge(0);
// 响应cookie
response.addCookie(cookie);
Cookie cookie2 = new Cookie("upwd2","1234567");
response.addCookie(cookie2);
// 删除指定cookie对象
Cookie cookie3 = new Cookie("uname",null);
// 删除cookie
cookie3.setMaxAge(0);
// 响应cookie
response.addCookie(cookie3);
}
}
4. Cookie 的注意
在一般的站点中常常有记住用户名这样一个操作,该操作只是将信息保存在
本机上,换电脑以后这些信息就无效了。而且 cookie 还不能跨浏览器。
Cookie 中不能出现中文,如果有中文则通过 URLEncoder.encode()来进行编
码,获取时通过 URLDecoder.decode()来进行解码。
不同的浏览器对 Cookie 也有限定, Cookie 的存储有是上限的。 Cookie 是
存储在客户端(浏览器)的, 而且一般是由服务器端创建和设定。后期结合
Session来实现回话跟踪。
在 Servlet 中保存的 Cookie 如果没有设置 path,那么它的 path 默认为当
前 Servlet 的所在路径;
当访问的路径包含了 cookie 的路径时,则该请求将带上该 cookie;如果访
问路径不包含 cookie 路径,则该请求不会携带该 cookie
/**
* Cookie的路径
* 只要访问的路径中包含cookie的path才能访问到该cookie
* cookie的路径默认是当前站点名下
*/
public class Cookie05 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置cookie能够被当前服务器下所有的项目访问
Cookie cookie = new Cookie("a","AA");
// 设置cookie的路径为服务器根路径
cookie.setPath("/");
// 响应cookie
response.addCookie(cookie);
Cookie cookie2 = new Cookie("b","BB");
// 设置cookie的路径为服务器根路径
cookie2.setPath("/sc04/test/cook");
// 响应cookie
response.addCookie(cookie2);
}
}
四、 Session
1. 介绍HttpSession
HttpSession 对象是 javax.servlet.http.HttpSession
的实例,该接口并不像
HttpServletRequest 或 HttpServletResponse
还存在一个父接口,该接口只是一个
纯粹的接口。 这因为 session 本身就属于 HTTP 协议的范畴。
对于服务器而言,每一个连接到它的客户端都是一个 session, servlet 容器
使用此接口创建 HTTP 客户端和 HTTP 服务器之间的会话。会话将保留指定的
时间段,跨多个连接或来自用户的页面请求。一个会话通常对应于一个用户,该用户可能多次访问一个站点。可以通过此接口查看和操作有关某个会话的信息,比如会话标识符、创建时间和最后一次访问时间。在整个
session 中,最重要的就是属性的操作。
session 无论客户端还是服务器端都可以感知到, 若重新打开一个新的浏览
器,则无法取得之前设置的 session,因为每一个 session 只保存在当前的浏览
器当中,并在相关的页面取得。
2. Session 的作用
Session 的作用就是为了标识一次会话,或者说确认一个用户;并且在一次
会话(一个用户的多次请求)期间共享数据。我们可以通过
req.getSession()方
法,来获取当前会话的 session 对象。
**3. 标识会话 JSESSIONID
**Session 既然是为了标识一次会话,那么此次会话就应该有一个唯一的标志,
这个标志就是 sessionId。
每当一次请求到达服务器,如果开启了会话(访问了 session),服务器第一
步会查看是否从客户端回传一个名为 JSESSION 的
cookie,如果没有则认为这是一次新的会话,会创建 一个新的 session
对象,并用唯一的 sessionId 为此次会话做一个标志。如果有 JESSIONID 这 个
cookie 回传,服务器则会根据
JSESSIONID 这个值去查看是否含有 id 为 JSESSION 值的 session
对象,如果没有则认为是一个新的会话,重新创建一个新的 session
对象,并标志此次会话; 如果找到了相应的 session
对象,则认为是之前标志过的一次会话,返回该 session对象,数据达到共享。
这里提到一个叫做 JSESSION 的 cookie,这是一个比较特殊的 cookie,当用
户请求服务器时,如果访问了 session,则服务器会创建一个名为
JSESSION,值为获取到的 session(无论是获取到的还是新创建的)的 sessionId
的 cookie 对象,并添加到 response
对象中,响应给客户端,有效时间为关闭浏览器。
所以 Session 的底层依赖 Cookie 来实现。
**
* Session
* 表示一次会话,会话可以保留指定时间长度
* 且在一次会话(一个用户的多次请求)期间共享数据。
*
* 创建Session对象
* request.getSession(); // 如果session不存在则新建session对象;如果session对象存在则获取session
*/
public class Session01 extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建session对象
HttpSession session = request.getSession();
// Session的常用方法
String id = session.getId();
System.out.println("会话标识符: " + id);
long createTime = session.getCreationTime();
System.out.println("创建时间: " + createTime);
long lastAccessTime = session.getLastAccessedTime();
System.out.println("最后一次访问时间: " + lastAccessTime);
boolean isNew = session.isNew();
System.out.println("是否是新建session:" + isNew);
}
}
4. 作为域对象
Session 用来表示一次会话,在一次会话中数据是可以共享的,这时 session
作为域对象存在,可以通过
setAttribute(name,value);方法向域对象中添加数据,
通过 getAttribute(name) 从域对象中获取数据,通过
removeAttribute(name)从域对象中移除数据。
获取域对象
- 请求转发
* request作用域不会失效,session作用域不会失效
- 重定向
* request作用域会失效,session作用域不会失效
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 获取域对象
* 请求转发
* request作用域不会失效,session作用域不会失效
* 重定向
* request作用域会失效,session作用域不会失效
*/
public class Session03 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取session对象
HttpSession session = request.getSession();
System.out.println("Session03:" + session.getId());
// 获取session域对象
String uname = (String) session.getAttribute("uname");
System.out.println("Session作用域中的uname:" + uname);
// 获取request作用域
String upwd = (String) request.getAttribute("upwd");
System.out.println("request作用域中的upwd:" + upwd);
}
}
5. Session的失效
1)、关闭浏览器
(session的底层是依赖cookie,默认关闭浏览器即失效;JSESSIONID不存在时,后台会新建一个sesession对象)
2)、关闭服务器(非正常关闭服务器时才会销毁,session对象在服务器正常关闭时会钝化到本地磁盘中,下次启动时从本地磁盘中读取出来,在Tomcat解压包的waork目录下)
3)、手动销毁(session.invalidate())
4)、服务器默认最大不活动时间
* Tomcat的解压缩包下的conf目录下的web.xml中
* 默认30分钟,单位为分钟
*
5)、手动设置最大不活动时间
通过 session.setMaxInactiveInterval(int);来设定 session
的最大不活动时间,单位为秒。
通过 getMaxInactiveInterval();方法来查看当前 Session
对象的最大不活动时间。
public class Session04 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 得到session对象
HttpSession session = request.getSession();
System.out.println("Session04:" + session.getId());
// 手动销毁
// session.invalidate();
// 获取最大不活动时间
int max = session.getMaxInactiveInterval();
System.out.println("最大不活动时间:" + max);
// 设置指定秒后失效
session.setMaxInactiveInterval(5);
}
}
五。ServletContext 对象
每一个 web 应用都有且仅有一个 ServletContext 对象,又称 Application 对
象,从名称中可知,该对象是与应用程序相关的。在 WEB
容器启动的时候,会每一个 WEB 应用程序创 建一个对应的 ServletContext
对象。
该对象有两大作用,
第一、作为域对象用来共享数据,此时数据在整个应用程序中共享;
第二、该对象中保存了当前应用程序相关信息。例如可以通过
getServerInfo();方法获取当前 服 务 器 信 息 ,
getResourceAsStream(Stringpath); 方法以流的形式获取某个资源,
getRealPath(String path);获取资源的真实路径等。
1. ServletContext 对象的获取
获取 ServletContext 对象的途径有很多例如通过 request 对象可以
通过 session 可以
package com.shsxt.servlet;
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;
/**
* ServletContext对象
*/
public class Servlet01 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取ServletContext对象
// 通过request对象获取
ServletContext servletContext = request.getServletContext();
// 通过session获取
ServletContext servletContext2 = request.getSession().getServletContext();
// 通过servletConfig对象
ServletContext servletContext3 = getServletConfig().getServletContext();
// 直接获取
ServletContext servletContext4 = getServletContext();
// 设置作用域
servletContext.setAttribute("usex", "man");
}
}
2. 作为域对象
ServletContext 也可当做域对象来使用,通过向 ServletContext 中存取数据,
可以使得整个应用程序共享某些数据。当然不建议存放过多数据,因为
ServletContext 中的数据一旦存储进去没有手动移除将会一直保存。
package com.shsxt.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet02
*/
public class Servlet02 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取servletContext域对象
String usex = (String) getServletContext().getAttribute("usex");
System.out.println(usex);
// 获取服务器版本
String serverInfo = request.getServletContext().getServerInfo();
System.out.println("获取服务器版本:" + serverInfo);
// 获取项目在服务器中的真实路径
String realPath = request.getServletContext().getRealPath("/");
System.out.println("获取项目在服务器中的真实路径:" + realPath);
}
}