HttpSession
作用:可以跟踪会话的类。 session是服务器端对象,保存在服务器端
时长范围:从用户首次访问服务器开始,到用户关闭浏览器。
HttpSession底层依赖Cookie,或是URL重写
Servlet中得到session对象:
HttpSession session = request.getSession();
jsp中直接使用。
session原理:
服务器端每一个session维护一份会话信息数据,
客户端和服务端依靠一个全局唯一标识sesssion_id来访问对应会话信息数据。
session创建:
当第一次获取session时,服务器才会创建session。然后保存到Cookie中
session的其他方法:
String getId(): 获取session Id
void void invalidate(): 使sessin失效。
boolean isNew();检查session是否为新。
session的最大不活动时间:
在web.xml中设置
<session-config>
<session-timeout> 30 </session-timeout>
</session-config>
url重写:
response.encodingURL("url");
该方法会对url进行智能重写---它会查看Cookie是否存在:
如果不存在,在指定的url后添加jsessionId参数
如果存在就不添加。
案例:登陆界面,保存用户信息(带Cookie)跳转
相关页面和Servlet:
login.jsp: 登陆界面 提供表单 表单指向loginServlet
succ1.jsp: 登陆成功访问的界面
loginServlet:校验验证码及信息,成功后带Cookie跳转
VerifyCodeServlet:调用VerifyCode生成图片,响应给客户端
VerifyCode类:生成验证码图片
效果图:
登陆流程图
实施大致思路:
校验流程图
login.jsp
<script type="text/javascript">
function _change(){
/**
*1.得到image图片
*2.修改其src为/day11_2/VerifyCodeServlet
*/
var imgEle=document.getElementById("img");
imgEle.src="/day11_2/VerifyCodeServlet?a="+new Date().getTime();
}
</script>
</head>
<body>
<%--提供登陆表单 --%>
<h1>登陆</h1>
<%
//读取名为uname的cookie,不为空则显示在文本框
String uname = "";
//得到请求中所有的cookie
Cookie[] cks = request.getCookies();
if(cks != null){ //存在Cookie时遍历
//遍历寻找名为uname的Cookie
for(Cookie ck : cks){
if("uname".equals(ck.getName())) //得到Cookie的名称与 uname比对
uname = ck.getValue(); //把Cookie值赋给uname
}
}
%>
<%
String message = "";
String msg = (String)request.getAttribute("msg"); //获取域中错误信息
if(msg != null){
message = msg;
}
%>
<font color="red"><%=message %></font>
<form action="/day11_2/LoginServlet" method="post">
<!--用jsp方式输出Cookie于用户名文本中 -->
用户名:<input type="text" name="username" value="<%=uname%>" />
密 码:<input type="password" name="password"/> <br/>
验证码:<input type="text" name="verifyCode" size="3"/>
<img id="img" src="/day11_2/VerifyCodeServlet">
<a href="JavaScript:_change()" rel="external nofollow" >看不清换一张</a>
<br/> <br/>
<input type="submit" value="登陆"/>
</form>
</body>
</html>
LoginServlet.java
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 校验验证码
* 1.从session中获取正取的验证码
* 2.从表单中获取用户填写的验证码
* 3.进行比较
* 4.如果相同,向下运行,否则保存错误信息到request域,转发到login.jsp
*/
// 获得的验证码里面对应的文本内容
String sessionCode = (String)request.getSession().getAttribute("session_code");
// 用户输入文本框里面的内容
String paramCode = request.getParameter("verifyCode");
if (!paramCode.equalsIgnoreCase(sessionCode)) {
request.setAttribute("msg", "验证码错误!");
request.getRequestDispatcher("/session2/login.jsp").forward(request,response);// 打回到登录界面。
return;// 返回,不继续执行下面的语句。
}
// 获取表单数据
// 处理中文问题
request.setCharacterEncoding("utf-8");
// 得到表单数据
String username = request.getParameter("username");
String password = request.getParameter("password");
// 校验用户名
if ("ywnxbx".equalsIgnoreCase(username)) { // 成功
// 附加项把用户名保存到Cookie中,发送给客户端浏览器
// 再次打开时,浏览器会读取Cookie中用户名,显示在文本框中。
Cookie cookie = new Cookie("uname", username);
cookie.setMaxAge(60 * 3); // 设置Cookie保存时长为3分钟
response.addCookie(cookie);
// 成功,保存到session,重定向到suss1
// 获取session, 保存信息到session域
HttpSession session = request.getSession();
session.setAttribute("username", username);
// 重定向到suss1
response.sendRedirect("/day11_2/session2/succ1.jsp");
} else { // 失败
// 失败,保存错误信息到request域中,转发到login.jsp用于在登陆界面显示
// 不能重定向,否则request域中内容消失
request.setAttribute("msg", "用户名或密码错误");
request.getRequestDispatcher("/session2/login.jsp").forward(
request, response);
}
}
succ1.jsp
<body>
<!-- 应该先判断session有没有值,防止此界面被直接登陆 -->
<% String username = (String)session.getAttribute("username");
if(username == null){
//向request域保存错误信息,转发到login.jsp页面
request.setAttribute("msg","您还没有登陆,不要冒充领导");
//得到调度器,转发
request.getRequestDispatcher("/session2/login.jsp").forward(request, response);
return;
}
%>
欢迎欢迎,热烈欢迎。 欢迎<%=username %> 领导指导工作!
</body>
VerifyCodeServlet.java
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*
* 1.生成图片
* 2.保存图片上的文本到session域中
* 3.把图片响应给客户端
*/
VerifyCode vc=new VerifyCode();
BufferedImage image=vc.getImage();
//保存图片上的文本到session域
request.getSession().setAttribute("session_code", vc.getText());
VerifyCode.output(image, response.getOutputStream());
}
轮子:生成随机验证码图片
public class VerifyCode {
private int w = 70;
private int h = 35;
private Random r = new Random();
// 宋体,华文楷书,黑体,华文新魏,华文隶书,微软雅黑,楷体_GB2312,Times New Roman
private String[] fontNames = { "宋体", "华文楷书", "黑体", "华文新魏", "微软雅黑", "华文隶书",
"楷体_GB2312", "Times New Roman" };
// 可选的字符
private String codes = "23456789abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ";
// 背景色
private Color bgColor = new Color(255, 255, 255);
// 验证码上的文本
private String text;
// 生成随机颜色
private Color randomColor() {
int red = r.nextInt(150);
int green = r.nextInt(150);
int blue = r.nextInt(150);
return new Color(red, green, blue);
}
// 生成随机字体
private Font randomFont() {
int index = r.nextInt(fontNames.length);// 获取下标
String fontName = fontNames[index];// 生成随机的字体名称
int style = r.nextInt(4);// 获取随机样式,0表示无样式,1表示粗体,2表示斜体,3表示粗体加斜体
int size = r.nextInt(5) + 24;// 生成随机字号,24~28
return new Font(fontName, style, size);
}
// 画干扰线
private void drawLine(BufferedImage image) {
int num = 3;// 一共画3条
Graphics2D g2 = (Graphics2D) image.getGraphics();
for (int i = 0; i < num; i++) {// 随机生成坐标,即4个值
int x1 = r.nextInt(w);
int y1 = r.nextInt(h);
int x2 = r.nextInt(w);
int y2 = r.nextInt(h);
g2.setStroke(new BasicStroke(1.5F));// 设置笔画的宽度
g2.setColor(Color.blue);// 干扰线颜色
g2.drawLine(x1, y1, x2, y2);// 画线
}
}
// 随机生成一个字符
private char randomChar() {
int index = r.nextInt(codes.length());
return codes.charAt(index);
}
// 创建BufferedImage
private BufferedImage createImage() {
BufferedImage image = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D) image.getGraphics();
g2.setColor(this.bgColor);
g2.fillRect(0, 0, w, h);
return image;
}
// 外界调用这个方法得到验证码
public BufferedImage getImage() {
BufferedImage image = createImage();// 创建图片缓冲区
Graphics2D g2 = (Graphics2D) image.getGraphics();// 得到绘制环境
StringBuilder sb = new StringBuilder();// 用来装载生成的验证码文本
// 向图中画4个字符
for (int i = 0; i < 4; i++) {// 循环4次
String s = randomChar() + "";// 随机生成一个字符
sb.append(s);// 把字母添加到sb中
double x = i * 1.0 * w / 4;// 设置当前字符的x轴坐标
g2.setFont(randomFont());// 设置随机字体
g2.setColor(randomColor());// 设置随机颜色
g2.drawString(s, (int) x, h - 5);
}
this.text = sb.toString();// 把生成的字符串赋给了this.text
drawLine(image);// 添加干扰线
return image;
}
// 返回验证码图片上面的文本
public String getText() {
return text;
}
// 保存图片到指定的输出流
public static void output(BufferedImage image, OutputStream out)
throws IOException {
ImageIO.write(image, "JPEG", out);
}
}