Top

JAVA SERVLETJSP DAY07

  1. 使用Session实现访问计数
  2. 使用Session实现登录
  3. Session超时的设置
  4. URL重写
  5. 验证码
  6. 为登录添加验证码功能

1 使用Session实现访问计数

1.1 问题

记录不同客户端访问服务器的次数

1.2 方案

由于对不同的客户端需要区分,所以使用session记录不同客户端的数据。由于访问次数需要保留,所以使用setAttribute方法进行记录。第一次访问时存储为1,后续访问在此基础上自增。

1.3 步骤

步骤一:新建CountServlet

图- 1

步骤二:部署应用,访问

图- 2

步骤三:多次刷新页面查看计数变化

图- 3

步骤四:重启浏览器,查看页面输出

图- 4

步骤五:查看控制台输出窗口

图– 5

结论:sessionID跟随一次会话,存储在客户端浏览器的内存中一个叫JSESSIONID的Cookie里面。第一次创建后,只要不关闭浏览器,那么每一次的请求sessionID都会被自动发送到服务器端。重启浏览器后,sessionID会被销毁,重新创建新的数值。

图- 6

图- 7

图-6为第一次访问,JSESSIONID在响应头中以Set-Cookie的形式传回客户端。图-7为刷新页面时的数据包,在请求头中,JSESSIONID以Cookie消息头的形式发给服务器端,以此同一个ID值找到对应的session对象。

1.4 完整代码

CountServlet.java文件的代码:

package web;

import java.io.IOException;
import java.io.PrintWriter;

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 CountServlet extends HttpServlet {

	public void service(HttpServletRequest request, 
						HttpServletResponse response)
						throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();		
		//获取session对象
		HttpSession session = request.getSession();		
		//输出sessionID
		System.out.println(session.getId());		
		//获取绑定的计数器
		Integer count = (Integer)session.getAttribute("count");		
		if(count==null){//第一次访问
			count = 1;
		}else{//不是第一次访问
			count++;
		}		
		//在session中绑定计数器
		session.setAttribute("count", count);		
		//输出提示信息
		out.println("这是第"+count+"次访问");
		out.close();
	}
}

web.xml文件代码:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="/java.sun.com/xml/ns/javaee"
 xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="/java.sun.com/xml/ns/javaee   /java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>CountServlet</servlet-name>
<servlet-class>web.CountServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CountServlet</servlet-name>
<url-pattern>/count</url-pattern>
</servlet-mapping>
</web-app>

2 使用Session实现登录

2.1 问题

保存登录信息,保护某些资源只有在登录验证之后才能访问。

2.2 方案

登录信息提交后进行验证,验证通过则将用户信息保存在session中,验证失败则转发回登录页面。对于需要保护的资源,添加从session中获取绑定值的功能,以判断是否能够成功获取绑定的用户信息为判断依据,获取到则代表已验证,则允许访问,获取不到绑定在session中的用户信息,代码验证没有通过,则拒绝访问该资源,而将请求重定向到登录页面。

2.3 步骤

步骤一:新建login.jsp页面

图– 8

图- 9

步骤二:新建ActionServlet类及配置

图– 10

图- 11

步骤三:新建index.jsp页面

图- 12

步骤四:部署后直接访问index.jsp页面

部署后访问index.jsp失败,会重定向到login.jsp页面

图- 13

步骤五:在login.jsp页面进行登录

图- 14

步骤六:新开页面后直接访问index.jsp页面

图- 15

在新开的页面直接访问index.jsp页面也能够看到显示的登录信息。

步骤七:重启浏览器后访问index.jsp页面

重启浏览器后,直接访问index.jsp页面,结果与步骤四一致。因为,关闭浏览器后保存的JSESSIONID信息会丢失,以至于无法再在服务器中找到绑定了登录信息的session对象,于是认为没有登录过,进行了重定向操作。

步骤八:修改index.jsp页面,添加“登出”链接

图- 16

步骤九:修改ActionServlet

图- 17

步骤十:重新访问login.jsp进行登录

图- 18

步骤十一:点击“登出”后,再次访问index.jsp

登出后,再次直接输入地址访问index.jsp,结果同步骤四,重定向到login.jsp页面。符合登出功能的效果。

2.4 完整代码

ActionServlet.java文件:

package web;

