一、概念
@WebServlet("/ServletSessionDemo1")
public class ServletSessionDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用Session共享数据
// 1.获取session
HttpSession session = request.getSession();
// 2.存储数据
session.setAttribute("msg","hello session");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet("/ServletSessionDemo2")
public class ServletSessionDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
// 获取数据
Object msg = session.getAttribute("msg");
System.out.println(msg);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
先访问Demo1,再访问Demo2
Session只能进行一次对话,如果再一次访问demo2,就访问不到
二、原理分析
三、细节问题
@WebServlet("/ServletSessionDemo3")
public class ServletSessionDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.获取Session
HttpSession session = request.getSession();
System.out.println(session);
// 希望客户端关闭以后,session也能相同
Cookie c = new Cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
2.当客户端不关闭,服务器关闭,两次获取的session
回答:基本不是同一个对象,但是要确保数据不丢失
Session的钝化:在服务器关闭前,将session对象序列化到硬盘里
Session的活化:在服务器启动后,将session文件转化为内存中的session对象即可
3.session的失效时间
服务器关闭
session对象调用invalid()方法
session默认有效时间30分钟(如果想要修改)
可以在Apache-tomcat文件的conf文件中找到web.xml文件,里面有标签<session-config>可以修改时间。
四、session的特点
1.session用于存储一次会话的多次请求数据,存在服务器端;
2.session可以存储任意类型,任意大小的数据;
session和cookie的区别:
session没有数据大小限制,cookie有;
session数据安全;
session存储数据在服务器端。
五、验证码的案例
需求:
1.访问一个有验证码的登陆页面login
2.用户输入用户名,密码以及验证码
如果输入有误,跳转登陆页面,提示:用户名或者密码有误
如果验证码输入有误,则跳转到主页success.jsp,显示:用户名,欢迎
<head>
<title>login</title>
</head>
<body>
<form action="/day05/loginServlet" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>验证码</td>
<td><input type="text" name="checkCode"></td>
</tr>
<tr>
<td colspan="2"><img src="/day05/ServletCheckCode"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登陆"></td>
</tr>
</table>
</form>
</body>
</html>
为了能让验证码刷新,我们需要在验证码的图片上加时间戳:
<head>
<title>login</title>
<script>
window.onload = function () {
document.getElementById("img").onclick = function () {
this.src = "/day05/ServletCheckCode?time="+new Date().getTime();
}
}
</script>
</head>
以下新建两个servlet
第一个是验证码的设置
@WebServlet("/ServletCheckCode")
public class ServletCheckCode extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100;
int height = 50;
// 1.创建对象,在内存中画图(验证码的图片对象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
// 2.美化图片
// 2.1 填充背景
Graphics g = image.getGraphics();// 画笔对象
g.setColor(Color.PINK);// 设置笔画颜色
g.fillRect(0,0,width,height);
// 2.2 画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width-1,height-1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; // 列出验证码所有可能出现的情况
// 生成随机角标
Random ran = new Random();
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < 4;i++){
int index = ran.nextInt(str.length());
// 获取字符
char ch = str.charAt(index); // 随机字符
sb.append(ch);
// 2.3 写验证码
g.drawString(ch+"",width/5*i,height/2);// 验证码字母的位置 20/40/60/80
}
String checkCode_session = sb.toString();
// 将验证码存入session
request.getSession().setAttribute("checkCode_session",checkCode_session);
// 画干扰线
g.setColor(Color.GREEN);
// 随机生成坐标点
for(int i = 0 ;i< 10;i++){
int i0 = ran.nextInt(width);
int i1 = ran.nextInt(width);
int i2 = ran.nextInt(width);
int i3 = ran.nextInt(width);
g.drawLine(i0,i1,i2,i3);
}
// 3.图片输出
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
第二个是登陆session的设置
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置request编码
request.setCharacterEncoding("utf-8");
// 获取参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String checkCode = request.getParameter("checkCode");
// 获取生成的验证码
HttpSession session = request.getSession();
String checkCode_session = (String)session.getAttribute("checkCode_session");
// 判断验证码是否正确
if(checkCode_session.equalsIgnoreCase(checkCode)){
// 忽略大小写比较
// 验证码正确
if("zhangsan".equals(username) && "123".equals(password)){// 需要查询数据库
// 登陆成功
// 存储信息
session.setAttribute("user",username);
// 重定向到success.jsp
response.sendRedirect(request.getContextPath()+"/success.jsp");
}else{
// 失败
// 存储信息到request
request.setAttribute("login_error","用户名或者密码错误");
// 转发到登陆页面
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}else{
//验证码不正确,存储信息到request
request.setAttribute("cc_error","验证码有误");
// 转发到登陆目录
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
测试结果:验证码输入错误后跳转回登陆页面
测试结果:输入错误用户名和密码
成功:
细节修改:
1.不想输出是空值null
修改login.jsp
<div><%=request.getAttribute("cc_error") == null? "" : request.getAttribute("cc_error")%></div>
<div><%=request.getAttribute("login_error") == null? "" :request.getAttribute("login_error") %></div>
2.登陆成功后退出去,再用原来的验证码,会出错
在这里增加session的删除功能即可,再加上判断验证码是否为空