👉引言💎
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。 热爱写作,愿意让自己成为更好的人............
铭记于心 | ||
🎉✨🎉我唯一知道的,便是我一无所知🎉✨🎉 |
准备工作
项目源代码
提取码: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.properties InputStream 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 { @Override public 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; } @Override public 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(); @Override public 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); } @Override public 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(); @Override protected 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()); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
public class LoginServlet extends HttpServlet { UserService userService= new UserServiceimpl(); @Override protected 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()); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } 复制代码
案例效果
登陆
用户名检测
注册
🌹写在最后💖: 路漫漫其修远兮,吾将上下而求索!伙伴们,再见!🌹🌹🌹