目录
三、会话跟踪
1、 Session(会话)
1.1 Http协议的特点
1)无连接
每次连接只处理一个请求,服务端处理完客户端一次请求,等到客户端作出回应之后便断开连接;
http 1.1之后变成了长连接connection:keep-alive
2)无状态
http是基于tcp的,而从http1.1开始默认使用持久连接;在这个连接过程中,客户端可以向服务端发送多次请求,服务端对于客户端每次发送的请求都认为它是一个新的请求,上一次会话和下一次会话没有联系
状态的主体是指由服务端所维护与客户端交互的信息(状态信息),Http不保存任何用户的状态信息,所以Http是无状态的协议
1.2 session的作用
session是用来跟踪会话,保存状态信息的;session是在服务端保存状态信息的,在session出现之前用cookie来跟踪会话,但cookie是将状态信息保存在浏览器(这种的就是浏览器cookie)的,随着浏览器的关闭就会消失。
1.3 session机制原理
①客户端请求之后,要创建session,在创建session之前,服务器先检查客户端的请求里是否已经包含session标识(sessionid)
②如果包含这个sessionid,(表名已经创建)服务器就按照这个sessionid把这个session检索出来使用。
③如果不包含这个sessionid,为此客户端创建一个session,并生成一个相关联的sessionid。
其中sessionid的值是一个不会重复、又不容易仿造的字符串,这个sessionid将被在本次响应中返回给客户端保存。客户端大多数情况下都会使用浏览器cookie保存sessionid。
1.4 HttpSession结构
HttpSession和Cookie一样,都是javax.servlet.http下面的;Cookie是一个类;而HttpSession是一个接口,它为session的实现提供了一些行为约束。
接口中的方法:
1、 public Object getAttribute(String name): 获得指定名称的属性值
2、 public void setAttribute(String name,Object o): 设置属性和值
3、 public void removeAttribute(String name) 删除指定名称的属性
4、 public Enumeration getAttributeNames()获得所有属性名字的Enumeration数组。以下代码可以简单的打印出所有属性的名字
Enumeration e = session.getAttributeNames();
String name = null;
while(e.hasMoreElements()){
name = (String)e.nextElement();
}
5、 public long getCreationTime()返回该对象生成的时间,单位是距离1970年1月1日午夜算起的毫秒数。
6、 public long getLastAccessedTime()返回客户上一次与这个会话相关联的请求的时间,也是一个毫秒值。通过这个方法容器很容易计算出这个客户有多长时间没有访问这个对象了。
7、 public String getId()返回该对象的Id号码,容器会使用精心准备的算法去保证各个HttpSession对象的Id号码是唯一的。
8、 public void setMaxInactiveInterval(int interval)设置最大不活动时间间隔。这个时间到达后,容器会调用invalidate()方法销毁该对象。(销毁实际上是删除其属性,即使invalidate()这个方法被调用后session这个对象还是存在的)。在Tomcat中,如果没有更改session的过期时间默认是30分钟。也可以通过web.xml文件进行更改,
<session-config>
<session-timeout>20</session-timeout>
</session-config>
9、 public int getMaxInactiveInterval()返回session对象不活动的最大时间间隔。
10、 public void invalidate()使这个对象失效,并且删除绑定在对象里的任何属性。
11、 public boolean isNew()如果这个对象是新创建的,则返回true。
12、 public ServletContext getServletContext()返回ServletContext对象。
1.5 创建session
创建session的方式是通过request来创建
//1.不加判断
//如果有session,就直接拿来用,没有的话就创建一个
request.getSeeion()
//2.加判断
// 当里面为true,有就用,没有就创建一个
// 当里面为false,有就用,没有就返回null
request.getSeeion(boolean)
1.6 HttpSession的生命周期
①Servlet容器会依据session对象设置的存活时间,在达到session时间后将session对象销毁。
②session生成后,只要用户继续访问,服务器就会更新session的最后访问时间,并维护该session。
③session的生命周期指的是从Servlet容器创建session对象到销毁的过程。
1.6.1 session的有效期
在web.xml对session进行有效期设置;单位是分钟
<session-config>
<session-timeout>30</session-timeout>
</session-config>
1.6.2 session的销毁
session一般在内存中存放,内存空间本身大小就有一定的局限性,因此session需要采用一种过期删除的机制来确保session信息不会一直累积,来防止内存溢出的发生。
1)session的超时时间可以通过maxInactiveInterval属性来设置。
2)如果我们想让session失效的话,也可以当通过调用session的invalidate()来完成。
案例:
实体类(添加lombok的jar包,可以减少代码量):
//导入jar包后可以使用简便方法代表
@Data //所有成员变量的get、set方法
@NoArgsConstructor //无参构造方法
@AllArgsConstructor //全参构造方法
@ToString //toString方法
public class User {
private Integer id;
private String username;
private String password;
}
接口:
public interface IUserDao {
List<Map<String,Object>> findAll();
List<Map<String,Object>> findOne(User user);
}
接口的实现类:
public class UserDaoImpl extends BaseDao implements IUserDao {
@Override
public List<Map<String, Object>> findAll() {
String sql = "select * from user";
return query(sql);
}
@Override
public List<Map<String,Object>> findOne( User user) {
String sql = "select * from user where username=? and password=?";
List<Map<String, Object>> query = query(sql, user.getUsername(), user.getPassword());
return query;
}
}
登录界面(index.jsp):
<form action="loginServlet" method="post">
用户名:<input type="text" name="username">
密 码:<input type="password" name="password">
<input type="submit" value="提交">
</form>
检查并添加session属性:
@WebServlet(name = "LoginServlet", value = "/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("GBK");
//获取表格中所有的元素
Map<String, String[]> parameterMap = req.getParameterMap();
System.out.println(parameterMap);
User user = new User();
try {
//导入commons-beanutils-1.7.0.jar 工具核心包
//导入commons-collections-3.2.2.jar 增强的集合包
//导入commons-logging-1.1.1.jar 日志记录包
//可以使用BeanUtils.populate()方法将parameterMap转化为user实体类
BeanUtils.populate(user,parameterMap);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
System.out.println(user);
IUserDao iUserDao = new UserDaoImpl();
List<Map<String, Object>> one = iUserDao.findOne(user);
System.out.println("查询的用户的信息:"+one);
if (one.size()>0){
//获取session对象
HttpSession session = req.getSession();
//1.将用户信息保存到session里面
session.setAttribute("username",user.getUsername());
//2.或者使用上面的表格集合两个是一样的作用
// session.setAttribute("username",one.get(0).get("username"));
//3.也可以直接存进去整个对象
// session.setAttribute("user",one);
resp.sendRedirect("welcomeServlet");
}else {
resp.sendRedirect("index.jsp");
}
}
// BeanUtils.populate(user,parameterMap);
// 通过添加的commons-beanutils-1.7.0.jar中的方法可以将parameterMap转化为一个实体类
// //获取其中的所有key值
// Set<String> strings = parameterMap.keySet();
// System.out.println(strings);
// Iterator<String> iterator = strings.iterator();
// User user = new User();
// while (iterator.hasNext()){
// String key = iterator.next();
// //输出key值和对应的value值
// System.out.println("key:"+key+"value:"+parameterMap.get(key)[0]);
//如果它的key值等于username,那么就把该key值对应的value数组中的第一个值取出来
// if (key.equals("username")){
// user.setUsername(parameterMap.get(key)[0]);
// }
// if (key.equals("password")){
// user.setPassword(parameterMap.get(key)[0]);
// }
// }
// System.out.println(user);
}
登录成功欢迎界面:
@WebServlet(name = "WelcomeServlet", value = "/welcomeServlet")
public class WelcomeServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Object username = session.getAttribute("username");
resp.setContentType("text/html;charset=gbk");
PrintWriter writer = resp.getWriter();
writer.print("欢迎欢迎,"+username);//
writer.print("<a href='logout'>退出</a>");
writer.flush();
writer.close();
}
}
退出session自毁:
@WebServlet(name = "LogoutServlet", value = "/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();//获取会话对象
session.invalidate();//会话自己销毁自己
resp.sendRedirect("index.jsp");//再次跳转到登录页面
}
}
1.7 session和cookie的区别
①cookie:服务器生成,通过浏览器输出到客户端电脑上的,如果没有设置maxAge属性,关闭浏览器就会消失。存储键值对,字符串类型数据,安全性低,不保存敏感的信息。
②cookie:一般用来保存用户信息(长时间保存)、购物车、个性化定制信息
①session:启动会话,创建session,在服务器(内存)上创建,每一个会话对应一个session; 存储键值对,可以存储各种类型的数据(Object);基于cookie实现的。默认存活时间30分钟。
②session:存储会话信息,更多用来存储用户的身份信息。