【JavaWeb】书城项目之与数据库交互的登录案例实现

2023-10-20 07:48

本文主要是介绍【JavaWeb】书城项目之与数据库交互的登录案例实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

准备工作

项目源代码

链接:https://pan.baidu.com/s/1Uj3Q9swg0Yab2KnY8I9k2g?pwd=1314
提取码:1314

首先更改前端页面中的url路径

请添加图片描述

三层架构

为什么要使用三层架构

所有和当前业务功能需求相关的代码全部耦合在一起,如果其中有任何一个部分出现了问题,牵一发而动全身,导致其他无关代码也要进行相应的修改。这样的话代码会非常难以维护。

所以为了提高开发效率,需要对代码进行模块化的拆分。整个项目模块化、组件化程度越高,越容易管理和维护,出现问题更容易排查。

三层架构的划分
  • 表述层:又可以称之为控制层,负责处理浏览器请求、返回响应、页面调度
  • 业务逻辑层:负责处理业务逻辑,根据业务逻辑把持久化层从数据库查询出来的数据进行运算、组装,封装好后返回给表述层,也可以根据业务功能的需要调用持久化层把数据保存到数据库、修改数据库中的数据、删除数据库中的数据
  • 持久化层:根据上一层的调用对数据库中的数据执行增删改查的操作
三层架构和数据模型的关系

请添加图片描述

模型对整个项目中三层架构的每一层都提供支持,具体体现是使用模型对象封装业务功能数据

其实数据模型就是我们之前学习的JavaBean,也是Java实体类,当然他还有很多其他的名称:

  • POJO:Plain old Java Object,传统的普通的Java对象
  • entity:实体类
  • bean或Java bean
  • domain:领域模型

持久层操作

创建数据库

请添加图片描述

封装工具类

封装JDBCUtils

将druid连接池与jdbc操作封装成工具类

package com.example.WebGo.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;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;static {// 1.创建一个用于存储外部属性文件信息的Properties对象Properties properties = new Properties();// 2.使用当前类的类加载器加载外部属性文件:jdbc.propertiesInputStream inputStream = com.example.WebGo.utils.JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");try {// 3.将外部属性文件jdbc.properties中的数据加载到properties对象中properties.load(inputStream);// 4.创建数据源对象dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}/*** 从数据源中获取数据库连接** @return 数据库连接对象*/public static Connection getConnection() {Connection connection = null;try {connection = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}return connection;}/*** 释放数据库连接** @param connection 要执行释放操作的连接对象*/public static void releaseConnection(Connection connection) {if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}}}
}
配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/WebGo
username=root
password=123456
initialSize=10
maxActive=20
maxWait=10000
封装DButils为Dao基类
import com.example.WebGo.utils.JDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;import java.sql.SQLException;
import java.time.Clock;
import java.util.List;public class BaseDao<T> {private QueryRunner queryRunner= new QueryRunner();public int update(String sql,Object...params){try {int update = queryRunner.update(JDBCUtils.getConnection(), sql, params);return update;} catch (SQLException throwables) {throwables.printStackTrace();throw new RuntimeException();}}public T getBean(Class<T>clasz,String sql,Object...params){try {return queryRunner.query(JDBCUtils.getConnection(), sql, new BeanHandler<>(clasz),params);} catch (SQLException throwables) {throwables.printStackTrace();throw new RuntimeException();}}public List<T> getBeanList(Class<T>clasz, String sql, Object...params){try {return queryRunner.query(JDBCUtils.getConnection(), sql, new BeanListHandler<>(clasz),params);} catch (SQLException throwables) {throwables.printStackTrace();throw new RuntimeException();}}
}
实现用户dao类
package com.example.WebGo.dao.impl;import com.example.WebGo.dao.BaseDao;
import com.example.WebGo.dao.api.Userdao;
import com.example.WebGo.entity.User;import java.sql.SQLException;public class Userdaoimpl extends BaseDao<User> implements Userdao {@Overridepublic User findByUsername(String username) throws SQLException {String sql="select user_id userId,user_name username,user_pwd userPwd,email from t_user where user_name=?";User user = getBean(User.class,sql,username);return user;}@Overridepublic void addUser(User user) throws SQLException {String sql="insert into t_user (user_name,user_pwd,email) values (?,?,?)";update(sql,user.getUserName(),user.getUserPwd(),user.getEmail());}
}
测试