import java.io.IOException;
import java.io.PrintWriter;

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 ActionServlet extends HttpServlet {

	public 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("."));
		HttpSession session = request.getSession();
		System.out.println(session.getId());		
		// 判断动作是否为登录
		if (action.equals("login")) {
			String name = request.getParameter("uname");
			String pwd = request.getParameter("pwd");						
			if (name.equals("111") && pwd.equals("111")) {
				session.setAttribute("uname", name);
				// 重定向到首页
				response.sendRedirect("index.jsp");
			} else {
				// 登录失败
				request.setAttribute("msg", "用户名或密码错误");
				request.getRequestDispatcher("login.jsp").forward(request,
						response);
			}
		} else if (action.equals("logout")) {
			// session失效
			session.invalidate();
			response.sendRedirect("login.jsp");
		}
		out.close();
	}

}

web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="/java.sun.com/xml/ns/javaee"
 xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="/java.sun.com/xml/ns/javaee   /java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>CountServlet</servlet-name>
<servlet-class>web.CountServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ActionServlet</servlet-name>
<servlet-class>web.ActionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CountServlet</servlet-name>
<url-pattern>/count</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ActionServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

login.jsp文件:

<%@ page contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
	<head>	
		<title>Insert title here</title>		
	</head>
	<body>
	<h3>登录</h3>
	<form action="login.do" method="post">
		用户名:<input name="uname"/><Br><br>
		密码:<input name="pwd" type="password"/><br><Br>		
		<input type="submit" value="登录"/>
	</form>
	</body>
</html>

index.jsp文件:

<%@ page contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//session验证
	Object uname = session.getAttribute("uname");
	if(uname == null){
		response.sendRedirect("login.jsp");
		return;
	}
%>
<html>
	<head>			
	</head>
	<body>
	<h3>首页</h3>欢迎你:<%=uname.toString()%><br><Br><Br>	
	<a href="logout.do">登出</a>	
	</body>
</html>

3 Session超时的设置

3.1 问题

使用编程式,修改session的超时时间为10秒。实现当用户登陆后,如果十秒钟没有任何动作,则session时效,此时再访问index.jsp页面,则依然会重定向到login.jsp页面,重新登录。

3.2 方案

使用setMaxInactiveInterval(10)方法实现编程式的session超时设置。时间单位为秒。

3.3 步骤

步骤一:修改ActionServlet

在创建session后,设置超时时间为10秒。

图- 19

步骤二:访问login.jsp页面后十秒内不操作

访问login.jsp,输入用户信息进行登录,到达index.jsp页面后,不再有任何动作,过十秒后,刷新index.jsp页面,请求会重定向到login.jsp页面。

如果以声明式的方式修改超时时间,则需要到tomcat的conf目录下,寻找web.xml文件,修改session-timeout。

图- 20

3.4 完整代码

ActionServlet.java文件代码:

package web;

import java.io.IOException;
import java.io.PrintWriter;

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 ActionServlet extends HttpServlet {

	public 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("."));
		

		// 判断动作是否为登录
		if (action.equals("login")) {
			String name = request.getParameter("uname");
			String pwd = request.getParameter("pwd");
			if (name.equals("111") && pwd.equals("111")) {
HttpSession session = request.getSession();
		System.out.println(session.getId());
		// 编程式--设定session超时时间为10秒
		session.setMaxInactiveInterval(10);
	session.setAttribute("uname", name);
				// 重定向到首页
				response.sendRedirect("index.jsp");				
			} else {
				// 登录失败
				request.setAttribute("msg", "用户名或密码错误");
				request.getRequestDispatcher("login.jsp").forward(request,
						response);
			}
		} else if (action.equals("logout")) {
HttpSession session = request.getSession();
			// session失效
			session.invalidate();
			response.sendRedirect("login.jsp");
		}
		out.close();
	}

}

4 URL重写

4.1 问题

如果浏览器禁用Cookie,则session不能再继续使用。如何在禁用Cookie的情况下依然能继续使用session。

4.2 方案

使用URL重写的方法,即改写原本的访问地址,在URI后面使用参数的方式携带上sessionID。

4.3 步骤

步骤一:修改ActionServlet

图- 21

步骤二:禁用浏览器Cookie

图- 22

步骤三:使用login.jsp完成登录

图 - 23

由于禁用了cookie,所以要想继续使用session那么就可以通过如上方式,在URL中添加sessionID信息,以达到传递id标识的作用。

4.4 完整代码

ActionServlet.java文件代码:

package web;

import java.io.IOException;
import java.io.PrintWriter;

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 ActionServlet extends HttpServlet {

	public 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("."));
		HttpSession session = request.getSession();
		System.out.println(session.getId());
		// 编程式--设定session超时时间为10秒
		//session.setMaxInactiveInterval(10);
		// 判断动作是否为登录
		if (action.equals("login")) {
			String name = request.getParameter("uname");
			String pwd = request.getParameter("pwd");			
			if (name.equals("111") && pwd.equals("111")) {
				session.setAttribute("uname", name);
				// 重定向到首页				
				 response.sendRedirect(
				        response.encodeRedirectURL("index.jsp"));
			} else {
				// 登录失败
				request.setAttribute("msg", "用户名或密码错误");				request.getRequestDispatcher("login.jsp").forward(request,
						response);
			}
		} else if (action.equals("logout")) {
			// session失效
			session.invalidate();
			response.sendRedirect("login.jsp");
		}
		out.close();
	}

}

