您的位置:首页 > 其它

Servlet中不可不知的Session技术

2017-05-02 15:59 573 查看

目录

目录

介绍

Session和Cookie的主要区别

Session的创建

Session的销毁

Session的实现原理

解决浏览器关闭后就立即丢失Session ID的问题

浏览器禁用Cookie后如何使用Session技术?

Session案例
用session实现简单的购物车效果

利用session完成用户登录功能

服务器端session防表单重复提交

利用session校验图片验证码

介绍

  Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的Session对象,由于Session为用户浏览器独享,所以用户在访问服务器的Web资源时,可以把各自的数据放在各自的Session中,当用户再去访问服务器中的其它Web资源时,其它Web资源再从用户各自的Session中取出数据为用户服务。

  在Web开发中,服务器可以为每个用户浏览器创建一个会话对象(Session对象),注意:一个浏览器独占一个Session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。

Session和Cookie的主要区别

Cookie是把用户的数据写给用户的浏览器;

Session技术把用户的数据写到用户独占的session中(即保存在服务器端)。

Session的创建

  在一次会话中,服务器首次需要针对该会话操作session时(在Java Web中即request.getSession(),在PHP中即session_start()),服务器才创建session,而不是用户首次访问服务器的某个网站后就立刻创建session的。

  参考:

session什么时候被创建 http://blog.sina.com.cn/s/blog_89a6f5b001010gy9.html session的创建和时间设置 http://blog.csdn.net/w8998036/article/details/51026966 php创建session的方法实例详解 http://www.jb51.net/article/60397.htm[/code] 
  Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。如:

HttpSession session = request.getSession();


  使用过程中,没有向getSession方法传递参数,则表示session未创建的情况下先创建session后再返回session对象,如果session已被创建则直接返回session对象。getSession方法存在对象的重载方法,接收一个布尔类型的参数。如:

HttpSession session = request.getSession(false);


  getSession(false) 则表示不管session有没有被创建,都不再创建session;getSession(true) 则强制创建session。

Session的销毁

  在Java中,默认session在30分钟之内未被使用,服务器就会将session销毁,不管用户浏览器此时有没有关闭。即便用户关闭了浏览器,结束了当前会话,session也不会立即销毁,直到默认时效内session未被使用。

  可以通过Web应用的配置文件web.xml,配置session的有效时间,如这里设置为10分钟:

<session-config>
<session-timeout>10</session-timeout>
</session-config>


  手动销毁session,则调用session对象的方法,如:

session.invalidate();


Session的实现原理

  用户打开浏览器访问服务器的某一应用资源后,如 ServletDemo(用户向服务器的一个Servlet发起了请求)。在该Servlet中服务器调用:

HttpSession session = request.getSession();


  则服务器将会判断针对当次会话是否创建了Session,实际上在创建Session的过程中即服务器为该会话生成了一个唯一的标识,我们称之为Session ID,与此同时,请求响应将返回保存了Session ID的Cookie信息。

  该Cookie的名称为
JSESSIONID
(在PHP中则为
PHPSESSID
),默认当浏览器关闭时该Cookie将被销毁。

  浏览器端通过获取到该Cookie信息后,用户下次再发起请求时(可以请求与上一次不同的Web资源),则将携带Cookie信息到服务器,服务器通过该Cookie就可以根据Session ID得知当前会话保存的Session。上次请求操作保存在session中的信息,在下次请求操作也同样可以读取到session中保存的信息。

解决浏览器关闭后就立即丢失Session ID的问题

  根据Session实现原理,我们可以知道,在默认情况下,当我们关闭浏览器后保存Session ID的Cookie也将被销毁,即我们再次打开浏览器发送相同请求,获得到的Session对象也不再与之前相同。

  需要注意的是,关闭浏览器后服务器存储的Session不一定就被销毁了,服务器存储的Session是在一定时间内未被操作,服务器才会将其销毁。这里关闭浏览器之后无法再使用上次Session的原因,在于我们丢失了Session ID(保存Cookie的Session ID默认在浏览器关闭时销毁)。

  那么解决这样的问题,我们只需要延长保存Session ID的Cookie的有效期限即可。如:

