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;}@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req,resp);}@Overrideprotected 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();@Overrideprotected 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");}}@Overrideprotected 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/javaeehttp://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进行登录和注册功能的实现项目