5 验证码

5.1 问题

根据随机产生的字符串绘制图片,并输出到jsp页面中

5.2 方案

使用java的绘图技术,动态绘制一张图片,由Servlet完成后,通过OutputStream将其内容输出到客户端。浏览器通过img标签的src属性访问该Servlet以获得动态图片。

5.3 步骤

步骤一:创建validateCode.jsp页面

图- 24

步骤二:创建ValidateCode.java文件

图- 25

步骤三:部署后访问查看图片

图- 26

5.4 完整代码

ValidateCode.java文件代码:

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.io.PrintWriter;
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);		
		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;
	}

}

validateCode.jsp文件代码:

<%@ page contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<html>
	<head>	
		<title>Insert title here</title>
		<style type="text/css">
			.s1{
				cursor:pointer;
			}
		</style>
	</head>
	<body>
		验证码:<input name="vcode"/>
		<img src="code" onclick="this.src='code?'+Math.random();" 
		class="s1" title="点击更换" />
	</body>
</html>

web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="/java.sun.com/xml/ns/javaee"
 xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="/java.sun.com/xml/ns/javaee   /java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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>

6 为登录添加验证码功能

6.1 问题

在登录时添加验证码功能。

6.2 方案

在产生验证码的随机字符串之后,绑定到session中,验证过程中将用户输入和session绑定中的验证码比对一致后再判断用户名和密码。

6.3 步骤

步骤一:修改ValidateCode.java文件

图 - 27

步骤二:修改login.jsp页面

图– 28

图 - 29

步骤三:修改ActionServlet.java文件

图 - 30

步骤四:重新部署,访问应用

用户名和密码以及验证码均正确的情况下登录成功。验证码区分大小写。登出后直接访问index.jsp会自动回到login.jsp页面。

6.4 完整代码

ValidateCode.java文件:

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.io.PrintWriter;
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;
	}

}

login.jsp文件:

<%@ page contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
	<head>	
		<title>Insert title here</title>
		<style type="text/css">
			.s1{
				cursor:pointer;
			}
		</style>
	</head>
	<body>
	<h3>登录</h3>
	<form action="login.do" method="post">
		用户名:<input name="uname"/><Br><br>
		密码:<input name="pwd" type="password"/><br><Br>
		验证码:<input name="vcode"/>
		<img src="code" onclick="this.src='code?'+Math.random();" 
		class="s1" title="点击更换" /><br><Br>
		<input type="submit" value="登录"/>
	</form>
	</body>
</html>

ActionServlet文件:

package web;

import java.io.IOException;
import java.io.PrintWriter;

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 ActionServlet extends HttpServlet {

	public 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("."));			
		// 判断动作是否为登录
		if (action.equals("login")) {
			String name = request.getParameter("uname");
			String pwd = request.getParameter("pwd");
			String number = request.getParameter("vcode");
			HttpSession session = request.getSession();
			String code = session.getAttribute("code").toString();
			if (number.equals(code) && name.equals("111") && pwd.equals("111")) {
				// 编程式--设定session超时时间为10秒
				//session.setMaxInactiveInterval(10);
				session.setAttribute("uname", name);
				// 重定向到首页
				//response.sendRedirect("index.jsp");
				 response.sendRedirect(
				 response.encodeRedirectURL("index.jsp"));
			} else {
				// 登录失败
				request.setAttribute("msg", "用户名或密码错误");
				request.getRequestDispatcher("login.jsp").forward(request,
						response);
			}
		} else if (action.equals("logout")) {
			HttpSession session = request.getSession();
			// session失效
			session.invalidate();
			response.sendRedirect("login.jsp");
		}
		out.close();
	}

}

web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="/java.sun.com/xml/ns/javaee"
 xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="/java.sun.com/xml/ns/javaee   /java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>CountServlet</servlet-name>
<servlet-class>web.CountServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ActionServlet</servlet-name>
<servlet-class>web.ActionServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ValidateCode</servlet-name>
<servlet-class>web.ValidateCode</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CountServlet</servlet-name>
<url-pattern>/count</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ActionServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ValidateCode</servlet-name>
<url-pattern>/code</url-pattern>
</servlet-mapping>
</web-app>