首先项目的结构及所用到的jar包如图:
主要用到jdbc和jstl的jar包,大家可自行去相应网站下载
一、数据库和数据表的创建
1.建库语句:
create database test;
2.建表语句:
CREATE TABLE `t_users` (
`user_name` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`password_md5` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
二、eclipse配置数据库连接池
首先创建一个动态web项目
1.把jdbc所用到的jar包复制到/web-inf/lib目录下,如图:
2.在meta-inf下创建一个context.xml文件,并输入以下代码:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/test" reloadable="true">
<!-- 配置数据源 -->
<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" maxActive="100"
maxldle="30" maxWait="10000" name="jdbc/test" password="root" type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/test?autoReconnect=true" username="root">
</Resource>
</Context>
<Resource属性说明>
1)name:指定Resource的JNDI名字。
2)auth:指定管理Resource的Manager,它有两个可选值:Container和Application。Container表示由容器来创建和管理Resource,Application表示由web应用来创建和管理Resource。
3)type:指定Resource的Java类名。
4)username:指定连接数据库的用户名。
5)password:指定连接数据库的口令。
6)driverClassName:指定连接数据库的JDBC驱动器中的Driver实现类的名字。
7)url:指定连接数据库的URL,127.0.0.1是要连接的数据库服务器的ip,3306是数据库服务器端口,BookDB是数据库名称。
8)maxActive:指定数据库连接池中处于活动状态的数据库连接的最大数目,取值为0,表示不受限制。
9)maxIdle:指定数据库连接池中处于空闲状态的数据库连接的最大数目,取值为0,表示不受限制。
10)maxWait:指定数据库连接池中的数据库连接处于空闲状态的最长时间(以毫秒为单位),超过这一时间,将会抛出异常。取值为-1,表示可以无限期等待。
3.配置web.xml
在<web-app></web-app>之间加入如下代码:
<resource-ref>
<description>MySQL DBCP</description>
<res-ref-name>jdbc/test</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>属性说明:
1)description:对所引用的资源的说明。
2)res-ref-name:指定所引用资源的JNDI名字,与<Resource>元素中的name属性对应。
3)res-type:指定所引用资源的类名,与<Resource>元素中的type属性对应。
4)res-auth:指定管理所引用资源的Manager,与<Resource>元素中的auth属性对应。
4.配置server.xml文件
在tomcat\conf下找到server.xml文件,在<GlobalNamingResources></GlobalNamingResources>之间加入如下内容:
<Resource name="jdbc/test" auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/test?characterEncodering=utf-8"
username="root"
password="root"
maxActive="200"
maxIdle="50"
maxWait="3000"/>
在<Host></Host>之间加入如下内容:
<Context docBase="D:\eclipse-workspace\loginRegister\WebContent"
path="/LoginRegister" reloadable="true" source="org.eclipse.jst.j2ee.server:test">
<ResourceLink global="jdbc/test" name="jdbc/test" type="javax.sql.DataSource"/>
</Context>
<Context>属性说明:
1)docBase:指定Web应用的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性的相对路径。如果Web应用采用开放目录结构,则指定Web应用的根目录;如果Web应用是个WAR文件,则指定WAR文件的路径。
2)path:指定访问该Web应用的URL入口。
3)reloadable:如果这个属性为true,Tomcat服务器会在运行状态下监视classes下文件的改动和WEB-INF/web.xml文件的改动,监测到文件被改动,服务器会自动重新加载Web应用。
4)source:
<ResourceLink>属性说明:
1)global:被连接的连接全局资源的名称。
2)name:创建的资源连接的名称,相对于java:comp/env context。
3)type:当web应用在该资源连接上进行查找时,返回的Java类名的全称。
至此数据库连接池配置完
三、实现访问数据库的DBServlet类
实现代码如下:
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.Context;
import javax.naming.InitialContext;
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.sql.DataSource;
/**
* Servlet implementation class DBServlet
*/
@WebServlet("/DBServlet")
public class DBServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//用于连接数据库的Connection对象
protected Connection conn=null;
protected ResultSet execSQL(String sql,Object... args) throws Exception{
//建立Preparedment对象
PreparedStatement pStmt=conn.prepareStatement(sql);
//为pStmt对象设置SQL参数值
for(int i=0;i<args.length;i++) {
pStmt.setObject(i+1,args[i]); //设置SQL参数值
}
pStmt.execute(); //执行SQL语句
//返回结果集,如果执行的SQL语句不返回结果集,则返回null
return pStmt.getResultSet();
}
//核对用户输入的验证码是否合法
protected boolean checkValidationCode(HttpServletRequest request,
String validationCode) {
//从httpSession中获得系统随机生成的验证码
String validationCodeSession=(String)request.getSession()
.getAttribute("validation_code");
//如果获得的验证码为null,说明验证码过期,用户必须刷新客户端页面,以获得新的验证码
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;
}
/**
* @see HttpServlet#HttpServlet()
*/
public DBServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see Servlet#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
try {
//如果数据库连接正常打开则关闭
if(conn!=null)
conn.close();
}catch(Exception e) {
}
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
try {
//如果conn为null,打开数据库连接
if(conn==null) {
//创建上下文对象ctx
Context ctx=new InitialContext();
//TODO
//获取数据源
DataSource ds=(DataSource)ctx.lookup("java:/comp/env/jdbc/test");
conn=ds.getConnection(); //为Connection对象赋值
}
}catch(Exception e) {
}
}
}
四、实现图形验证码
代码如下:
import java.awt.*;
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.*;
public class ValidationCode extends HttpServlet {
//图形验证码的字符集合,系统将随机从这个字符串中选择一些字符作为验证码
private static String codeChars=
"@#$%^&*123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
//返回一个随机颜色(Color对象)
private static Color getRandomColor(int minColor,int maxColor) {
Random random=new Random();
//保存minColor最大不会超过255
if(minColor>255)
minColor=255;
//保存maxColor最大不会超过255
if(maxColor>255)
maxColor=255;
//获得hong、绿、蓝三种颜色的随机颜色值
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);
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
//获取验证码集合的长度
int charsLength=codeChars.length();
//关闭客户端浏览器的缓冲区
response.setHeader("ragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires",0);
//设置图形验证码的长和宽
int width=90,height=20;
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获得用于输出文字的Graphics对象
Graphics g=image.getGraphics();
Random random=new Random();
g.setColor(getRandomColor(180,250)); //随机设置要填充的颜色
g.fillRect(0,0, width, height); //填充图形背景
//设置初始字体
g.setFont(new Font("Times New Roman",Font.ITALIC,height));
g.setColor(getRandomColor(120,180)); //随机设置字体颜色
//用于保存最后随机生成的验证码
StringBuilder validationCode=new StringBuilder();
//验证码的随机字体
String[] fontNames= {"Times New Roman","Book antiqua","Arial"};
for(int i=0;i<3+random.nextInt(3);i++) { //随机生成3-5个验证码
//随机设置当前验证码的字符的字体
g.setFont(new Font(fontNames[random.nextInt(3)],Font.ITALIC,height));
//随机获得当前验证码的字符
char codeChar=codeChars.charAt(random.nextInt(charsLength));
validationCode.append(codeChar);
//随机设置当前验证码字符的颜色
g.setColor(getRandomColor(10,100));
//在图形上输出验证码字符,x和y都是随机生成的
g.drawString(String.valueOf(codeChar),
16*i+random.nextInt(7),height-random.nextInt(6));
}
//获得HttpSession对象
HttpSession session=request.getSession();
//设置5分钟失效
session.setMaxInactiveInterval(5*60);
//将验证码保存在session对象中
session.setAttribute("validation_code",validationCode.toString());
g.dispose(); //关闭Graphics对象
OutputStream os=response.getOutputStream();
//以jpeg格式向客户端发送图形验证码
ImageIO.write(image,"JPEG",os);
}
}
五、实现注册系统
1.实现注册Servlet类
Register.java代码如下:
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Register extends DBServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
String userName=null;
if(request.getParameter("login")!=null) {
response.sendRedirect("login.jsp");
return;
}try {
super.service(request, response);
userName=request.getParameter("username");
String password=request.getParameter("password");
String email=request.getParameter("email");
String validationCode=request.getParameter("validation_code");
if(userName==null||password==null||validationCode==null)
return;
if(userName.equals("")||password.equals("")||validationCode.equals(""))
return;
userName=new String(userName.getBytes("ISO-8859-1"),"UTF-8");
request.setAttribute("page","register.jsp");
if(!checkValidationCode(request,validationCode))
return;
email=(email==null)?"":email;
String _password=password;
String sql="insert into t_users(user_name,password_md5,email) values(?,?,?)";
execSQL(sql,userName,_password,email);
request.setAttribute("info","用户注册成功!");
}catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
request.setAttribute("info",userName+"已经被使用!");
}finally {
RequestDispatcher rd=request.getRequestDispatcher("result.jsp");
rd.forward(request,response);
}
}
}
2.实现这测系统主界面
register.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function checkRegister(){
var username=document.getElementById("username");
if(username.value==""){
alert("用户名不能为空!");
username.focus();
return;
}
var password=document.getElementById("password");
if(password.value==""){
alert("必须输入密码!");
password.focus();
return;
}
var repassword=document.getElementById("repassword");
if(repassword.value!=password.value){
alert("两次输入的密码不一致!");
repassword.focus();
return;
}
var email=document.getElementById("email");
if(email.value!==""){
if(!checkEmail(email))
return;
}
var validation_code=document.getElementById("validation_code");
if(validation_code.value==""){
alert("验证码b不能为空");
validation_code.focus();
return;
}
register_form.submit();
}
function checkEmail(email){
var email=email.value;
var pattern =/^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
flag=pattern.test(email);
if(!flag){
alert("email格式不正确");
email.focus();
return false;
}
return true;
}
function refresh(){
var img=document.getElementById("img_validation_code")
img.src="validation_code?"+Math.random();
}
</script>
<meta charset="utf-8">
<title>注册页面</title>
</head>
<body>
<form name="register_form" action="register" method="post">
<span class="require">*</span>用户名:
<input type="text" id="username" name="username" size="30" maxLength="30"/><br/>
<span class="require">*</span>密码:
<input type="password" id="password" name="password" size="30" maxLength="30"/><br/>
<span class="require">*</span>请再次输入密码:
<input type="password" id="repassword" name="repassword" size="30" maxLength="30"/><br/>
邮箱地址:
<input type="text" id="email" name="email" size="30" maxLength="30"/><br/>
<span class="require">*</span>验证码:
<input type="text" id="validation_code" name="validation_code"
style="width:60px;margin-top:2px" size="30" maxLength="30"/>
<img id="img_validation_code" src="validation_code"/>
<input type="button" value="刷新" οnclick="refresh()"/><br/>
<input type="button" value="注册" οnclick="checkRegister()"/>
<input type="submit" value="登陆" name="login"/>
</form>
</body>
</html>
3.实现结果jsp页面
result.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib uri="/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>结果页</title>
</head>
<body>
<form name="form" action="${requestScope.page}" method="post"/>
<script type="text/javascript">
<c:if test="${requestScope.info!=null}">
alert('${requestScope.info}');
form.submit();
</c:if>
</script>
</body>
</html>
六、实现登陆系统
1.实现登陆servlet
Login.java代码如下:
import java.io.IOException;
import java.sql.ResultSet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Login extends DBServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
if(request.getParameter("register")!=null) {
response.sendRedirect("register.jsp");
return;
}
String page="login.jsp";
String userName="";
try {
super.service(request, response);
userName=request.getParameter("username");
String password=request.getParameter("password");
String validationCode=request.getParameter("validation_code");
if(userName==null||password==null||validationCode==null)
return;
if(userName.equals("")||password.equals("")||validationCode.equals(""))
return;
userName=new String(userName.getBytes("ISO-8859-1"),"UTF-8");
if(!checkValidationCode(request,validationCode))
return;
String sql="select user_name,password_md5 from t_users where user_name=?";
ResultSet rs=execSQL(sql,new Object[]{userName});
if(rs.next()==false) {
request.setAttribute("userError",userName+"不存在");
}else {
if(!rs.getString("password_md5").equals(password))
request.setAttribute("passwordError","密码不正确");
else page="WEB-INF/main.jsp";
//TODO
}
}catch(Exception e) {
}finally {
request.setAttribute("username",userName);
RequestDispatcher rd=request.getRequestDispatcher(page);
rd.forward(request,response);
}
}
}
在web-inf下创建main.jsp
之所以把main.jsp放到web-inf目录中,是因为这个目录中的文件在客户端浏览器是无法直接访问的,一般需要验证才能访问的页面都应该放在该目录或其子目录中
main.jsp的代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登陆成功</title>
</head>
<body>
登陆成功
</body>
</html>
2.实现登陆系统主界面
login.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登陆页面</title>
<script type="text/javascript">
function checkLogin(){
var username=document.getElementById("username");
if(username.value==""){
alert("用户名不能为空!");
username.focus();
return;
}
var password=document.getElementById("password");
if(password.value==""){
alert("必须输入密码!");
password.focus();
return;
}
var validation_code=document.getElementById("validation_code");
if(validation_code.value==""){
alert("验证码不能为空");
validation_code.focus();
return;
}
login_form.submit();
}
function refresh(){
var img=document.getElementById("img_validation_code")
img.src="validation_code?"+Math.random();
}
</script>
</head>
<body>
<form name="login_form" action="login" method="post">
账号:
<input type="text" id="username" value="${requestScope.username}"
name="username" size="30" maxLength="30"/>
<font color="#FF0000">${requestScope.userError}</font><br/>
密码:
<input type="password" id="password" name="password" size="30"/>
<font color="#FF0000">${requestScope.passwordError}</font><br/>
验证码:
<input type="text" id="validation_code" name="validation_code"
style="width:60ox;margin-top:2px;" size="30" maxLength="30"/>
<font color="#FF0000">${requestScope.codeError}</font>
<img id="img_validation_code" src="validation_code"/>
<input type="button" value="刷新" οnclick="refresh()"/><br/>
<input type="button" value="登陆" name="login" οnclick="checkLogin()"/>
<input type="submit" value="注册" name="register"/>
</form>
</body>
</html>
最后elipse启动tomcat即可运行