//=========== 解决浏览器关闭后就立即丢失Session ID的问题(延长保存Session ID的Cookie的有效期,默认没有设置该Cookie的有效期,即浏览器关闭则该Cookie被销毁) ============
String sessionId = session.getId();
Cookie cookie = new Cookie("JSESSIONID", sessionId);
cookie.setPath("/day07/"); // path的值需要与原来的一致才行
cookie.setMaxAge(30 * 60); // 设置为30分钟内有效
response.addCookie(cookie);
//=========== 解决浏览器关闭后就立即丢失Session ID的问题 ============


浏览器禁用Cookie后如何使用Session技术?

  从Session的实现原理中,我们可以发现Session的实现需要依赖于Cookie,那么当用户浏览器禁用了Cookie后又该如何使用Session技术呢?

  Session的实现原理最基本的是要求用户在每次请求时发送保存有Session ID的信息(如发送保存有Session ID的Cookie)。禁用Cookie后,我们可以为页面中每条请求增加一个参数,用于发送Session ID的值。这样,服务器获取到Session ID后就可以获取到用户独占的Session,为用户服务。

  在Java中,通过request对象的getSession方法获取session对象,getSession方法会先判断请求是否发送了含有Session ID的Cookie过来,如果没有,则会判断请求中是否发送了保存Session ID的参数过来。这两种情况下都未能获取到Session ID的话,服务器则判定还未替当前用户创建独占的session,并为用户进行创建。

  示例:

WelcomeServlet.java

package com.wm103.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
* Created by DreamBoy on 2017/5/2.
*/
@WebServlet(name = "WelcomeServlet", urlPatterns = {"/WelcomeServlet"})
public class WelcomeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession();

response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();

String url1 = response.encodeURL("/day07/SessionDemo1"); // 通过encodeURL方法为该请求增加Session ID的参数;如前面getSession方法是通过Cookie获取到Session ID的,则这里不会增加Session ID这个参数,因为服务器可以判断用户浏览器未禁用Cookie。如果是首次创建Session同样也会添加Session ID参数。
String url2 = response.encodeURL("/day07/SessionDemo2");
out.print("<a href='" + url1 + "'>购买</a>   ");
out.print("<a href='" + url2 + "'>结账</a>");
}
}


  注:通过repsonse对象的encodeURL方法为该请求增加Session ID的参数;如前面getSession方法是通过Cookie获取到Session ID的,则这里不会增加Session ID这个参数,因为服务器可以判断用户浏览器未禁用Cookie。如果是首次创建Session同样也会添加Session ID参数。

SessionDemo1.java

package com.wm103.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

/**
* Created by DreamBoy on 2017/5/1.
*/
@WebServlet(name = "SessionDemo1", urlPatterns = {"/SessionDemo1"})
public class SessionDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("name", "笔记本");
}
}


ServletDemo2.java

package com.wm103.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
* Created by DreamBoy on 2017/5/1.
*/
@WebServlet(name = "SessionDemo2", urlPatterns = {"/SessionDemo2"})
public class SessionDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");

HttpSession session = request.getSession();
response.getWriter().write((String) session.getAttribute("name"));
}
}


  示例效果(这里演示的是未禁用Cookie的情况下的使用效果):

用户首次访问时,服务器创建Session,此时页面中所有请求的链接均被加上Session ID参数值。



用户点击购买后,返回首页,刷新。此时服务器将接收到浏览器端的Cookie,判定用户浏览器未禁用Cookie,则未向页面中的所有请求链接添加Session ID参数值。



用户点击结账,查看购买的商品



Session案例

用session实现简单的购物车效果

  将购买后的商品保存在session中,显示购物车页面时,从session中取出所有购买后的商品。

  显示商品列表 ListBookServlet.java

package com.wm103.shopping;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;

