实现注册登录:Tomcat+Servlet+JDBC+DAO三层架构+动态代理设计模式+注解log
0. 需求图和流程图
功能需求图:
整体框架图:
键来!~
1. 实体类 Entity
package com.demo.entity;
public class Userinfo {
private String username;
private String password;
public Userinfo() {
}
public Userinfo(String username, String password) {
this.username = username;
this.password = password;
}
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;
}
@Override
public String toString() {
return "Userinfo{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
2. 封装数据层 Dao
2.0 数据库连接池:配置文件 + 连接工具类
# 数据库配置
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/companydb?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
# 初始化连接数
initialSize=10
# 最大连接数
maxActive=50
# 最小空闲连接数
minIdle=5
# 超时等待时间,单位:毫秒ms
maxWait=5000
package com.demo.utils;
public class DBUtils {
private static DruidDataSource druidDataSource = null;
private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>();
static {
Properties ppts = new Properties();
InputStream is = DBUtils.class.getClassLoader().getResourceAsStream("database.properties");
try {
ppts.load(is);
druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(ppts);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DruidDataSource getDruidDataSource() {
return druidDataSource;
}
private static Connection getConnection() {
Connection connection = THREAD_LOCAL.get();
try {
if (null == connection) {
connection = getDruidDataSource().getConnection();
THREAD_LOCAL.set(connection);
}
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void begin() {
try {
getConnection().setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void commit() {
try {
getConnection().commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback() {
try {
getConnection().rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void release(Connection connection, Statement statement, ResultSet resultSet) {
try {
if (null != resultSet) {
resultSet.close();
}
if (null != statement) {
statement.close();
}
if (null != connection) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2.1 接口 UserinfoDao
package com.demo.dao;
public interface UserinfoDao {
int insert(Userinfo userinfo);
Userinfo delete(int id);
int update(Userinfo userinfo);
Userinfo search(int id);
Userinfo search(String username);
}
2.2 实现类 UserifoDaoImpl
package com.demo.dao.impl;
public class UserinfoDaoImpl implements UserinfoDao {
private QueryRunner queryRunner = new QueryRunner(DBUtils.getDruidDataSource());
@Override
public int insert(Userinfo userinfo) {
String sql = "insert into userinfo(username, password) value(?,?)";
Object[] params = {userinfo.getUsername(), userinfo.getPassword()};
try {
return queryRunner.update(sql, params);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public Userinfo delete(int id) {
String sql = "delete from userinfo where id=?";
try {
return queryRunner.update(sql, id) > 0 ? search(id) : null;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
@Override
public int update(Userinfo userinfo) {
String sql = "update userinfo set username=?,password=? where id=?";
Object[] params = {userinfo.getUsername(), userinfo.getPassword()};
try {
return queryRunner.update(sql, params);
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
@Override
public Userinfo search(int id) {
return doSearch("id", id);
}
@Override
public Userinfo search(String username) {
return doSearch("username", username);
}
private Userinfo doSearch(String param, Object value) {
String sql = "select * from userinfo where " + param + "=?";
try {
return queryRunner.query(sql, new BeanHandler<>(Userinfo.class), value);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
3. 业务逻辑层 Service
3.0 日志管理:注解 + 动态代理 + 日期工具类
package com.demo.anno;
@Retention(RetentionPolicy.RUNTIME)
public @interface SysLog {
}
package com.demo.utils;
public class DateUtils {
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
public static String utilToStrDate(java.util.Date date) {
return SIMPLE_DATE_FORMAT.format(date);
}
public static java.util.Date strToUtilDate(String date) {
try {
return SIMPLE_DATE_FORMAT.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public static java.sql.Date utilToSqlDate(java.util.Date date) {
return new java.sql.Date(date.getTime());
}
}
package com.demo.service.proxy;
public class UserinfoServiceProxy {
private UserinfoService userinfoService;
public UserinfoServiceProxy(UserinfoService userinfoService) {
this.userinfoService = userinfoService;
}
public UserinfoService getDynamicProxyInstance() {
return (UserinfoService) Proxy.newProxyInstance(
userinfoService.getClass().getClassLoader(),
userinfoService.getClass().getInterfaces(),
(proxy, method, args) -> {
Object result;
boolean present = method.isAnnotationPresent(SysLog.class);
if (present) {
String strDate = DateUtils.utilToStrDate(new Date());
String className = userinfoService.getClass().getName();
String methodName = method.getName();
System.out.print("[" + strDate + "]|" + className + "|" + methodName + "(");
for (Object param : args) {
System.out.print(param + ",");
}
System.out.println(")");
result = method.invoke(userinfoService, args);
System.out.println("[" + strDate + "]|" + className + "|" + methodName + "() return:" + result);
} else {
result = method.invoke(userinfoService, args);
}
return result;
});
}
}
3.1 接口 UserinfoService
package com.demo.service;
public interface UserinfoService {
@SysLog
int add(String username, String password);
@SysLog
Userinfo del(int id);
@SysLog
int change(Userinfo userinfo);
@SysLog
Userinfo get(int id);
@SysLog
boolean login(String username, String password);
}
3.2 实现类 UserinfoServiceImpl
package com.demo.service.impl;
public class UserinfoServiceImpl implements UserinfoService {
private UserinfoDao userinfoDao = new UserinfoDaoImpl();
@Override
public int add(String username, String password) {
DBUtils.begin();
if (userinfoDao.search(username) != null) {
System.out.println("用户名重复,请重试!");
return -1;
}
int result = userinfoDao.insert(new Userinfo(username, password));
if (result > 0) {
DBUtils.commit();
} else {
DBUtils.rollback();
}
return result;
}
@Override
public Userinfo del(int id) {
DBUtils.begin();
Userinfo userinfo = userinfoDao.delete(id);
if (null != userinfo) {
DBUtils.commit();
} else {
DBUtils.rollback();
}
return userinfo;
}
@Override
public int change(Userinfo userinfo) {
DBUtils.begin();
int result = userinfoDao.update(userinfo);
if (result > 0) {
DBUtils.commit();
} else {
DBUtils.rollback();
}
return result;
}
@Override
public Userinfo get(int id) {
DBUtils.begin();
Userinfo userinfo = userinfoDao.search(id);
if (null != userinfo) {
DBUtils.commit();
} else {
DBUtils.rollback();
}
return userinfo;
}
@Override
public boolean login(String username, String password) {
DBUtils.begin();
Userinfo userSearch = userinfoDao.search(username);
if (null != userSearch) {
return password.equals(userSearch.getPassword());
}
return false;
}
}
4. 请求和响应处理 Servlet
4.1 注册 register
package com.demo.servlet;
@WebServlet(name = "RegisterServlet", urlPatterns = "/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
if (username == null || password == null ||
username.trim().length() == 0 || password.trim().length() == 0) {
regFailed("账号/密码不能为空", response);
return;
}
UserinfoServiceProxy userinfoServiceProxy = new UserinfoServiceProxy(new UserinfoServiceImpl());
UserinfoService proxyInstance = userinfoServiceProxy.getDynamicProxyInstance();
int addResult = proxyInstance.add(username, password);
if (addResult > 0) {
response.sendRedirect("/demo55/login/login.html");
} else {
regFailed("账号已存在", response);
}
}
private void regFailed(String errInfo, HttpServletResponse response) throws IOException {
response.getWriter().println(errInfo + ",注册失败!");
response.setHeader("refresh", "3;url=/demo55/register/register.html");
}
}
4.2 登录 login
package com.demo.servlet;
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
if (username == null || password == null ||
username.trim().length() == 0 || password.trim().length() == 0) {
loginFailed("账号/密码不能为空", response);
return;
}
UserinfoServiceProxy userinfoServiceProxy = new UserinfoServiceProxy(new UserinfoServiceImpl());
UserinfoService proxyInstance = userinfoServiceProxy.getDynamicProxyInstance();
if (proxyInstance.login(username, password)) {
request.setAttribute("userName", username);
request.getRequestDispatcher("/user").forward(request, response);
} else {
loginFailed("账号/密码有误", response);
}
}
private void loginFailed(String errInfo, HttpServletResponse response) throws IOException {
response.getWriter().println(errInfo + ",登陆失败!");
response.setHeader("refresh", "3;url=/demo55/login/login.html");
}
}
4.3 用户中心 user
package com.demo.servlet;
@WebServlet(name = "UserServlet", urlPatterns = "/user")
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String uName = (String) request.getAttribute("userName");
if (null != uName) {
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<head>");
writer.println("<meat charset='utf-8'>");
writer.println("</head>");
writer.println("<body>");
writer.println("<font color=\"red\">" + uName + "</font>,欢迎回来!");
writer.println("</body>");
writer.println("</html>");
}
}
}
5. 表示层页面 WebPage
5.1 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册和登陆</title>
</head>
<body>
<h2>请选择需要的功能:</h2>
<a href="register/register.html"><input type="button" value="注册" /></a>
<a href="login/login.html"><input type="button" value="登陆" /></a>
</body>
</html>
5.2 register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
</head>
<body>
<h2>注册:</h2>
<form action="/demo55/register" method="post">
<table>
<tr>
<td>账号:</td>
<td>
<label>
<input type="text" name="username" placeholder="请输入用户名"/>
</label>
</td>
</tr>
<tr>
<td>密码:</td>
<td>
<label>
<input type="password" name="password" placeholder="请输入密码"/>
</label>
</td>
</tr>
</table>
<input type="submit" value="注册"/>
<input type="reset" value="重置"/>
</form>
</body>
</html>
5.3 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆页面</title>
</head>
<body>
<h2>登陆:</h2>
<form action="/demo55/login" method="post">
<table>
<tr>
<td>账号:</td>
<td>
<label>
<input type="text" name="username" placeholder="请输入用户名"/>
</label>
</td>
</tr>
<tr>
<td>密码:</td>
<td>
<label>
<input type="password" name="password" placeholder="请输入密码"/>
</label>
</td>
</tr>
</table>
<input type="submit" value="登陆"/>
</form>
</body>
</html>
6. 运行结果示例图
6.1 日志记录
6.2 页面操作