1 简述Session的工作原理。

参考答案

浏览器访问Web服务器时,服务器会为每一个浏览器在服务器端的内存中分配空间,单独创建一个Session对象,该对象有一个Id属性,其值唯一,一般称之为SessionId,并且服务器会将这个SessionId(使用Cookie的方式)发送给浏览器;浏览器再次访问服务器时,会将SessionId发送给服务器,服务器可以依据SessionId找到对应的Session对象。

2 下列说法正确的是() 。

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对象。

3 简述什么是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 ){}

4 为NETCTOSS系统的登录增加验证码功能。

在课后练习“使用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>