/**
* Created by DreamBoy on 2017/5/2.
*/
@WebServlet(name = "ListBookServlet", urlPatterns = {"/ListBookServlet"})
public class ListBookServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();

// 输出网站所有商品
out.print("<div style='margin: 20px 50px; padding: 10px 30px; border: 1px solid #eee; box-shadow: 0 2px 2px #ede'>");
out.write("<h3>本网站有如下商品:</h3>");
out.print("<ul>");
Map<String, Book> map = Db.getAll();
for (Map.Entry<String, Book> entry: map.entrySet()) {
Book book = entry.getValue();
out.print("<li style='line-height: 2'>" + book.getName() + " <a href='/day07/BuyServlet?id=" + book.getId() + "' target='_blank'>购买</a></li>");
}
out.print("</ul>");
out.print("</div>");
}
}

class Db {
private static Map<String, Book> map = new LinkedHashMap<>();
static { // 静态代码块
map.put("1", new Book("1", "JavaWeb开发", "007号", "一本关于JavaWeb开发的书"));
map.put("2", new Book("2", "JDBC开发", "008号", "一本关于JDBC开发的书"));
map.put("3", new Book("3", "Spring开发", "009号", "一本关于Spring开发的书"));
map.put("4", new Book("4", "Struts开发", "010号", "一本关于Struts开发的书"));
map.put("5", new Book("5", "Android开发", "011号", "一本关于Android开发的书"));
}

public static Map<String, Book> getAll() {
return map;
}
}

class Book implements Serializable {
private String id;
private String name;
private String author;
private String description;

public Book() {
}

public Book(String id, String name, String author, String description) {
this.id = id;
this.name = name;
this.author = author;
this.description = description;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}
}


  处理购买请求 BuyServlet.java

package com.wm103.shopping;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* Created by DreamBoy on 2017/5/2.
*/
@WebServlet(name = "BuyServlet", urlPatterns = {"/BuyServlet"})
public class BuyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
Book book = Db.getAll().get(id);

HttpSession session = request.getSession();
// 手工以Cookie形式发SessionId,以解决关闭浏览器后,重新打开浏览器上次购买的东西还在

// 从session中得到用户用于保存所有书的集合(购物车)
List list = (List) session.getAttribute("list");
if(list == null) {
list = new ArrayList<>();
}
list.add(0, book);
session.setAttribute("list", list);

//response.sendRedirect("/day07/ListCartServlet");
response.sendRedirect(request.getContextPath() + "/ListCartServlet");
}
}


  显示购物车页面 ListCartServlet.java

package com.wm103.shopping;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
* Created by DreamBoy on 2017/5/2.
*/

/**
* 显示用户购买的商品
*/
@WebServlet(name = "ListCartServlet", urlPatterns = {"/ListCartServlet"})
public class ListCartServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();

HttpSession session = request.getSession(false);
if(session == null) {
out.write("您还没有购买任何商品!" + "<a href='/day07/ListBookServlet'>前往购买</a>");
return;
}

List<Book> list = (List) session.getAttribute("list");
out.print("<div style='margin: 20px 50px; padding: 10px 30px; border: 1px solid #eee; box-shadow: 0 2px 2px #ede'>");
out.write("<h3>您购买了如下商品:</h3>");
out.print("<ul>");
for (Book book: list) {
out.print("<li style='line-height: 2'>" + book.getName() + "</li>");
}
out.print("</ul>");
out.print("</div>");
}
}


利用session完成用户登录功能

  登录页面 login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form action="/day07/LoginServlet" method="post">
<label>用户名:</label><input type="text" name="username"><br/>
<label>密 码:</label><input type="password" name="password"><br/>
<input type="submit" value="登录">
</form>
</body>
</html>


  处理登录请求 LoginServlet.java

package com.wm103.login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

/**
* Created by DreamBoy on 2017/5/2.
*/
@WebServlet(name = "LoginServlet", urlPatterns = {"/LoginServlet"})
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");

