文章目录
1. 在MySQL中创建一个用户表
2. 在IDEA中创建此项目
打开idea–>File–>New->Moudle–>JavaEnterprise–>勾选Web Application–>项目命名为logindemo
3. 对项目进行分层
在src目录下创建如下包,用于分层。
domain:实体类;servlet:控制层;dao:接口层;service:服务层;util:工具层;test:测试层
同时在WEB-INF目录下创建一个lib目录,先复制mysql-connector-java-5.1.6.jar包,并添加为Module jar包,用于连接数据库。
4. 测试数据库是否连接成功
- 在domain 实体层下创建实体类 Users
注意:实体类的名字尽量与数据库中的表名一致,此项目中都名为Users
package com.zz.domain;
import java.io.Serializable;
//实体层:用户表
//Serializable接口是启用其序列化功能的接口
public class Users implements Serializable {
private int id;
private String name;
private String gender;
private String password;
private String email;
private String birthday;
public Users() {
}
public Users(int id, String name, String gender, String password, String email, String birthday) {
this.id = id;
this.name = name;
this.gender = gender;
this.password = password;
this.email = email;
this.birthday = birthday;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Users{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", birthday='" + birthday + '\'' +
'}';
}
}
- 在Util 工具层 下引入一个JDBC工具类,名为DBUtils, DBUtils中封装了对JDBC的操作
package com.zz.util;
import java.io.InputStream;
import java.sql.*;
import java.util.List;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
//DBUtils封装了对JDBC的操作
public class DBUtils {
//访问数据库的小帮手
public static PreparedStatement pstm;
// 数据库连接池封装对象
public static DataSource dataSource;
// 操作属性文件对象
public static Properties properties = new Properties();
//完成类中静态属性初始化,并且多次访问时,只有一次访问才会执行此静态块,而且只执行一次
static {
//让is输入流对象只想src目录下的jdbc.properties
InputStream is = DBUtils.class.getClassLoader().getResourceAsStream(
"jdbc.properties");
try {
//加载属性文件到properties对象中
properties.load(is);
//数据库连接加载配置文件,完成访问数据库的所有配置
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//保证线程安全的数据库访问,一个线程只绑定一个链接对象,多次访问时同一个连接对象
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
//打开数据库连接
public static Connection getConnection() {
Connection conn = tl.get();// 从当前线程上获得链接
try {
if (conn == null || conn.isClosed() ) {
//从连接池中获取连接对象
conn = dataSource.getConnection();
// 把连接绑定到当前线程上
tl.set(conn);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
//关闭所有数据库访问对象
public static void closeAll(Connection con, PreparedStatement pstm,
ResultSet rs) {
try {
if (rs != null)
rs.close();
if (pstm != null)
pstm.close();
if (con != null && !con.isClosed())
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//关闭所有数据库访问对象
public static void closeAll() {
try {
if (pstm != null)
pstm.close();
if (DBUtils.getConnection() != null && !DBUtils.getConnection().isClosed())
DBUtils.getConnection().close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 所有的增删改的方法
public static int myExecuteUpdate(String sql, List list) throws Exception {
//添加第二个参数的意义是为了获得新增记录的主键。
pstm = getConnection().prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
pstm.setObject(i + 1, list.get(i));
}
}
return pstm.executeUpdate();
}
// 所有的查询的方法
public static ResultSet myExecuteQuery(String sql, List list) {
try {
//第二个参数的意思,执行更新语句后可以获得主键
pstm = getConnection().prepareStatement(sql);
if (list != null) {
for (int i = 0; i < list.size(); i++) {
pstm.setObject(i + 1, list.get(i));
}
}
return pstm.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void startTransaction() {
Connection conn = getConnection();
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void commit() {
Connection conn = getConnection();
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback() {
Connection conn = getConnection();
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void release() {
Connection conn = getConnection();
try {
conn.close();
tl.remove();// 与线程池有关,解除关系
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void endTransaction() {
Connection conn = getConnection();
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- 在lib 目录下按照之前的方法导入commons-dbcp2-2.7.0.jar、commons-logging-1.2.jar、commons-pool2-2.7.0.jar三个jar包,同样以模块jar包使用,至此lib目录下,有如下四个jar包
- 在src目录下创建文件 jdbc.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/xbky?useUnicode=true&characterEncoding=UTF-8
username=root
password=123456
initialSize=20
- 在test 测试层创建Test类
在此,先测试连接数据库是否成功
package com.zz.test;
import com.zz.util.DBUtils;
import java.sql.Connection;
public class Test {
public static void main(String[] args) {
Connection conn;
try {
conn = DBUtils.getConnection();
if(conn!=null){
System.out.println("sql连接成功!");
}else{
System.out.println("sql连接失败!");
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
至此,项目包结构如下
运行结果如下,显示连接成功
5. 编写接口、实现登录和注册功能
- 在dao 接口层 编写用户的业务逻辑接口UserDao
有登录、注册以及根据用户编号查询用户的方法
package com.zz.dao;
import com.zz.domain.Users;
//用户的业务逻辑接口
public interface UsersDao {
//用户登录
public Users login(String name, String password);
//用户注册
public Users reg(Users users);
//根据用户编号查询用户
public Users queryUserByid(int id);
}
编写接口的实现类UsersDaoImpl
package com.zz.dao.impl;
import com.zz.dao.UsersDao;
import com.zz.domain.Users;
import com.zz.util.DBUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
//接口UsersDao的实现类,实现接口的所有方法
public class UsersDaoImpl implements UsersDao {
//用户登录
@Override
public Users login(String name, String password) {
Connection conn; // 连接对象
ResultSet rs; //数据集
List args = new ArrayList(); //参数集合
String sql = "select * from users where name=? and password=?"; //?占位符
Users loginUser = null; //用户对象
try {
conn = DBUtils.getConnection();
args.add(name);
args.add(password);
rs = DBUtils.myExecuteQuery(sql, args); //传进去返回一个数据集
if (rs.next()) { //如果有下条记录就说明就登录成功了。用户资料返回
loginUser = new Users();
loginUser.setId(rs.getInt("id"));
loginUser.setName(rs.getString("name"));
loginUser.setPassword(rs.getString("password"));
loginUser.setGender(rs.getString("gender"));
loginUser.setEmail(rs.getString("email"));
loginUser.setBirthday(rs.getString("birthday"));
}
return loginUser;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
@Override
public Users reg(Users users) {
Connection conn; //连接对象
List args = new ArrayList();
String sql = "insert into users (name,password,gender,email,birthday) values (?,?,?,?,?)";
Users regUser = null;
int result;
try {
conn = DBUtils.getConnection();
DBUtils.startTransaction();//开启事务
args.add(users.getName());
args.add(users.getPassword());
args.add(users.getGender());
args.add(users.getEmail());
args.add(users.getBirthday());
result = DBUtils.myExecuteUpdate(sql, args);
if (result > 0) { //说明注册成功了。用户资料返回
//获得新生成的用户的编号。
//问题的焦点是你如何获得新添加用户的主键呢?
ResultSet temp = DBUtils.pstm.getGeneratedKeys();
temp.next();
int id = temp.getInt(1);
regUser = queryUserByid(id);
}
DBUtils.commit(); //提交事务
DBUtils.endTransaction();
return regUser;
} catch (Exception ex) {
ex.printStackTrace();
DBUtils.rollback(); //回滚
DBUtils.endTransaction(); //关闭事务
return null;
}
}
@Override
public Users queryUserByid(int id) {
Connection conn; //连接对象
ResultSet rs; //数据集
List args = new ArrayList();
String sql = "select * from users where id=?";
Users user = null;
try{
conn = DBUtils.getConnection();
args.add(id);
rs = DBUtils.myExecuteQuery(sql,args);
if(rs.next()){ //说明就登录成功了。用户资料返回
user = new Users();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
user.setGender(rs.getString("gender"));
user.setEmail(rs.getString("email"));
user.setBirthday(rs.getString("birthday"));
}
return user;
}catch(Exception ex){
ex.printStackTrace();
return null;
}
}
}
- 在测试层 编写测试类Test
测试用户的登录效果,和注册效果
package com.zz.test;
import com.zz.dao.UsersDao;
import com.zz.dao.impl.UsersDaoImpl;
import com.zz.domain.Users;
import com.zz.util.DBUtils;
import java.sql.Connection;
public class Test {
public static void main(String[] args) {
/* Connection conn;
try {
conn = DBUtils.getConnection();
if(conn!=null){
System.out.println("sql连接成功!");
}else{
System.out.println("sql连接失败!");
}
}catch (Exception ex){
ex.printStackTrace();
}*/
//测试用户登录的效果。
Users loginUser = null;
UsersDao usersDao = new UsersDaoImpl();
loginUser = usersDao.login("张某","123456");
if(loginUser!=null){
System.out.println("登录成功!");
}else{
System.out.println("登录失败!");
}
/*
// 测试用户注册的效果
Users regUser = new Users();
regUser.setName("王某");
regUser.setGender("男");
regUser.setPassword("654321");
regUser.setEmail("[email protected]");
regUser.setBirthday("1998-11-10");
UsersDao usersDao = new UsersDaoImpl();
regUser = usersDao.req(regUser);
System.out.println(regUser);
*/
}
}
6. 编写service层
跟dao层类似
- 编写接口UsersService
package com.zz.service;
import com.zz.domain.Users;
public interface UsersService {
//用户登录
public Users login(String name, String password);
//用户注册
public Users reg(Users users);
//根据用户编号查询用户
public Users queryUserByid(int id);
}
- 编写接口的实现类 UsersServiceImpl
package com.zz.service.impl;
import com.zz.dao.UsersDao;
import com.zz.dao.impl.UsersDaoImpl;
import com.zz.domain.Users;
import com.zz.service.UsersService;
public class UsersServieImpl implements UsersService {
private UsersDao usersDao = new UsersDaoImpl();
@Override
public Users login(String username, String password) {
return usersDao.login(username,password);
}
@Override
public Users reg(Users users) {
return usersDao.reg(users);
}
@Override
public Users queryUserByid(int id) {
return usersDao.queryUserByid(id);
}
}
7. 编写servlet层
package com.zz.servlet;
import com.zz.domain.Users;
import com.zz.service.UsersService;
import com.zz.service.impl.UsersServieImpl;
import com.zz.service.impl.UsersServieImpl;
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;
@WebServlet(name = "UsersServlet",value="UsersServlet")
public class UsersServlet extends HttpServlet {
private String action ;
private UsersService usersService = new UsersServieImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(request.getParameter("action")!=null){
this.action = request.getParameter("action");
switch(this.action){
case "login":
login(request,response);
break;
case "reg":
reg(request,response);
break;
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
//执行登录动作
private void login(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
Users loginUser = null;
loginUser = usersService.login(request.getParameter("name"),request.getParameter("password"));
if(loginUser!=null){
System.out.println("登录成功!");
//把登录成功的用户保存到session中
request.getSession().setAttribute("loginUser",loginUser);
response.sendRedirect(request.getContextPath()+"/main.jsp");
}else{
System.out.println("登录失败!");
response.sendRedirect(request.getContextPath()+"/login_failure.jsp");
}
}
//执行注册
private void reg(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
Users user = new Users();
user.setName(request.getParameter("name"));
user.setPassword(request.getParameter("password"));
user.setGender(request.getParameter("gender"));
user.setEmail(request.getParameter("email"));
user.setBirthday(request.getParameter("birthday"));
Users regUser = null;
regUser = usersService.reg(user);
if(regUser!=null){
System.out.println("注册成功!");
System.out.println(regUser);
//页面跳转到登录页面。
response.sendRedirect(request.getContextPath()+"/login.jsp");
}else{
System.out.println("注册失败!");
}
}
}
8. 编写filter过滤器
添加一个过滤器,防止中文乱码
package com.zz.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
//规定,乌龟的屁股规定。
@WebFilter(description = "EncodingFilter",value="/*",initParams ={@WebInitParam(name="encoding",value="utf-8")}) // 凡是过滤器一般都是 /* ,过滤所有的请求
public class EncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding = filterConfig.getInitParameter("encoding");
}
//过滤器过滤的是请求,什么样的请求呢?各种各样请求,只有是请求,就被过滤以下。能理解吗?
//过滤器在过滤器请求的时候,一定会执行doFilter这个方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//请求使用utf-8
servletRequest.setCharacterEncoding(this.encoding);
//响应也使用utf-8
servletResponse.setCharacterEncoding(this.encoding);
//不会有中文乱码
filterChain.doFilter(servletRequest,servletResponse); //千万不要忘了写,过滤器链条,继续向后过滤
}
@Override
public void destroy() {
}
}
9. 编写JSP页面
登录页面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录</title>
<style>
#regDiv {
/*div水平居中*/
margin: 0px auto;
width: 400px;
height: 70px;
border: 1px solid #ccc;
padding: 10px;
}
h1 {
text-align: center;
}
input {
width: 280px;
}
.label {
width: 30%;
}
.controller {
width: 70%;
}
table {
border-collapse: collapse;
border-spacing: 0px 0px;
height: auto;
}
</style>
</head>
<body>
<h1>用户登录</h1>
<div id="regDiv">
<form action="${pageContext.request.contextPath}/UsersServlet?action=login" method="post">
<table>
<tr>
<td class="label">用户名:</td>
<td class="controller"><input type="text" name="name"></td>
</tr>
<tr>
<td class="label">密码:</td>
<td class="controller"><input type="password" name="password"></td>
</tr>
<tr>
<%--colspan=“2”是指将2列合并,合并之后要把合并的那个单元格删除掉,才能体现出效果
text-align指这个div块内的文本居中--%>
<td colspan="2" style="text-align: center">
<input type="submit" style="width:60px" value="登录">
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
注册页面 reg.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户注册</title>
<style>
#regDiv {
/*div水平居中*/
margin: 0px auto;
width: 400px;
height: 160px;
border: 1px solid #ccc;
padding: 10px;
}
h1 {
text-align: center;
}
input {
width: 280px;
}
.label {
width: 30%;
}
.controller {
width: 70%;
}
table {
border-collapse: collapse;
border-spacing: 0px 0px;
height: auto;
}
</style>
</head>
<body>
<h1>用户注册</h1>
<div id="regDiv">
<form action="${pageContext.request.contextPath}/UsersServlet?action=reg" method="post">
<table>
<tr>
<td class="label">用户名:</td>
<td class="controller"><input type="text" name="name"></td>
</tr>
<tr>
<td class="label">密码:</td>
<td class="controller"><input type="password" name="password"></td>
</tr>
<tr>
<td class="label">确认密码:</td>
<td class="controller"><input type="password" name="confirmpass"></td>
</tr>
<tr>
<td class="label">性别:</td>
<td class="controller">
<input type="radio" style="width:20px" name="gender" value="男" checked/>男
<input type="radio" style="width:20px" name="gender" value="女" />女
</td>
</tr>
<tr>
<td class="label">电子邮箱:</td>
<td class="controller"><input type="text" name="email" value=""/></td>
</tr>
<tr>
<td class="label">出生日期:</td>
<td class="controller"><input type="date" name="birthday" value=""/></td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<input type="submit" style="width:60px" value="注册">
</td>
</tr>
</table>
</form>
</div>
</body>
</html>
主页面 main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<h1>系统主页面</h1>
<hr>
<div id="main">
欢迎您:${sessionScope.loginUser.name}<br>
</div>
</body>
</html>
登录失败页面 login_failure.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录失败</h1>
<hr>
<a href="login.jsp">返回</a>
</body>
</html>
10. 系统测试
测试用户注册:
进入用户注册页面,进行用户注册,注册成功后跳转到用户登录页面,刷新数据库中Users表可查看,添加了刚注册的用户
测试用户登录:
进入用户登录页面,进行用户登录,注册成功后跳转到系统主页面