参考答案
浏览器访问Web服务器时,服务器会为每一个浏览器在服务器端的内存中分配空间,单独创建一个Session对象,该对象有一个Id属性,其值唯一,一般称之为SessionId,并且服务器会将这个SessionId(使用Cookie的方式)发送给浏览器;浏览器再次访问服务器时,会将SessionId发送给服务器,服务器可以依据SessionId找到对应的Session对象。
A. 在Servlet中,Session对象不需要创建,直接就可以使用。
B. 使用Session对象的setAttribute方法进行对象的绑定。
C. Session对象不能手动删除,只能等待系统删除。
D. 禁用Cookie后,Session功能将失效。
参考答案
本题正确答案为AB。
C选项说法错误。Session对象的invalidate方法,可以立即删除Session对象。
D选项说法错误。服务器在默认情况下,会使用Cookie的方式将SessionId发送给浏览器,如果用户禁止Cookie,则SessionId不会被浏览器保存,此时,服务器可以使用URL重写的方式来发送SessionId。因此如果浏览器禁用Cookie,服务器可以使用URL重写的方式来使用Session对象。
参考答案
Session超时指的是:Web服务器会将空闲时间过长的Session对象删除掉,以节省服务器内存空间资源。web服务器缺省的超时时间限制:一般是30分钟。修改Session的缺省时间限制,有如下两种方式:
1. 通过修改tomcat中 conf/web.xml 文件的设置,代码如下所示:
<session-config> <session-timeout>30</session-timeout> </session-config>
2.通过编程的方式来修改,通过调用Session对象的setMaxInactiveInterval方法来修改,该方法的声明如下所示:
void setMaxInactiveInterval ( int seconds ){}
在课后练习“使用Cookie实现登录功能,可以设置身份保存时间为“一次”或“永久””的基础上为登录添加验证码功能。
参考答案
完成本案例可以按照如下步骤进行。
步骤一:新建ValidateCode.java文件
在web包下新建类ValidateCode,该类是一个Servlet。然后在该类中编写生产验证码的代码,并将生成的验证码保存到session中。代码如下所示:
package web; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ValidateCode extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.创建空白图片 BufferedImage image = new BufferedImage(100,30,BufferedImage.TYPE_INT_RGB); //1.获取图片画笔 Graphics g = image.getGraphics(); Random r = new Random(); //2.设置画笔颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); //3.绘制矩形的背景 g.fillRect(0, 0, 100, 30); //4.调用自定义的方法,获取长度为5的字母数字组合的字符串 String number = getNumber(5); HttpSession session = request.getSession(); session.setAttribute("code", number); g.setColor(new Color(0,0,0)); g.setFont(new Font(null,Font.BOLD,24)); //5.设置颜色字体后,绘制字符串 g.drawString(number, 5, 25); //6.绘制8条干扰线 for(int i=0;i<8;i++){ g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255),r.nextInt(255))); g.drawLine(r.nextInt(100), r.nextInt(30), r.nextInt(100), r.nextInt(30)); } response.setContentType("image/jpeg"); OutputStream ops = response.getOutputStream(); ImageIO.write(image, "jpeg", ops); ops.close(); } private String getNumber(int size){ String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; String number = ""; Random r = new Random(); for(int i=0;i<size;i++){ number+=str.charAt(r.nextInt(str.length())); } return number; } }
步骤二:修改web.xml
修改web.xml,配置ValidateCode,如图-1所示:
图– 1
步骤三:修改login.jsp
修改login.jsp,添加验证码,如图-2,图-3所示。
图– 2
图– 3
步骤四:修改ActionServlet.java文件
修改ActionServlet中的“login”分支,添加关于验证码的判断代码,如图-4所示。
图– 4
步骤五:显示“验证码错误”
修改login.jsp页面,在该页面中获取提示“验证码错误”信息,如图-5所示。
图– 5
步骤六:重新部署,访问应用
用户名和密码以及验证码均正确的情况下登录成功。如果验证码错误,返回login.jsp,显示错误信息,如图-6所示。
图– 6
本案例的完整代码如下。
ValidateCode类的完整代码如下所示:
package web; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ValidateCode extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.创建空白图片 BufferedImage image = new BufferedImage(100,30,BufferedImage.TYPE_INT_RGB); //1.获取图片画笔 Graphics g = image.getGraphics(); Random r = new Random(); //2.设置画笔颜色 g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255))); //3.绘制矩形的背景 g.fillRect(0, 0, 100, 30); //4.调用自定义的方法,获取长度为5的字母数字组合的字符串 String number = getNumber(5); HttpSession session = request.getSession(); session.setAttribute("code", number); g.setColor(new Color(0,0,0)); g.setFont(new Font(null,Font.BOLD,24)); //5.设置颜色字体后,绘制字符串 g.drawString(number, 5, 25); //6.绘制8条干扰线 for(int i=0;i<8;i++){ g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255),r.nextInt(255))); g.drawLine(r.nextInt(100), r.nextInt(30), r.nextInt(100), r.nextInt(30)); } response.setContentType("image/jpeg"); OutputStream ops = response.getOutputStream(); ImageIO.write(image, "jpeg", ops); ops.close(); } private String getNumber(int size){ String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; String number = ""; Random r = new Random(); for(int i=0;i<size;i++){ number+=str.charAt(r.nextInt(str.length())); } return number; } }
ActionServlet类的完整代码如下所示:
package web; import java.io.IOException; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import dao.AccountDAO; import dao.AdminInfoDAO; import entity.Account; import entity.AdminInfo; public class ActionServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); // 获取请求资源路径 String uri = request.getRequestURI(); // 获取请求资源路径中除应用名以外的部分 String action = uri.substring(uri.lastIndexOf("/") + 1, uri .lastIndexOf(".")); AccountDAO dao = new AccountDAO(); if (action.equals("list")) { try { List<Account> accounts = dao.findAll(); request.setAttribute("accounts", accounts); request.getRequestDispatcher("listAccount.jsp").forward( request, response); } catch (Exception e) { e.printStackTrace(); out.print("系统繁忙"); } } else if (action.equals("add")) { String realName = request.getParameter("realName"); String idcardNo = request.getParameter("idcardNo"); String loginName = request.getParameter("loginName"); String telephone = request.getParameter("telephone"); try { Account account = new Account(); account.setRealName(realName); account.setIdcardNo(idcardNo); account.setLoginName(loginName); account.setStatus("0"); account.setTelephone(telephone); dao.save(account); response.sendRedirect("list.do"); } catch (Exception e) { e.printStackTrace(); out.print("系统繁忙"); } } else if (action.equals("delete")) { String accountId = request.getParameter("accountId"); try { dao.delete(Integer.parseInt(accountId)); response.sendRedirect("list.do"); } catch (Exception e) { e.printStackTrace(); out.print("系统繁忙"); } } else if (action.equals("load")) { String accountId = request.getParameter("accountId"); try { Account acc = dao.findById((Integer.parseInt(accountId))); request.setAttribute("account", acc); request.getRequestDispatcher("modifyAccount.jsp").forward( request, response); } catch (Exception e) { e.printStackTrace(); out.print("系统繁忙"); } } else if (action.equals("modify")) { String accountId = request.getParameter("accountId"); String realName = request.getParameter("realName"); String idcardNo = request.getParameter("idcardNo"); String loginName = request.getParameter("loginName"); String telephone = request.getParameter("telephone"); try { Account account = new Account(); account.setAccountId(Integer.parseInt(accountId)); account.setRealName(realName); account.setIdcardNo(idcardNo); account.setLoginName(loginName); account.setTelephone(telephone); dao.modify(account); response.sendRedirect("list.do"); } catch (Exception e) { e.printStackTrace(); out.print("系统繁忙"); } } else if (action.equals("login")) { String adminCode = request.getParameter("adminCode"); String password = request.getParameter("password"); String saveCookie = request.getParameter("saveCookie"); Cookie adminCodeCookie = new Cookie("AdminCode", adminCode); Cookie pwdCookie = new Cookie("Password", password); if (saveCookie != null && "yes".equalsIgnoreCase(saveCookie)) { adminCodeCookie.setMaxAge(60 * 60 * 24 * 30 * 12);// 保存一年 pwdCookie.setMaxAge(60 * 60 * 24 * 30 * 12); } else { adminCodeCookie.setMaxAge(0); pwdCookie.setMaxAge(0); } response.addCookie(adminCodeCookie); response.addCookie(pwdCookie); // 验证码 String number = request.getParameter("vcode"); HttpSession session = request.getSession(); String code = session.getAttribute("code").toString(); if (number==null || !number.equalsIgnoreCase(code)) { request.setAttribute("vcode_err", "验证码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); } else { AdminInfoDAO adminInfoDAO = new AdminInfoDAO(); try { AdminInfo adminInfo = adminInfoDAO .findByAdminCode(adminCode); if (adminInfo == null || !adminInfo.getPassword().equals(password)) { request.setAttribute("login_err", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward( request, response); } else { response.sendRedirect("list.do"); } } catch (Exception e) { e.printStackTrace(); throw new ServletException(e); } } } } }
web.xml文件的配置代码如下所示:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>actionServlet</servlet-name> <servlet-class>web.ActionServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>actionServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet> <servlet-name>ValidateCode</servlet-name> <servlet-class>web.ValidateCode</servlet-class> </servlet> <servlet-mapping> <servlet-name>ValidateCode</servlet-name> <url-pattern>/code</url-pattern> </servlet-mapping> </web-app>
login.jsp文件的完整代码如下所示:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>达内-NetCTOSS</title> <link type="text/css" rel="stylesheet" media="all" href="styles/global.css" /> <link type="text/css" rel="stylesheet" media="all" href="styles/global_color.css" /> <style type="text/css"> .s1 { cursor: pointer; } </style> </head> <body class="index"> <div class="login_box"> <form name="login" action="login.do" method="post"> <% String adminCode = ""; String password = ""; Cookie[] cookies = request.getCookies(); System.out.println(cookies); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if ("AdminCode".equals(cookies[i].getName())) { adminCode = cookies[i].getValue(); } if ("Password".equals(cookies[i].getName())) { password = cookies[i].getValue(); System.out.println(password); break; } } } %> <table> <tr> <td class="login_info"> 帐号: </td> <td colspan="2"> <input name="adminCode" type="text" class="width150" value="<%=adminCode%>" /> </td> </tr> <tr> <td class="login_info"> 密码: </td> <td colspan="2"> <input name="password" type="password" class="width150" value="<%=password%>" /> </td> </tr> <tr> <td class="login_info"> 验证码: </td> <td colspan="2"> <input name="vcode" type="text" class="width150" /> <img src="code" onclick="this.src='code?'+Math.random();" class="s1" title="点击更换" /> </td> </tr> <tr> <td class="login_info"> <input type="checkbox" name="saveCookie" value="yes" checked /> </td> <td colspan="2"> 自动登录 </td> </tr> <tr> <td></td> <td class="login_button"> <a href="javascript:document.login.submit();"><img src="images/login_btn.png" /></a> </td> <td> <span class="required"> <% String errorMsg = (String) request.getAttribute("login_err"); String vcodeMsg = (String) request.getAttribute("vcode_err"); %> <span style="color: red;"><%=errorMsg == null ? "" : errorMsg%></span> <span style="color: red;"><%=vcodeMsg == null ? "" : vcodeMsg%></span> </span> </td> </tr> <tr> </tr> </table> </form> </div> </body> </html>