List<User> list = DB.getAll();
for(User user: list) {
if(user.getUsername().equals(username) && user.getPassword().equals(password)) {
HttpSession session = request.getSession();
session.setAttribute("user", user); // 登录成功,向session存入一个登录标记
response.sendRedirect(request.getContextPath() + "/index.jsp");
return;
}
}

response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.write("用户名或密码错误!");
}
}


  User.java

package com.wm103.login;

/**
* Created by DreamBoy on 2017/5/2.
*/
public class User {
private String username;
private String password;

public User() {
}

public User(String username, String password) {
this.username = username;
this.password = password;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}


  模拟数据库操作 DB.java

package com.wm103.login;

import java.util.ArrayList;
import java.util.List;

/**
* Created by DreamBoy on 2017/5/2.
*/
public class DB {
public static List<User> list = new ArrayList<>();
static {
list.add(new User("aaa", "123"));
list.add(new User("bbb", "123"));
list.add(new User("ccc", "123"));
}
public static List getAll() {
return list;
}
}


  登录成功后跳转首页 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
欢迎您,${user.username}! <a href="/day07/LogoutServlet">退出登录</a>
</body>
</html>


  退出登录 LogoutServlet.java

package com.wm103.login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
* Created by DreamBoy on 2017/5/2.
*/

/**
* 用户注销
*/
@WebServlet(name = "LogoutServlet", urlPatterns = {"/LogoutServlet"})
public class LogoutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(false);
if(session == null) {
response.sendRedirect(request.getContextPath() + "/index.jsp");
return;
}

session.removeAttribute("user");
response.sendRedirect(request.getContextPath() + "/login.html");
}
}


服务器端session防表单重复提交

表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在form表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。

当用户提交form表单时,负责处理表单提交的servlet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。

在下列情况下,服务器程序将拒绝用户提交的表单请求:

存储Session域中的表单标识号与表单提交的标识号不同

当前用户的Session中不存在表单标识号

用户提交的表单数据中没有标识号字段

处理生成随机标识号的Servlet FormSerlvet.java

package com.wm103.form;

import sun.misc.BASE64Encoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

/**
* Created by DreamBoy on 2017/5/2.
*/
@WebServlet(name = "FormServlet", urlPatterns = {"/FormServlet"})
public class FormServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 产生随机数(表单号)
TokenProcessor tp = TokenProcessor.getInstance();
String token = tp.generateToken();

request.getSession().setAttribute("token", token);
request.getRequestDispatcher("/form.jsp").forward(request, response);
}
}

