day11
1.HTTP协议特点无状态协议:在当前请求中无法保留上一次请求的参数。
2.会话技术:在浏览器和服务器建立连接之后,浏览器和服务器之间的多次请求和响应共享数据的过程就称之为会话技术。
3.cookie会话技术
3.1 cookie原理
在浏览器初次访问页面的时候,携带一个参数信息到达服务器。
服务器对当前请求作出响应的时候,携带一个set-cookie响应头,其中保存的内容就是刚刚请求发送的参数信息。
响应到达服务器之后,浏览器会自动将set-cookie响应头中的数据保留在浏览器中。
在用户发送下一次请求的时候会将这个数据存放在一个cookie请求头中。
3.2 cookie类
cookie是sun公司提供一个专门操作cookie的类型,在其中保存了很多有关cookie操作的api。
创建cookie
Cookie cookie = new Cookie();
设置cookie
设置有效路径(setPath())
一个cookie可以设置在某一个有效的范围内,在这个范围内都能读取到cookie信息,设置这个范围,就是设置有效路径,如果不设置有效路径,则当前cookie只在servlet资源名称部分有效。如果设置有效路径,则在指定的有效路径之下都有效。(所谓有效就是都能读取到。)通常会将cookie的有效路径设置为web应用的虚拟路径级别。setPath(request.getContextPaht() + “/”); 添加"/“的原因:考虑web应用虚拟路径可能是一个缺省路径,如果为缺省,则此处添加一个”",会导致设置无聊,添加一个"/",就可以
设置最大生命时长(setMaxAge(保存一个秒值))
在设置上cookie的最大生命时长之后,它会在达到这个时间之前一直保留在浏览器中。在时间到达之后会由浏览器自动销毁。如果不设置最大生命时长,则这个cookie是一个会话级别的cookie(随着会话的结束而结束)。
发送cookie
response.addCookie(cookie); // 相当于response.setHeader(“set-cookie”,“time=” + time);
获取cookie
获取cookie名称:cookie.getName();
获取cookie值:cookie.getValue();
request.getCookies(); // 相当于request.getHeader(“cookie”);得到的是一个cookie数组,数组中保存了所有的cookie信息,可以通过循环遍历的方式获取指定名称的cookie。
删除cookie
在cookie类中,并未提供删除cookie的api,但是可以通过向浏览器发送一个生命时长为0且与要删除cookie同名+同path+同domain(一般都相同不做修改)的cookie,实现删除操作。
案例:网页中输出用户上一次访问页面的时间
实现:
//获取用户上一次访问页面的时间
public class CookieDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//响应数据乱码处理
response.setContentType("text/html;charset=utf-8");
//0.准备时间值
Date date = new Date();
String time = date.toLocaleString();
//1.设置set-cookie响应头
response.setHeader("set-cookie", "time="+time);
//2.获取cookie请求头
String beforeTime = request.getHeader("cookie");
if(beforeTime == null){//初次访问页面没有cookie
response.getWriter().write("您是初次访问本页面");
}else{
response.getWriter().write("上次访问页面的时间为:"+beforeTime);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3.3 cookie特点
cookie是一个浏览器端的技术,数据保留在浏览器中,由于任何用户都可以查看到这些cookie,所以它是不安全的。
-
修改EasyMall页面
a. 添加记住用户名功能:
i. 导入login相关内容。
ii. 修改_head.jsp页面中的内容如下:
登录
iii. 修改login.jsp页面内容如下:
5.session会话技术
5.1 session概述:在浏览器端保存数据不安全,所以考虑将数据存放在服务器身上,这样的会话技术就称之为session会话技术。
5.2 session原理
在服务器端保留一个对象,这个对象保存用户相关数据信息,并且会在对象身上存在一个sessionid,这个id也会作为cookie发送到浏览器中保留下来。在浏览器叫做JSESSIONID
5.3 session的使用方式
request.getSession(); // 如果服务器中没有session对象,则建立一个新的session使用。如果有session对象,则直接获取使用。
request.getSerssion(true);// 如果服务器中没有session对象,则建立一个新的session使用。如果有session对象,则直接获取使用。
request.getSerssion(false);// 如果服务器中没有seesion对象,则返回null。如果有sesssion对象,则获取使用。
5.4作为域对象使用;
域对象:一个对象有一个可见的范围,在这个范围内利用对象身上的map实现数据的共享,这个对象就称之为域对象。
操作API:
setAttribute();
getAttribute();
removeAttribute();
getAttributeName();
生命周期:在request.getSession()调用的时候,session对象创建。
意外身亡:在web应用被移出容器,或者服务器意外关闭的时候,session对象会被销毁。总结:session对象会随着web应用的销毁而销毁。
在服务器正常关闭的时候,如果session中仍有数据,则会序列化到磁盘上,形成一个文件。这个过程称之为钝化。在服务器启动的时候,会重新读取这个session文件,这个过程称之为活化。
自杀:session.invalidate();可以主动释放session对象。
超时死亡:在web.xml中存在session生命时长的配置信息,这个时间默认为30分钟,经过这个时间之后,服务器将会自动销毁session。
作用范围:
整个会话范围内。
主要功能:
在整个会话范围内共享数据。
5.5 session特点
session将数据保存在服务器端,是一门服务器端技术。保存在服务器端的数据是较为安全的。session一般用于存储安全性要求较高,但是时间比较短的数据。
6.功能实现—购物车
BuyServlet—购物车Servlet
//购物车的servlet
public class BuyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(“text/html;charset=utf-8”);
//1.创建session
HttpSession session = request.getSession();
//2.获取请求参数prod
String prod = request.getParameter(“prod”);
prod = new String(prod.getBytes(“iso8859-1”),“utf-8”);
//3.设置到session域中
session.setAttribute(“prod”, prod);
//在关闭浏览器之后然后可以获取关闭之前的session对象
//获取浏览器中的JSESSIONID保留下来即可
Cookie cookie = new Cookie(“JSESSIONID”,session.getId());
cookie.setPath(request.getContextPath()+"/");
cookie.setMaxAge(606024);
response.addCookie(cookie);//session本质就是基于cookie工作的
response.getWriter().write(“恭喜,商品【”+prod+"】已经加入购物车!");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
PayServlet—付款Servlet
//付款servlet
public class PayServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType(“text/html;charset=utf-8”);
//从购物车中取出商品,然后对商品付款。
//1.从session域中取出域属性prod
if(request.getSession(false) == null){
//如果没有session对象,则证明用户直接访问当前servlet,没有选择商品
response.getWriter().write(“您尚未选择任何商品”);
}else{
//2.在页面中显示付款信息
//session存在则取出商品信息
HttpSession session = request.getSession(false);
String prod = (String) session.getAttribute(“prod”);
response.getWriter().write(“您已为商品【”+prod+"】付款");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
sale.jsp---提供商品信息
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" session="false"%>
商品销售页面
小米手机
棒棒糖
鼠标
麦克风
筷子
付款
7.修改EasyMall添加登录功能。
修改LoginServlet.java,添加如下代码:
//3.连接数据库查询数据是否匹配
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
ComboPooledDataSource source = JDBCUtils.getPool();
try {
conn = source.getConnection();
ps = conn.prepareStatement("select * from user where username=? and password=?");
ps.setString(1, username);
ps.setString(2, password);
rs = ps.executeQuery();
//3.1存在则登录用户
if(rs.next()){
//保存用户名称,作为登录依据--session
HttpSession session = request.getSession();
//将用户名存入session域,
//稍后回到首页读取用户名,如果能够读取到,则证明登录成功
session.setAttribute("username", username);
}else{
//3.2不存在则提示用户信息不正确
//request 域属性 msg
request.setAttribute("msg", "用户名或密码不正确");
//请求转发
request.getRequestDispatcher("/login.jsp").forward(request, response);
return;
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.close(conn, ps, rs);
}
修改regist.jsp页面,添加如下代码:
<%=request.getAttribute("msg")==null?"":request.getAttribute("msg") %> |
修改_head.jsp页面,中添加如下内容
<%
//如果存在session对象,并且包含username域属性,则证明是登录状态
if(request.getSession(false)!=null&&
request.getSession().getAttribute("username")!=null ){
%>
欢迎,<%=request.getSession().getAttribute("username") %>回来 |
注销
<%
}else{
%>
登录 |
注册
<%
}
%>
- 验证码校验
request 范围太小
servletContext 范围太大
session 范围适合
ValidateServlet.java添加如下代码:
//生成验证码的servlet
public class ValidateServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//验证码不能使用缓存图片,所以控制浏览器不使用缓存
response.setDateHeader(“Expires”, -1);
response.setHeader(“Pragma”, “no-Cache”);
response.setHeader(“Cache-control”, “no-cache”);
//调用验证码工具类,生成一张验证码图片,发送到响应缓冲区中,最后会发送到浏览器中。
VerifyCode vc = new VerifyCode();
vc.drawImage(response.getOutputStream());
String code = vc.getCode();
//存储到session域中
HttpSession session = request.getSession();
session.setAttribute(“code”, code);
System.out.println(“code:”+code);
System.out.println(“图片生成成功。”);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
RegistServlet.java添加如下代码
//6.验证码校验
//从域中取出自动生成的验证码 和用户输入的比较
HttpSession session = request.getSession();
String code = (String) session.getAttribute(“code”);
if(!code.equalsIgnoreCase(valistr) ){
request.setAttribute(“msg”, “验证码不正确”);
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
-
注销功能
//注销servlet
public class LogOutServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if(request.getSession(false)!=null){
request.getSession(false).invalidate();
}
response.sendRedirect(request.getContextPath());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}