系 统 概 述
一个简单的留言板所实现的功能有:用户注册、用户登录、查看留言信息和留言四个功能。在学习了JSP/Servlet后编写的
一个简单的实例,虽然简单,却拥有一个完整系统的必要功能,所以可以让自己初步了解使用JSP/Servlet技术开发系统的一般步骤。
系统功能简介:
用户注册:当用户注册一个新用户时,就是向数据库user_table表中添加一条记录。
当用户输入注册信息后,将用户的的注册信息提交到服务端负责处理注册信息的Servlet。当Servlet成功处理完用户的信息后,
客户端自动跳转到【登录界面】进行登录。
用户登录:当用户输入用户名、密码和验证码时。系统将信息提交的处理登录信息的Servlet。Servlet则调用服务器控制器里
的方法来处理用户登录。当用户登录成功时,客户端自动跳转到【留言板】。
留言板:调用数据库中的留言信息,显示在页面上。同时用户可以通过【留言】按钮,跳转到【留言】界面,留言功能和注册功能
类似,向数据库ly_table表中添加一条记录。
数据库的设计:
对于该系统来说有两个表【user_table】和【ly_table】。
【user_table】如下:
字段名 | 类型 | 含义 |
id | int | 用户id |
username | varchar(20) | 用户名 |
password | varchar(20) | 密码 |
【ly_table】如下:
字段名 | 类型 | 含义 |
id | int | 留言信息的id |
userId | int | 用户的id |
title | varchar(25) | 标题名字 |
date | date | 留言时间 |
connect | text | 留言类容 |
实现系统的基础类:
实现在注册、登录系统中使用的一些重要的类:连接和操作数据库的DB类、存储用户的User类、
存储留言信息的LeaveMessageTable类和实现图形验证码的ValidationCode类。
连接和操作数据库的DB类中具体包括如下方法:
public User checkUser(String username , String password) :检查用户时候存在,存在就返回一个User对象,否则返回null 。
public boolean checkValidationCode(HttpServletRequest request ,String validationCode) :检测验证码是否正确。
public boolean addInfo(LeaveMessageTable ly) : 向数据库插入留言。
public boolean insertUser(String username,String password) :向数据库存入用户。
public ArrayList findLyInfo() : 从数据库中导出留言,返回一个ArrayList对象。
private ResultSet execSQL(String sql , Object ...args) : 执行SQL语句。
在DB类的构造函数中连接数据库。这样有Servlet类创建DB对象时,便在创建过程中进行数据库的连接。
package com.cnblogs.jbelial.DBServlet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import Common.Encrypter;
import Common.LeaveMessageTable;
import Common.User;
public class DB{
// 定义数据库连接变量
private Connection connection ;
// 定义参数
private String sql_driver = "com.mysql.jdbc.Driver" ;
private String sql_url = "jdbc:mysql://localhost:3306/web_ly_table" ;
private String sql_username = "root" ;
private String sql_password = "hezuoan" ;
public DB()
{
try
{
//建立数据库的连接
Class.forName(sql_driver) ;
connection = DriverManager.getConnection(sql_url,sql_username,sql_password) ;
}
catch(Exception e)
{
e.printStackTrace() ;
}
}
// 用于执行各种SQL语句的方法
private ResultSet execSQL(String sql , Object ...args)
throws SQLException
{
PreparedStatement pstmt = connection.prepareStatement(sql) ;
// 为PreparedStatement对象设置SQL参数
for (int i = 0 ; i < args.length ; ++ i)
{
pstmt.setObject(1 + i, args[i]) ;
}
// 运行
pstmt.execute() ;
return pstmt.getResultSet();
}
// 核对用户输入的验证码是否正确
public boolean checkValidationCode(HttpServletRequest request ,
String validationCode)
{
String validationCodeSession = (String) request.getSession().getAttribute("validationCode") ;
if(validationCodeSession == null)
{
// 给result.jsp设置信息
request.setAttribute("info" , "验证码过期") ;
// 给login.jsp设置信息
request.setAttribute("codeError", "验证码过期") ;
return false ;
}
if(!validationCode.equalsIgnoreCase(validationCodeSession))
{
request.setAttribute("info","验证码错误") ;
request.setAttribute("codeError", "验证码错误") ;
return false ;
}
return true;
}
// 检查用户登录信息
public User checkUser(String username , String password)
{
try
{
String sql = "select * from user_table where username = ? and password = ?" ;
ResultSet rs = execSQL(sql,username,password) ;
User user = new User() ;
while (rs.next())
{
user.setId(rs.getInt("id")) ;
user.setUsername(rs.getString("username")) ;
user.setPassword(rs.getString("password")) ;
return user ;
}
return null ;
}
catch(Exception e)
{
e.printStackTrace();
return null ;
}
}
// 插入留言
public boolean addInfo(LeaveMessageTable ly){
try{
String sql = "insert into ly_table(userId,data,title,content) values(?,?,?,?)" ;
execSQL(sql , ly.getUserId(), ly.getDate(),ly.getTitle(),ly.getContent());
return true;
}catch(Exception e){
e.printStackTrace();
return false;
}
}
// 插入用户
public boolean insertUser(String username,String password){
try{
String sql = "insert into user_table(username,password) values(?,?)" ;
execSQL(sql ,username , password) ;
return true;
}catch(Exception e){
e.printStackTrace();
return false;
}
}
// 获取留言信息。
public ArrayList findLyInfo()
{
ArrayList arrayList = new ArrayList() ;
try
{
String sql = "select * from ly_table" ;
ResultSet rs = execSQL(sql) ;
while(rs.next())
{
LeaveMessageTable ly = new LeaveMessageTable() ;
ly.setId(rs.getInt("id")) ;
ly.setUserId(rs.getInt("userId")) ;
ly.setDate(rs.getDate("data")) ;
ly.setTitle(rs.getString("title")) ;
ly.setContent(rs.getString("content")) ;
arrayList.add(ly) ;
}
return arrayList ;
}
catch(Exception e)
{
e.printStackTrace() ;
return null ;
}
}
// 获取用户名
public String getUserName(int id)
{
String username = null;
try{
String sql = "select username from user_table where id = ?" ;
ResultSet rs= execSQL(sql , new Object[]{id});
while(rs.next()){
username=rs.getString(1);
}
return username;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}
User类和LeaveMessageTable类:
User类中则包含Id、用户名和密码三个属性。同时包含各个属性的set和get方法。
package Common;
public class User {
// 用户的id
private int id ;
// 用户名
private String username ;
// 用户密码
private String password ;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
}
LeaveMessageTable类:包含了如下属性Id、留言用户Id、留言标题、留言时间、留言类容属性。同时也包含了各个属性的
set和get方法。
package Common;
import java.sql.Date;
public class LeaveMessageTable {
private int id ;
private int userId ;
private Date date ;
private String title ;
private String content ;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
实现图形验证码:
实现图形验证码大致分为5步上来完成:
1、建立图形缓冲区;
2、在图形缓冲区用随机颜色填充背景。
3、在图形缓冲区上输出验证码。
4、将验证码保存在HttpSession对象中。
5、向客户端输出图形验证码。
通过ValidationCode类来实现验证码功能,该类也是Servlet类,在客户端只要像访问普通Servlet一样访问ValidationCode类即可。
package com.cnblogs.jbelial.Validation;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.* ;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@SuppressWarnings("serial")
public class ValidationCode extends HttpServlet
{
// 图形验证码的字符集合,系统通过随机从这些字符串中选择一些字符作为验证码
private static String codeChars =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTYVWXYZ" ;
// 返回一个随机颜色
private static Color getRandomColor(int minColor , int maxColor)
{
Random random = new Random() ;
if (minColor > 255)
minColor = 255 ;
if (maxColor > 255)
maxColor = 255 ;
// 获取颜色的随机值
int red = minColor + random.nextInt(maxColor - minColor) ;
int green = minColor + random.nextInt(maxColor - minColor) ;
int blue = minColor + random.nextInt(maxColor - minColor) ;
return new Color(red,green,blue) ;
}
public void doGet (HttpServletRequest request ,
HttpServletResponse response) throws IOException
{
// 获取验证码集合的长度。
int charsLength = codeChars.length() ;
// 关闭浏览器缓冲区
response.setHeader("ragma", "No-cache") ;
response.setHeader("Cache-Control", "no-cache") ;
response.setDateHeader("Expires", 0) ;
// 设置图片传送的格式。
response.setContentType("image/jpeg");
// 设置图形验证码的长和宽度
int width = 90 ;
int height = 20 ;
// 建立图形缓冲区
BufferedImage image = new BufferedImage(width , height,
BufferedImage.TYPE_INT_RGB) ;
// 获取用于输出文字的Graphics对象
Graphics graphics = image.getGraphics() ;
Random random = new Random() ;
// 设置要填充的颜色
graphics.setColor(getRandomColor(180 , 250)) ;
// 填充图形背景
graphics.fillRect(0, 0, width, height) ;
// 设置初始字体和颜色
graphics.setFont(new Font("Time New Roman" , Font.ITALIC, height)) ;
graphics.setColor(getRandomColor(120,180)) ;
// 保存验证码
StringBuilder validationCode = new StringBuilder() ;
// 验证码的随机字体
String[] fontNames = {"Times New Roman" , "Book antiqua" , "Arial" } ;
// 随机生成验证码
for (int i = 0 ; i < 4 ; ++ i)
{
// 设置当前验证码字符的字体
graphics.setFont(new Font(fontNames[random.nextInt(3)] , Font.ITALIC ,
height)) ;
// 随机获得验证码的字符
char codeChar = codeChars.charAt(random.nextInt(charsLength)) ;
validationCode.append(codeChar) ;
graphics.setColor(getRandomColor(20,120)) ;
// 在图形上输出验证码字符
graphics.drawString(String.valueOf(codeChar), 16*i+random.nextInt(7),
height - random.nextInt(6) ) ;
}
// 获得Session对象,并设置Session对象为3分钟
HttpSession session = request.getSession();
session.setMaxInactiveInterval(5*60) ;
// 将验证码放入session对象中.
session.setAttribute("validationCode",validationCode.toString() ) ;
// 关闭graphics对象。
graphics.dispose() ;
// 向客户端发送图形验证码
ImageIO.write(image,"JPEG" ,response.getOutputStream()) ;
}
public void doPost (HttpServletRequest request ,
HttpServletResponse response) throws IOException
{
doGet(request , response) ;
}
}
实现注册系统:
包括一个register.jsp、result.jsp和RegisterServlet类。
RegisterServlet类负责处理处理用户的提交的注册信息。
RegisterServlet类在处理用户注册信息之前,创建DB类对象来连接数据库。然后通过调用DB类的方法来判断验证码是否正确和用户名是否被注册。
当一系列的判断都通过时,则向数据库中插入用户记录。
RegisterServlet类的最后不管是否向数据库中插入用户记录,都会跳转到result.jsp页面。
package com.cnblogs.jbelial.Register;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import Common.User;
import com.cnblogs.jbelial.DBServlet.DB;
public class RegisterServlet extends HttpServlet {
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// 设置字符集编码
request.setCharacterEncoding("UTF-8") ;
response.setContentType("UTF-8");
// 判断是否跳到【登录】
if (request.getParameter("login") != null)
{
response.sendRedirect("login.jsp") ;
return ;
}
DB db = new DB() ;
String username = null ;
// 设置result页面要跳转的页面
String page = "login.jsp" ;
try
{
// 获取界面的用户名和密码参数
username = request.getParameter("username") ;
String password = request.getParameter("password") ;
String validationCode = request.getParameter("validationCode") ;
// 核对验证码
if (!db.checkValidationCode(request, validationCode))
return ;
User user = db.checkUser(username,password) ;
if (user != null)
{
request.setAttribute("info", username + "已被使用!") ;
page = "register.jsp" ;
}
else if (db.insertUser(username , password))
{
// 定义result.jsp中使用的消息
request.setAttribute("info" , "用户注册成功") ;
}
request.setAttribute("page", page) ;
}
catch(Exception e) { }
finally
{
// 跳转到result.jsp
RequestDispatcher rd = request.getRequestDispatcher("/result.jsp") ;
rd.forward(request, response) ;
}
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response) ;
}
}
register.jsp则负责显示注册页面:
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>用户注册</title>
<script type="text/javaScript">
function refresh()
{
var img = document.getElementById("imgValidationCode") ;
img.src = "ValidationCode"+Math.random() ;
}
function checkRegister()
{
var username = document.getElementById("username") ;
if(username.value == "" )
{
alert("请输入用户名!") ;
//把焦点放到username输入文本上
username.focus() ;
return ;
}
var password = document.getElementById("password") ;
if(password.value == "" )
{
alert("请输入密码!");
password.focus() ;
return ;
}
var re_password = document.getElementById("re_password") ;
if(re_password.value != password.value)
{
alert("输入的密码不一致!") ;
re_password.focus() ;
return ;
}
var validationCode = document.getElementById("validationCode") ;
if(validatoinCode.value == "")
{
alert("请输入验证码!");
validatoinCode.focus() ;
return ;
}
register_form.submit() ;
}
</script>
</head>
<body>
<center>
<h2>用户注册</h2>
<form name = "register_form" action = "RegisterServlet" method = "post">
<table>
<tr>
<td>
用户名:
</td>
<td>
<input type = "text" id = "username" name = "username"
size = "25">
</td>
</tr>
<tr>
<td>
密码:
</td>
<td>
<input type = "password" id = "password" name = "password"
size = "25">
</td>
</tr>
<tr>
<td>
再次输入密码:
</td>
<td>
<input type = "password" id = "re_password" name = "re_password"
size = "25">
</td>
</tr>
<tr>
<td>
验证码:
</td>
<td>
<input type = "text" id = "validationCode" name = "validationCode"
style = "width:60px;margin-top:10px"/>
<img id = "imgValidationCode" src = "ValidationCode"/>
<input type = "button" value = "刷新" onclick = "refresh()"/>
</td>
</tr>
</table>
<input type = "button" value = "注册" onclick = "checkRegister()"/>
<input type = "submit" value = "登录" name = "login">
</form>
</center>
</body>
</html>
result.jsp页面则负责显示结果:
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<form name = "result_form" action = "${requestScope.page}" , method = "post">
${requestScope.info}
<input type = "submit" value = "确定" >
</form>
</body>
</html>
实现登录系统:
登录系统和注册系统类似,包含login.jsp和LoginServlet类。
LoginServlet类负责处理用户提交的登录信息。通过创建DB对象来连接数据库,再调用DB中的方法来判断用户提交的验证码和用户名、密码
的真确性,如果都正确则跳转到main.jsp,否则返回到login.jsp并显示提示消息;
package com.cnblogs.jbelial.Login;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import Common.User;
import com.cnblogs.jbelial.DBServlet.DB;
public class LoginServlet extends HttpServlet {
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置字符集编码
request.setCharacterEncoding("UTF-8") ;
response.setContentType("UTF-8");
// 判断是否跳到【注册】
if (request.getParameter("register") != null)
{
response.sendRedirect("register.jsp") ;
return ;
}
DB db = new DB() ;
// 设置跳转界面
String page = "login.jsp" ;
String username = null ;
try
{
// 获取请求页面的参数
username = request.getParameter("username") ;
String password = request.getParameter("password") ;
String validationCode = request.getParameter("validationCode") ;
// 验证码检测
if (!db.checkValidationCode(request, validationCode))
return ;
User user = db.checkUser(username,password) ;
if (user == null)
request.setAttribute("userError", "用户名或密码错误") ;
if (user != null)
{
// 如果根据检查,user不为空,表示用户名正确和密码正确,进行下一步操作。
ArrayList arrayList = new ArrayList() ;
arrayList = db.findLyInfo() ;
request.setAttribute("arrayList", arrayList) ;
// 设置跳转到主界面
page = "main.jsp" ;
request.getSession().setAttribute("user", user) ;
}
}
catch(Exception e){}
finally
{
request.setAttribute("username", username) ;
RequestDispatcher rd = request.getRequestDispatcher("/"+page) ;
rd.forward(request, response) ;
}
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response) ;
}
}
login.jsp则负责显示登录界面
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>用户登录</title>
</head>
<script type="text/javaScript">
function refresh()
{
var img = document.getElementById("imgValidationCode") ;
img.src = "ValidationCode" ;
}
function checkLogin()
{
var username = document.getElementById("username_id");
if (username.value == "" )
{
alert("请输入用户名!") ;
username.focus() ;
return ;
}
var password = document.getElementById("password_id") ;
if (password.value == "")
{
alert("密码不能为空");
password.focus() ;
return ;
}
var validationCode = document.getElementById("validationCode_id") ;
if ( validationCode.value == "")
{
alert("验证吗不能为空") ;
validationCode.focus() ;
return ;
}
login_form.submit() ;
}
</script>
<body>
<center>
<h2>用户登录</h2>
<form name = "login_form" action = "LoginServlet" method = "post" >
<table>
<tr>
<td>
用户名:
</td>
<td>
<input type = "text" id = "username_id" value = "${requestScope.username}" name = "username"
size = "25" />${requestScope.userError}
</td>
</tr>
<tr>
<td>
密 码:
</td>
<td>
<input type="password" id="password_id" name="password" size="25">
</td>
</tr>
<tr>
<td>
验证码:
</td>
<td>
<input type = "text" id = "validationCode_id" name = "validationCode"
style = "width:60px;margin-top:10px"/>
<img id = "imgValidationCode" src = "ValidationCode"/>
<input type = "button" value = "刷新" onclick = "refresh()"/>
${requestScope.codeError}
</td>
</tr>
</table>
<input type = "button" value = "登录" onclick = "checkLogin()">
<input type = "submit" value = "注册" name = "register">
</form>
</center>
</body>
</html>
实现留言系统:
addMessageServlet类就是把用户提交的留言信息提取出来,然后存入数据库。
main.jsp则在用户登录后,自动跳转到显示留言的界面。