请添加图片描述

请添加图片描述

封装MD5Utils加密工具类

由于下面登录时 我们需要对用户输入的密码信息 进行加密处理,所以在这里实现一个MD5工具类的封装,该代码直接复制粘贴即可,无需过多关注

public class MD5Util {/*** 针对明文字符串执行MD5加密* @param source* @return*/public static String encode(String source) {// 1.判断明文字符串是否有效if (source == null || "".equals(source)) {throw new RuntimeException("用于加密的明文不可为空");}// 2.声明算法名称String algorithm = "md5";// 3.获取MessageDigest对象MessageDigest messageDigest = null;try {messageDigest = MessageDigest.getInstance(algorithm);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}// 4.获取明文字符串对应的字节数组byte[] input = source.getBytes();// 5.执行加密byte[] output = messageDigest.digest(input);// 6.创建BigInteger对象int signum = 1;BigInteger bigInteger = new BigInteger(signum, output);// 7.按照16进制将bigInteger的值转换为字符串int radix = 16;String encoded = bigInteger.toString(radix).toUpperCase();return encoded;}
}

业务逻辑层操作

开发中对业务代码返回值的介绍
  • 方法的返回值应该对应这个方法本身的业务功能

    • 写操作:没有返回值
    • 读操作:有返回值,返回值就是查询的结果
  • 方法执行是否成功

    • 成功:不抛异常
    • 失败:抛异常
    • 最好失败便是抛异常,不要返回布尔类型
登录与注册的业务逻辑处理
public class UserServiceimpl implements UserService {private Userdao userdao= new Userdaoimpl();@Overridepublic void doRegister(User userForm) throws Exception {User user = userdao.findByUsername(userForm.getUserName());if(user!=null){throw new RuntimeException("用户名已存在");}String olduserPwd=userForm.getUserPwd();String encode = MD5Util.encode(olduserPwd);userForm.setUserPwd(encode);userdao.addUser(userForm);}@Overridepublic User doLogin(User parameterUser) throws Exception {//1. 调用dao层的方法根据用户名查询用户信息User loginUser = userdao.findByUsername(parameterUser.getUserName());//2. 判断loginUser是否为空if (loginUser != null) {//说明用户名正确,那么接下来校验密码//parameterUser中的密码是用户输入的密码,我们对其进行MD5加密,完之后跟loginUser中的密码(数据库中的密码)进行比对String encodePwd = MD5Util.encode(parameterUser.getUserPwd());//加密之后的用户输入的密码String dbPwd = loginUser.getUserPwd();//数据库中的密码if (dbPwd.equals(encodePwd)) {//说明密码正确,登录成功,返回loginUser对象return loginUser;}else {//密码错误throw new RuntimeException("密码错误");}}throw new RuntimeException("用户名错误");}
}

表现层(接收请求并响应)

请添加图片描述

public class RigisterServlet extends HttpServlet {UserService userService = new UserServiceimpl();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");Map<String, String[]> map = request.getParameterMap();map.forEach((a,b)->{for(String str:b){ System.out.println(a+"="+b);}});User user = new User();try {BeanUtils.populate(user, map);System.out.println(user);userService.doRegister(user);response.sendRedirect(request.getContextPath() + "/pages/user/regist_success.html");} catch (Exception e) {e.printStackTrace();response.getWriter().write("注册失败!!!" + e.getMessage());}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}
}

请添加图片描述

public class LoginServlet extends HttpServlet {
UserService userService=  new UserServiceimpl();@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");User user = new User();Map<String, String[]> map = request.getParameterMap();try {BeanUtils.populate(user,map);User User = userService.doLogin(user);response.sendRedirect(request.getContextPath()+"/pages/user/Login_success.html");} catch (Exception e) {e.printStackTrace();response.getWriter().write("登陆失败!!!"+e.getMessage());}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);}
}

案例效果

登陆

请添加图片描述

请添加图片描述

用户名检测

请添加图片描述
请添加图片描述

注册

请添加图片描述
请添加图片描述

这篇关于【JavaWeb】书城项目之与数据库交互的登录案例实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/245718

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置