Java Web实战:利用三层架构与Servlet构建登录注册模块
前言导读
三层架构:View(视图层)Service(业务层)DAO(持久层)
- 使用了JDBCtemplate技术,封装了原生的JDBC技术操作MySQL数据库(DAO层)
- 实现了登录功能和注册功能(Service层)
- 使用Servlet操作前端表单提供的数据,进行登录和注册,以及完成页面跳转的需求实现(View层)
第一步:创建JavaWeb项目,在pom.xml中配置相关依赖
pom.xml
不要把我的项目名也一起复制了,只复制依赖<dependency>和插件部分<build>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>maven_9_11</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>maven_9_11 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--MySQL数据库连接驱动jar包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- servlet依赖支持-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--JDBCTemplate依赖支持,因为JDBCTemplate是Spring框架封装的一个工具类,因此需要导入Spring相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
</dependencies>
<build>
<!--配置项目名 -->
<finalName>web</finalName>
<plugins>
<!--配置jetty服务器插件支持-->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.14.v20161028</version>
</plugin>
<!--配置tomcat服务器插件支持-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8080</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin>
</plugins>
</build>
</project>
第二步:创建数据库表和实体类并导入JDBCTemplate工具类
数据库表t_user:
这里不介绍如何创建这样的一个数据库了(保证user_id为主键即可)
User实体类:
package com.csx.entity;
import java.io.Serializable;
public class User implements Serializable {
private Integer userId;
private String userName;
private String password;
public User(){}
public User(Integer userId, String userName, String password) {
this.userId = userId;
this.userName = userName;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
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;
}
}
工具类:
package com.csx.util;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtils {
private static DataSource dataSource =null;
static{
try (
InputStream is=JDBCUtils.class.getResourceAsStream("/JDBCUtils.properties")
){
Properties p = new Properties();
p.load(is);
dataSource = new DriverManagerDataSource(p.getProperty("url"), p.getProperty("username"), p.getProperty("password"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static JdbcTemplate getJDBCTemplate(){
//创建JDBCTemplate对象并传入数据库连接池
JdbcTemplate template = new JdbcTemplate(dataSource);
return template;
}
/**
* 获取数据库连接池
* @return
*/
public static DataSource getDataSource(){
return dataSource;
}
/**
* 开始线程绑定 +获取连接
* @return
*/
public static Connection startTransaction(){
if (!TransactionSynchronizationManager.isSynchronizationActive()){
TransactionSynchronizationManager.initSynchronization();
}
Connection connection =DataSourceUtils.getConnection(dataSource);
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return connection;
}
/**
* 提交事务
* @param conn
*/
public static void commit(Connection conn){
try {
conn.commit();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
clear(conn);
}
}
/**
* 回滚事务
* @param conn
*/
public static void rollback(Connection conn){
try {
conn.rollback();
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
clear(conn);
}
}
/**
* 解除线程绑定+释放资源+归还连接到线程池
* @param conn
*/
public static void clear(Connection conn){
//清除线程绑定的资源
TransactionSynchronizationManager.clear();
TransactionSynchronizationManager.unbindResourceIfPossible(dataSource);
//归还数据库连接至连接池
if (conn!=null){//非空判断,判断为空再归还
DataSourceUtils.releaseConnection(conn,dataSource);
}
}
}
在resources资源目录下创建JDBCUtils.properties目录
JDBCUtils.properties
url=jdbc:mysql://localhost:3306/csx_demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeZone=Asia/shanghai
username=root
password=root
第三步:创建DAO层,书写SQL支持
UserDao接口:
package com.csx.dao;
import com.csx.entity.User;
public interface UserDao {
/**
* 根据用户名和密码指定用户是否存在
* @param userName
* @return
*/
public User selectUserByUserName(String userName,String password);
/**
* 新增用户信息
* @param user
* @return
*/
public int insertUser(User user);
}
UserDaoImpl实现类:
package com.csx.dao.impl;
import com.csx.dao.UserDao;
import com.csx.entity.User;
import com.csx.service.UserService;
import com.csx.util.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
public class UserDaoImpl implements UserDao {
private JdbcTemplate template = JDBCUtils.getJDBCTemplate();
/**
* 根据用户名和密码指定用户是否存在
*
* @param userName
* @param password
* @return
*/
@Override
public User selectUserByUserName(String userName, String password) {
String sql="select * from t_user where user_name=? and password=? ";
List<User> list = template.query(sql, new BeanPropertyRowMapper<>(User.class), userName, password);
return list.isEmpty()?null:list.get(0);
}
/**
* 新增用户信息
*
* @param user
* @return
*/
@Override
public int insertUser(User user) {
String sql="insert into t_user(user_name,password) values(?,?)";
return template.update(sql, user.getUserName(), user.getPassword());
}
}
第四步:创建Service层,书写登录和注册逻辑
UserService接口:
package com.csx.service;
public interface UserService {
/**
* 用户登录功能
* @param username
* @param password
* @return
*/
public boolean login(String username,String password);
/**
* 用户注册功能
* @return
*/
public boolean register(String username,String password);
}
UserServiceImpl实现类:
package com.csx.service.impl;
import com.csx.dao.UserDao;
import com.csx.dao.impl.UserDaoImpl;
import com.csx.entity.User;
import com.csx.service.UserService;
import com.csx.util.JDBCUtils;
import java.sql.Connection;
public class UserServiceImpl implements UserService {
private UserDao userDao =new UserDaoImpl();
/**
* 用户登录功能
*
* @param username
* @param password
* @return
*/
@Override
public boolean login(String username, String password) {
boolean boo =false;
Connection conn =null;
try{
conn= JDBCUtils.startTransaction();
//业务功能
User user = userDao.selectUserByUserName(username,password);
//判断用户名是否存在
if (user!=null){
//判断密码是否正确
if (user.getPassword().equals(password)){
boo=true;
}else {
throw new RuntimeException("密码错误!");
}
}else {
throw new RuntimeException("用户不存在!");
}
JDBCUtils.commit(conn);
}catch (Exception e){
JDBCUtils.rollback(conn);
throw new RuntimeException(e);
}
return boo;
}
/**
* 用户注册功能
*
* @param username
* @param password
* @return
*/
@Override
public boolean register(String username, String password) {
boolean boo=false;
Connection conn=null;
try {
conn = JDBCUtils.startTransaction();
//业务功能
User u = userDao.selectUserByUserName(username,password);
if (u == null) {
User user = new User(null, username, password);
userDao.insertUser(user);
boo = true;
} else {
throw new RuntimeException("用户名重复,注册失败!");
}
JDBCUtils.commit(conn);
}catch (Exception e){
JDBCUtils.rollback(conn);
throw new RuntimeException(e);
}
return boo;
}
}
第五步:书写Servlet接收页面传入的数据,并响应
LoginServlet:
package com.csx.servlet;
import com.csx.service.UserService;
import com.csx.service.impl.UserServiceImpl;
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;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private UserService userService =new UserServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("username");
String pwd =request.getParameter("password");
try {
boolean login = userService.login(name, pwd);
if (login){
System.out.println("登录成功!");
response.sendRedirect("login_success.html");
}else {
}
} catch (Exception e) {
System.out.println("登录失败");
response.sendRedirect("login_failed.html");
}
}
}
RegisterServlet:
package com.csx.servlet;
import com.csx.service.UserService;
import com.csx.service.impl.UserServiceImpl;
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("/register")
public class RegisterServlet extends HttpServlet {
private UserService userService =new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("username");
String pwd =request.getParameter("password");
try {
boolean login = userService.register(name, pwd);
if (login){
System.out.println("注册成功!");
// response.sendRedirect("register_success.html");
response.sendRedirect("register_success.html");
}
} catch (Exception e) {
System.out.println("注册失败!");
response.sendRedirect("register_failed.html");
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
}
web.xml配置
创建一个JavaWeb项目,想要使用注解@WebServlet来配置Servlet路径映射,需要将webapp目录下的WBE-INF目录下的web.xml中配置3.0 以上的配置头,例如:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> </web-app>
第六步:在webapp目录下创建HTML页面
login.html:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Form</title>
<style>
/* 简单的样式来美化表单 */
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.login-form {
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.login-form h2 {
margin-bottom: 20px;
}
.login-form input[type="text"],
.login-form input[type="password"] {
width: calc(100% - 22px);
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.login-form input[type="submit"] {
background-color: #ff0000;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.login-form input[type="submit"]:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="login-form">
<h2>Login</h2>
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<input type="submit" value="Login">
</form>
</div>
</body>
</html>
login_success.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录成功!</h1>
</body>
<script>alert('登录成功!')</script>
</html>
login_failed:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录失败</h1>
</body>
<script>
alert('登录失败')
</script>
</html>
register.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registration Form</title>
<style>
/* 简单的样式来美化表单 */
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.registration-form {
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.registration-form h2 {
margin-bottom: 20px;
}
.registration-form input[type="text"],
.registration-form input[type="password"] {
width: calc(100% - 22px);
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.registration-form input[type="submit"] {
background-color: #28a745;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.registration-form input[type="submit"]:hover {
background-color: #218838;
}
</style>
</head>
<body>
<div class="registration-form">
<h2>Registration</h2>
<form action="/register" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<input type="submit" value="Register">
</form>
</div>
</body>
</html>
register_success:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login Form</title>
<style>
/* 简单的样式来美化表单 */
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.login-form {
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.login-form h2 {
margin-bottom: 20px;
}
.login-form input[type="text"],
.login-form input[type="password"] {
width: calc(100% - 22px);
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.login-form input[type="submit"] {
background-color: #ff0000;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.login-form input[type="submit"]:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="login-form">
<h2>Login</h2>
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<input type="submit" value="Login">
</form>
</div>
</body>
<script>
alert(' 注册成功,请登录!');
</script>
</html>
register_failed:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registration Form</title>
<style>
/* 简单的样式来美化表单 */
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.registration-form {
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.registration-form h2 {
margin-bottom: 20px;
}
.registration-form input[type="text"],
.registration-form input[type="password"] {
width: calc(100% - 22px);
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.registration-form input[type="submit"] {
background-color: #28a745;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.registration-form input[type="submit"]:hover {
background-color: #218838;
}
</style>
</head>
<body>
<div class="registration-form">
<h2>Registration</h2>
<form action="/register" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<input type="submit" value="Register">
</form>
</div>
</body>
<script>
alert("注册失败!")
</script>
</html>
第七步:项目启动与测试
项目启动,参考我的这篇博客:JavaWeb项目启动
运行测试
登录
登录失败
登录成功
注册
注册成功
注册成功会直接跳转到登录页面
注册失败
注册失败,弹出警告框,并且返回注册页面
总结
整体结构图
忽略我没有在博客书写的类和html页面,它们是我自己测试时使用的,不影响整体功能执行
基于三层架构和Servlet进行登录和注册功能的实现项目