1. Servlet简介
1. Servlet是一个接口,其中包括5个未实现的方法,而其实现类有两个,一个是HttpServlet类以及GenericServlet类。Servlet是一个运行在服务器的java程序,用于接收和响应客户端发送过来的请求。
2. Servlet程序的编写
- 编写一个类,实现Servlet接口的5个方法。
- 在项目的web.xml文件中进行配置,配置该Servlet执行的访问路径。
具体如下所示
/**
* @ClassName:ServletDemo1
* @Description:编写一个Servlet程序,实现Servlet接口(或继承HttpServlet)
* @author:
*/
public class ServletDemo1 implements Servlet{
/**
* @Title:init
* @Description:Servlet类的初始化方法,用于初始化
* @param config
* @throws ServletException
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
/**
* @Title:getServletConfig
* @Description:获取ServletConfig对象
* @return
* @see javax.servlet.Servlet#getServletConfig()
*/
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
/**
* @Title:service
* @Description:接受客户端请求,并发出响应
* @param req
* @param res
* @throws ServletException
* @throws IOException
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
//ServletRequest对象接收请求
String user=req.getParameter("user");
System.out.println(user);
//ServletResponse对象发送响应
res.getWriter().print("user:"+user);
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
在<webapp>节点下添加下元素
<servlet>
<servlet-name>demo1</servlet-name>//定义ServletDemo1类的别名,或者说id
<servlet-class>servlet.base.ServletDemo1</servlet-class>//类的全限定名,用于Class.forName()加载类
</servlet>
<servlet-mapping>//定义通过http://localhost:8080/Servlet/demo1路径访问所映射的Servlet类,一共有3种路径形式
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
3. Servlet实例的生命周期
- 创建:当一个请求首次被服务器接收后,创建对应的Servlet对象,也就是new,然后立即调用void init(ServletConfig config)方法进行初始化。服务器只会创建一个对应的Servlet实例(单例模式),并调用一次init方法,后续的请求只会继续使用同一个Servlet对象。
- 处理:接收到请求后,调用Servlet实例的service方法处理请求。每接受一次请求,就会调用一次。客户端每发送一次请求,就会生成一个新线程调用Servlet实例的service方法
- 销毁:调用destroy方法销毁Servlet实例,或者准确说是在对象被销毁之前调用执行,在这个方法中用来做一些销毁前处理,当服务器关闭或者移除项目时,就会执行该方法,只会被调用一次。
4. Servlet几个类的关系
1. GenericServlet抽象类实现了Servlet接口,并添加了几个方法;HttpServlet抽象类继承了GenericServlet类,并添加了更多的方法。
2. HttpServlet是实现了与Http协议相关的Servlet类,如果要实现其他协议的相关类,就继承GenericServlet来实现。
3. 通过继承HttpServlet重写doGet、doPost方法来实现自己的请求处理逻辑。
4. 对于继承GenericServlet类来实现其他相关协议的Servlet类,如果需要重写init方法,就重写无参的init方法 public void init()方法。
5. 配置Servlet的自动加载
1. 只需在web.xml中的Servlet配置中添加一行
<servlet>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>servlet.base.ServletDemo4</servlet-class>
<!-- 设置服务器启动时自动加载,参数表示加载的优先级,数字必须为正整数,
越小则加载优先级越高,加载时就最先加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
通常这种启动时加载应用于在Servlet初始化阶段可能会有一些耗时极长的代码,此时可以设置服务器启动时自动加载。
6. Servlet的访问路径
1. <url-pattern></url-pattern>中三种路径的写法以及优先级:
- /demo,完全路径匹配,访问路径http://localhost:8080/Servlet/demo
- /*,目录匹配,即访问路径http://localhost:8080/Servlet/下的所有请求都会由该Servlet节后
- *.do或*.action,扩展名匹配,前面不能加 /,表示所有以 .do 或 .action 结尾的请求,比如http://localhost:8080/Servlet/demo.do,http://localhost:8080/Servlet/demo.action等都会由该Servlet处理;也可以不用 * 而用demo等具体字符来指定具体路径,也就是http://localhost:8080/Servlet/demo.do
2. 以上三种路径的优先级为:
- 以最接近匹配路径的优先级最高,比如对于/abc/a.html路径的请求,/abc/*的优先级肯定大于/*的优先级
- 完全路径匹配>目录匹配>扩展名匹配
3. 相对路径:即当前文件与目标文件的相对路径,相对路径前面没有 / ,在web开发中相对路径的写法,比如说
当前文件路径为 http://localhost:8080/Servlet/demo1.html
目标文件路径为 http://localhost:8080/Servlet/demo2.html
目标文件的相对路径就为 demo2.html 或者写为 ./demo2.html,./代表当前文件所在目录,也就是http://localhost:8080/Servlet
又或者
当前文件路径为 http://localhost:8080/Servlet/demo/demo1.html
目标文件路径为 http://localhost:8080/Servlet/demo2.html
目标文件的相对路径就为 ../demo2.html , ../ 就表示当前文件所在目录(http://localhost:8080/Servlet/demo)的上一级目录(http://localhost:8080/Servlet)
4. 绝对路径:绝对路径分为客户端绝对路径和服务器端绝对路径。绝对路径前必须有 / 。
- 客户端绝对路径必须包含项目名称,比如 /Servlet/demo1。
- 服务器端绝对路径可以不写项目名称,直接写 /demo1。
7. ServletConfig对象
1. 在Servlet初始化时,通过调用init方法将创建的ServletConfig对象传入Servlet中,来设置Servlet,该对象与配置Servlet的web.xml文件相关。如下
<servlet>
<servlet-name>ServletDemo5</servlet-name>
<servlet-class>servlet.base.ServletDemo5</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>me</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123</param-value>
</init-param>
</servlet>
web.xml文件中配置的信息,以键值对存放在ServletConfig对象中,在Servlet中也可以通过该ServletConfig对象进行访问。
/**
*
* @ClassName:ServletDemo5
* @Description:关于ServletConfig对象的说明,用于获取web.xml中配置的信息
* @author:
*/
public class ServletDemo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletConfig config=getServletConfig();
config.getServletName();//获取Servlet的名称,即 <servlet-name>ServletDemo5</servlet-name>
config.getServletContext();//获取ServletContext对象
config.getInitParameterNames();//获取所有的参数名
config.getInitParameter("name");//依据参数名获取初始化参数
}
}
8. ServletContext对象——Servlet中的第一个域对象
1. Servlet中一共有3个域对象,ServletContext是其中之一,其范围是整个web项目,也就是说一个项目中的所有Servlet共享一个ServletContext对象,一个项目中的所有Servlet都可以通过ServletContext对象来传递数据。
2. 生命周期:服务器启动时,会自动为每个web项目创建一个ServletContext对象,并且直到项目被移除服务器或服务器关闭时,该对象才会被销毁。
3. 获取ServletContext对象:可以通过ServletConfig对象来获取,或者Servlet内直接调用方法getServletContext()来获取。
/**
* @ClassName:ServletDemo6
* @Description:ServletContext对象详解
* @author:
*/
public class ServletDemo6 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//每个WEB项目都只有一个ServletContext对象,项目中所有Servlet共享
//通过该对象可以在各个Servlet中传递数据,服务器启动时自动为每一个web应用
//创建ServletContext对象
//服务器关闭时ServletContext销毁
ServletContext context=getServletContext();
//或
//ServletContext context=getServletConfig().getServletContext();
}
}
4. 存储数据:通过ServletContext对象的setAttribute(name, object)方法来插入数据。域对象通用的方法。
5. 取出数据:通过ServletContext对象的context.getAttribute(name)方法取出数据。域对象通用的方法。
6. 移除数据:通过ServletContext对象的removeAttribute(name)方法移除数据。域对象通用的方法。
7. 获取全局初始化参数:通过ServletContext对象的getInitParameter(name)来获取项目的全局初始化参数,初始化参数在web.xml文件中<web-app>元素中<context-param>进行配置,如下
<web-app>
<context-param>
<param-name>name</param-name>
<param-value>sss</param-value>
</context-param>
</web-app>
8. 设置全局初始化参数:通过ServletContext对象的setInitParameter(name, value)来设置项目的全局初始化参数。
9. 应用:通过该域变量,可以统计当前项目或者说网站被访问的次数,通过设置一个count的int变量,每收到一个请求就自增一次。
10. 读取资源文件:
/**
* @ClassName:ServletDemo6
* @Description:ServletContext对象详解
* @author:
*/
public class ServletDemo6 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context=getServletContext();
//Servlet中读取属性文件
//获取输入流
/*通过ServletContext来获取
*InputStream getResourceAsStream(String path)通过文件路径获取输入流
*String getRealPath(String path) 通过文件路径获取磁盘绝对路径
*
*path的写法:
*文件放在src下,path="/WEB-INF/classes/pro.properties"
*文件放在某个包下,path="/WEB-INF/classes/servlet/base/pro.properties"
*文件放在webapp下,path="/pro.properties"
*
*/
//通过类加载器读取文件,其路径只能写相对路径且只能获取在src路径下的内容
//String path="pro.perties";
//InputStream in=this.getClass().getClassLoader().getResourceAsStream(path);
Properties pro=new Properties();
String path="/WEB-INF/classes/pro.properties";
InputStream in=getServletContext().getResourceAsStream(path);
pro.load(in);
//String realPath=getServletContext().getRealPath(path);
//pro.load(new FileInputStream(getServletContext().getRealPath(path)));
}
}
9. ServletRequest对象和ServletResponse对象
1. ServletRequest对象和ServletResponse对象由服务器创建,当服务器接收到一个请求Request时,就会创建一个ServletRequest对象和一个ServletResponse对象;从客户端发送的请求在服务器端都通过ServletRequest对象来获取,而向客户端发送响应时,都必须使用ServletResponse对象来发送。ServletRequest与ServletResponse都是一个接口,其子接口分别是HttpServletRequest和HttpServletResponse,主要用于处理Http协议类型的请求和响应。下面主要以子接口HttpServletRequest和HttpServletResponse进行API分析。
9.1 HttpServletResponse
1. HttpServletResponse对象的常用API:
- public void setHeader(String name, String value):设置响应头信息,使用这个方法设置响应头的值,必须是一个响应头对应一个值。比如setHeader( "xx", "yy"),那么响应头结果为 xx:yy
- public void addHeader(String name, String value):设置响应头信息,使用这个方法设置响应头的值,一个响应头对应多个值。比如setHeader( "xx", "yy"),setHeader( "xx", "zz")那么响应头结果为 xx : yy,zz
- public void setStatus(int sc):设置状态码,比如200,302等,可以在javax.servlet.http.HttpServletResponse源码中查看所有的状态码静态常量。
- public void sendRedirect(String location):进行重定向功能,location写目标地址。
- public void setCharacterEncoding(String charset):设置response的缓冲区的编码格式,比如UTF-8
- public void setContentType(String type):设置响应体中响应内容的类型,比如 text/html
- public PrintWriter getWriter():获取输出字符流,
- public ServletOutputStream getOutputStream():获取输出字节流
- public void addCookie(Cookie cookie):
- public void setDateHeader(String name, long date):设置的响应头的值表示是时间时,使用此方法来设置响应头
2. 关于HttpServletResponse对象的重定向实现:有两种方法来实现,如下
- 设置302状态码和location响应头的值(重定向地址字符串)
- 直接使用public void sendRedirect(String location)方法
重定向的过程包括两次请求和两次响应,可以由浏览器地址栏中地址的变化看出来。
public class Demo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//进行重定向
//方法1
response.sendRedirect("/Servlet/response/Demo1Test");
//方法2
//设置状态吗
//response.setStatus(302);//302状态码表示进行重定向
//设置响应头,需要写绝对路径,不能写相对路径
//response.setHeader("location", "/Servlet/response/Demo1Test");
}
}
3. 使用HttpServletResponse对象的实现页面定时刷新或者定时跳转:通过响应头 refresh来实现
public class Demo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置跳转,5秒后自动跳转
response.setHeader("refresh", "5;url=/Servlet/response/Demo1Test");
}
}
3. 使用HttpServletResponse对象的实现浏览器禁用缓存:通过设置三个响应头实现
public class Demo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置三个响应头信息来设置禁用缓存
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);//该响应头的值是一个日期时间类型,用long型变量来表示的,精确到毫秒,也就是说单位是毫秒,表示缓存到那一时刻后删除缓存
// //通过设置Expires响应头来设置浏览器缓存一月后过期
// Calendar calendar = Calendar.getInstance();//获取日历类实例
// calendar.setTime(new Date());//获取当前服务器时间
// calendar.add(Calendar.MONTH, 1);//为获取到的时间的月份加1
// Date expirationDate = calendar.getTime();//获取calendar日历类对象对应的Date类对象
// 通过Date类对象来获取对应的long值,精确到毫秒
// response.setDateHeader("Expires", expirationDate.getTime());
//
}
}
禁用当前响应页面的浏览器缓存,可以使之后每次访问都会刷新新的值,比如说一个显示服务端时间的页面,刷新一次都会得到一个新的值,如果不禁用缓存,就可能会多次访问得到一个不变的值,而这个值就是浏览器缓存中的值。
4. 使用HttpServletResponse对象的解决输出的浏览器页面的内容中的中文乱码问题:
可以通过设置响应头Content-Type的值或者调用setContentType("text/html;charset=utf-8")方法来解决中文乱码问题。
public class Demo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//当使用字符流输出中文时,我们需要设置response缓冲区的编码格式
response.setCharacterEncoding("utf-8");
//设置浏览器端打开该文件时的编码格式
response.setContentType("text/html;charset=utf-8");
//上面两行代码可直接调用另一个方法来实现相同的效果
//response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.print("薇恩");
out.flush();
out.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//当使用字节流输出中文时,只需要保证将中文字符编码成字节数组的格式与浏览器端的编码方式相同
//即都设置为utf-8,保证两端的编码格式相同
//设置浏览器打开文件的编码
response.setHeader("Content-Type", "text/html;charset=utf-8");
//设置传输的字节码的编码格式
response.getOutputStream().write("薇恩".getBytes("utf-8"));
}
}
5. 使用HttpServletResponse对象实现文件下载功能:通过设置响应头 Content-Disposition 的值来实现文件下载。其值为字符串,形式如
"attachment;filename=文件名称",表示将文件作为附件形式打开。
public class Demo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应头信息,以附件形式打开文件(即打开下载栏下载到本地),如果不设置头信息,仅仅通过url在浏览器页面显示也是下载,只不过是下载到浏览器缓存中由浏览器显示
response.setHeader("Content-Disposition", "attachment;filename=03.jpg");
//获取文件输出流
InputStream in=getServletContext().getResourceAsStream("/03.jpg");
byte[] b=new byte[1024];
int len=0;
OutputStream out=response.getOutputStream();
while((len=in.read(b))!=-1){
out.write(b);
}
in.close();
out.close();
}
}
6. 验证码功能的实现:
public class Demo6 extends HttpServlet {
//创建验证码图片
BufferedImage createImage(){
//声明 "画纸" 对象
BufferedImage image=new BufferedImage(150, 50, BufferedImage.TYPE_INT_RGB);
//获取"画笔"对象
Graphics g=image.getGraphics();
//设置画笔颜色
g.setColor(Color.BLUE);
//在画布填充颜色背景
g.fillRect(0, 0, 150, 50);
//更换画笔颜色,填充验证码
g.setColor(Color.BLACK);
//设置字体
g.setFont(new Font("宋体", Font.BOLD , 20));
//输入准备好的字符串
g.drawString("1234", 50, 30);
//将图片返回
return image;
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
BufferedImage image=createImage();
//将图片响应给浏览器
ImageIO.write(image, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
9.2 HttpServletRequest——Servlet中的第二个域对象
1. 常用API:
- public Object getAttribute(String name):从域对象中获取属性键值对的方法
- public void setAttribute(String name, Object o):向域对象中设置属性键值对的方法
- public Enumeration<String> getAttributeNames():获取域对象中所有属性的键值
- public void removeAttribute(String name):删除域对象中的某个键值
- public String getParameter(String name):通过参数名来获取请求中的参数值,用来获取比如参数值来自于密码框、文本框中的数据
- public String[] getParameterValues(String name):也是通过参数名来获取请求中的参数值,但用来获取参数值来自于复选框中的数据
- public Map<String, String[]> getParameterMap():获取请求中的参数键值对,也就是说以封装方式获取请求中的数据
- public RequestDispatcher getRequestDispatcher(String path):用来进行转发。
- public String getHeader(String name):获取请求头,可以使用 referer 来获取发送该请求的原地址,可以防止盗链,比如说在A网址的网页中有一个指向C网址的超链接,点击就会向C网址发送请求,而请求头 referer 就保存了A网址的值,这样在服务端添加一个判断条件后就可以分辨哪些网站发送的请求有效,哪些无效了。
- public String getMethod():获取请求的方式,是get还是post等。
- public String getScheme():获取请求所使用的协议类型,比如http或https。
- public String getServerName():获取服务器名,比如 http://localhost:8081/Servlet/response/demo5 中的 localhost
- public int getServerPort():获取服务器端口值,比如 http://localhost:8081/Servlet/response/demo5 中的 8081
- public String getContextPath():获取项目路径,比如 http://localhost:8081/Servlet/response/demo5 中的 /Servlet
- public String getServletPath():获取Servlet路径,比如 http://localhost:8081/Servlet/response/demo5 中的 /response/demo5
- public String getRequestURI():获取请求的URI,相当于getContextPath()+getServletPath(),比如 http://localhost:8081/Servlet/response/demo5 中的 /Servlet/response/demo5
- public StringBuffer getRequestURL():获取请求的URL,请求的完整路径,也就是http://localhost:8081/Servlet/response/demo5
2. 对于获取请求中的中文参数值的乱码问题解决:
public class ReqDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//对于get请求,可以先取的数据,然后将获得的字符串先按照iso8859-1解码,然后再按照utf-8编码
String s=request.getParameter("");
s=new String(s.getBytes("iso8859-1"), "utf-8");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//对于post请求,只需要在getParameter方法调用之前设置编码格式即可
request.setCharacterEncoding("utf-8");
request.getParameter("");
}
}
3. HttpServletRequest作为一个域对象:其作用范围仅为一次请求的范围内,或者说在请求对应的Servlet范围内有效。
4. 转发与重定向的区别:
- 转发是在服务器内部进行的,只有一次请求一次响应,而重定向是服务器会把新地址作为响应返回给客户端,由客户端向这个新地址发起请求,是两次请求两次响应。
- 转发时客户端浏览器的地址栏不变,而重定向会使地址栏改变。
- 转发可以通过HttpServletRequest域对象,在两个Servlet之间传递数据,重定向则不可以。
- 重定向可以定向到任何网络页面
public class ReqDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//重定向,location的值为重定向地址
response.sendRedirect(location);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//转发,path的值为转发的地址
request.setAttribute("name", "xx");//在request中存储数据,可以在目标Servlet中取出
request.getRequestDispatcher(path).forward(request, response);
}
}
5. 部分细节问题:
- 字节流和字符流互斥,也就是说response.getWriter().write()和response.getOutputStream().write()不能同时使用。
- 转发时,response的缓冲区会被清空。
@WebServlet("/request/Demo7")
public class Demo7 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("ss");
//response.getOutputStream().write(new byte[3]);字节流和字符流不能同时使用
request.getRequestDispatcher("/ReqDemo1");//转发时,上面存储在response缓冲区内的数据将会被清空,也就是说"ss"不会显示在浏览器页面上
}
}
6. 路径一些写法问题
- ServletContext域对象有两个方法,用于获取服务端文件资源:
- InputStream getResourceAsStream(String path):通过服务器系统的文件路径获取输入流,写法不包含项目名称,比如"/WEB-INF/classes/xx.xml"
- String getRealPath(String path) :通过服务器系统的文件路径获取磁盘绝对路径,再通过这个绝对路径便可以获得输入流,写法不包含项目名称
- 重定向的路径写法:
- 在客户端,所以必须包含项目名称,比如 /Servlet/demo
- 转发的路径写法:
- 在服务端,所以不包含项目名称,比如 /demo
10. Cookie
1. 简介:Cookie是客户端技术,服务端将数据以Cookie的形式存储到客户端的浏览器中,当浏览器再次访问同一个网站时,请求中就会带着Cookie数据发送给服务器。
2. API的使用:
- public Cookie(String name, String value):构造方法
- public String getName():获取Cookie的名称
- public void setValue(String newValue):设置Cookie的值
- public String getValue():获取Cookie的值
- public void setMaxAge(int expiry):设置浏览器中Cookie的存在时间,单位为秒,默认关闭浏览器时销毁。
- public void setPath(String uri):设置Cookie的可以被访问的有效路径,及决定那些路径下的请求所发出的请求可以携带该Cookie
- public void setDomain(String domain):设置Cookie的有效域名
public class Demo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//生成Cookie
Cookie c=new Cookie("name", "vn");
//设置cookie的有效时间,默认关闭浏览器时即销毁,可以通过此方法将cookie保存至本地磁盘,单位为秒,只要不超过
//时间,关闭浏览器也不会销毁,设置为0时,即可立即删除磁盘上的该Cookie
c.setMaxAge(60);
//设置Cookie的可以被访问的有效路径,及决定那些路径下的请求所发出的请求可以携带该Cookie
//如果不设置则说明仅为当前Servlet路径的上一级路径下所使用,
//即在/Servlet/cookie/路径下即可访问,路径必须从项目名开始写绝对路径
c.setPath("/Servlet");//设置只要是在 http://localhost:8081/Servlet/ 路径下的请求都可用该Cookie
//注意,如果Cookie已经设置过有效路径,在进行手动删除时,即setMaxAge(0)时,
//需要先设置Cookie路径与之前设置路径相同方可生效
//设置Cookie的有效域名
//c.setDomain(".baidu.com");//即在.taotao.com域名下的所有请求都会携带该Cookie,比如xxx.taotao.com
response.addCookie(c);//在服务端把Cookie存储到response中返回给浏览器。
}
}
3. Cookie的使用:
- 服务端创建Cookie对象后,使用HttpServletResponse对象response调用addCookie()方法将Cookie对象添加到响应中。
- 服务端可以从HttpServletRequest对象request中通过调用getCookies()方法来获取所有的Cookie。
11. Session——Servlet中的第三个域对象
1. 简介:Session是服务端技术,利用这个技术,服务器可以为每一个用户的浏览器创建一个独享的保存在服务器的Session对象,当客户端浏览器需要使用Session中的数据时,服务端就会将这个Session中的数据返回给用户浏览器。
获取HttpSession对象通过HttpServletRequest对象request来获取,如果HttpSession对象还未创建则会创建一个新的HttpSession对象返回,否则则会返回已存在的HttpSession对象。HttpSession对象中的属性以键值对形式存在。
public class Demo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session=request.getSession();
System.out.println(session.getId());//获取session的id
}
}
如果第一次创建HttpSession对象,则会将该HttpSession对象的Sessionid创建一个Cookie返回给用户浏览器,当用户浏览器第二次请求处理中获取HttpSession时,就会依据这个Cookie中的Sessionid来得到Session对象,所以浏览器一关闭就会造成Sessionid的这个Cookie被删除,如果浏览器的Cookie缓存项被禁用(相当于关闭浏览器的作用),那么同样也无法取得Session中的数据,会生成新的Session对象并存储数据,但是因为没有Sessionid所以就无法取得Session对象,Session对象仍然在服务器端存在。
2. 部分常用API:
- public void setAttribute(String name, Object value):插入属性
- public Object getAttribute(String name):依据属性名取得属性值
- public String getId():获取当前session的id
- public void removeAttribute(String name):依据属性名删除属性
- public void invalidate():手动销毁session对象(比如说在用户退出登录的时候)
- public Enumeration<String> getAttributeNames():获取session中所有属性的属性名
3. Session域对象的有效范围:在一次会话的范围之内(ServletContext路径),也就是说,浏览器访问同一个站点,可以有多次请求和响应,只要浏览器不关闭,就会有效,比如说,第一次请求 http://localhost:8081/Servlet/demo5 并生成了一个session,如果浏览器不关闭,那么在后续访问http://localhost:8081/Servlet/xx 路径下的所有Servlet中都可以得到这个session。
4. Session对象的创建:创建是在第一次访问的时候调用request.getSession()时创建;
5. Session对象的销毁:
- 非正常销毁,也就是服务器直接(强制)关闭,服务器正常关闭,也就是通过bin目录下的shutdown.bat(或.sh)关闭服务器时,会把session对象序列化存储在在tomcat目录下work\Catalina\localhost+项目名的目录下,当服务器重新启动时,就会将此文件反序列化加载到服务器中;若是强制关闭比如断电等则会销毁session对象,因为无法将session对象序列化存储到文件系统中。
- tomcat服务器默认session对象销毁时间是30分钟,可以通过在web.xml文件中设置销毁时间,只需添加以下配置
<session-config>
<session-timeout>60</session-timeout>
</session-config>
- 手动销毁,通过调用invalidate()方法来实现销毁,比如用户退出登录的时候。