class TokenProcessor {
/*
* 1. 把构造方法私有
* 2. 自己创建一个
* 3. 对外暴露一个方法:允许获取上面创建的对象
*/
private TokenProcessor() {}
private static final TokenProcessor instance = new TokenProcessor();

public static TokenProcessor getInstance() {
return instance;
}

public String generateToken() {
String token = System.currentTimeMillis() + new Random().nextInt() + "";
try {
MessageDigest md = MessageDigest.getInstance("md5"); // 消息摘要
byte[] md5 = md.digest(token.getBytes()); // 128位,16字节

// base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(md5);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}


  显示form表单的页面 form.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>防止表单重复提交</title>
</head>
<body>
<form action="/day07/DoFormServlet" method="post">
<input type="hidden" name="token" value="${token}">
<label>用户名:</label><input type="text" name="username"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>


  处理表单请求 DoFormServlet.java

package com.wm103.form;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
* Created by DreamBoy on 2017/5/2.
*/

/**
* 处理表单提交请求
*/
@WebServlet(name = "DoFormServlet", urlPatterns = {"/DoFormServlet"})
public class DoFormServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*String username = request.getParameter("username");

// 模拟网络延迟
try {
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("向数据库中注册用户——" + username);*/

boolean b = isTokenValid(request);
if(!b) {
System.out.println("请不要重复提交表单!");
return;
}

request.getSession().removeAttribute("token");
String username = request.getParameter("username");
System.out.println("向数据库中注册用户——" + username);
}

/**
* 判断表单号是否有效
* @param request
* @return
*/
private boolean isTokenValid(HttpServletRequest request) {
String clientToken = request.getParameter("token");
if (clientToken == null || clientToken.equals("")) {
return false;
}
HttpSession session = request.getSession(false);
if (session == null) {
return false;
}
String serverToken = (String) session.getAttribute("token");
return serverToken != null && clientToken.equals(serverToken);
}
}


利用session校验图片验证码

  生成验证码图片后,并用session保存验证码的内容用于校验下次用户输入提交的验证码是否正确。

  生成图片验证码 ImageServlet.java

package com.wm103.checkcode;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

/**
* Created by DreamBoy on 2017/4/28.
*/

/**
* 输出一张随机图片(图片验证码)
*/
@WebServlet(name = "ImageServlet", urlPatterns = {"/ImageServlet"})
public class ImageServlet extends HttpServlet {
public static final int WIDTH = 120;
public static final int HEIGHT = 50;

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();

// 1. 设置背景色
this.setBackground(g);

// 2. 设置边框
this.setBorder(g);

// 3. 画干扰线
this.drawRandomLine(g);

// 4. 写随机数
String random = this.drawRandomNum((Graphics2D) g);
request.getSession().setAttribute("checkcode", random);

// 5. 图片写给浏览器
response.setContentType("image/jpeg");
// 控制浏览器不要缓存图片
response.setDateHeader("expires", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");

ImageIO.write(image, "jpg", response.getOutputStream());

}

private void setBackground(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
}

private void setBorder(Graphics g) {
g.setColor(Color.BLUE);
g.drawRect(1, 1, WIDTH - 2, HEIGHT - 2);
}

private void drawRandomLine(Graphics g) {
g.setColor(Color.GREEN);
for(int i = 0; i < 5; i++) {
int x1 = new Random().nextInt(WIDTH);
int y1 = new Random().nextInt(HEIGHT);

int x2 = new Random().nextInt(WIDTH);
int y2 = new Random().nextInt(HEIGHT);
g.drawLine(x1, y1, x2, y2);
}
}

private String drawRandomNum(Graphics2D g) {
int fontSize = 20;
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.BOLD, fontSize));

String base = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789";
int fontNum = 4;
int y = 32;
int x = 18; String ch;
StringBuffer sb = new StringBuffer();
for(int i = 0; i < fontNum; i++) {
int degree = new Random().nextInt() % 30;
double radian = degree * Math.PI / 180; // 弧度
g.rotate(radian, x, y); // 设置旋转的弧度

ch = base.charAt(new Random().nextInt(base.length())) + "";
sb.append(ch);
g.drawString(ch, x, y);

g.rotate(-radian, x, y);
x += 25;
}
return sb.toString();
}
}


  使用图片验证码页面 register.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<form action="/day07/RegisterServlet" method="post">
<p><label>用户名:</label><input type="text" name="username"></p>
<p><label>密 码:</label><input type="password" name="password"></p>
<p><label>验证码:</label><input type="text" name="checkcode">
<img style="cursor:pointer;" src="/day07/ImageServlet" alt="换一张" onclick="this.src = '/day07/ImageServlet?' + new Date().getTime()"></p>
<input type="submit" value="注册">
</form>
</body>
</html>


  处理注册请求,这里只校验填写的验证码是否正确 RegisterServlet.java

package com.wm103.checkcode;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* Created by DreamBoy on 2017/5/2.
*/
@WebServlet(name = "RegisterServlet", urlPatterns = {"/RegisterServlet"})
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// request.setCharacterEncoding("UTF-8"); // 如果是中文验证码则需要处理中文编码的问题

// 处理注册请求之前,校验验证码是否有效
String c_checkcode = request.getParameter("checkcode");
String s_checkcode = (String) request.getSession().getAttribute("checkcode");
System.out.println(c_checkcode);
System.out.println(s_checkcode);
if(c_checkcode != null && s_checkcode != null && c_checkcode.toLowerCase().equals(s_checkcode.toLowerCase())) {
System.out.println("处理注册请求!");
} else {
System.out.println("验证码验证失败!");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息