MVC架构-01

打印 上一主题 下一主题

主题 937|帖子 937|积分 2811

MVC

本文为动力节点老杜web课程mvc部分笔记,以银行转账项目为例
不使用MVC框架(分析存在的问题

1.搞个数据库
  1. CREATE TABLE `t_act` (
  2.   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自然主键,与业务无关,自增',
  3.   `actno` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '账号',
  4.   `balance` decimal(10,2) DEFAULT NULL COMMENT '余额',
  5.   PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
复制代码
2.创建项目bank(不使用maven,手动配置

2.1基本流程


  • 创建空project                (无需序号 1. 空格)
  • moudle
  • 手动添加Framwork支持
  • project structure
  • 在dependency目录下添加相关jar包,切不可添加在source目录下(没用)


  • 添加tomcat服务器
  • 。。。
2.2遇到的问题 Servlet包找不到(低级错误


  • 原因
    上述jar包添加过程有误
  • 措施
    1.以为jdk17与tomcat9不适配,换成10仍不适配
    2.在web  WEB-INF中创建lib目录,将servlet-api.jar拷过去,仍不管用

2.3 jsp文档写一个简单页面(EL表达式不熟练
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3.   <head>
  4.     <base href="${pageContext.request.scheme}://${pageContext.request.serverPort}${pageContext.request.contextPath}/">
  5.     <title>银行账户转账</title>
  6.   </head>
  7.   <body>
  8.   <form action="transfer" method="post">
  9.     转出账户:<input type="text" name="fromActno"><br>
  10.     转入账户:<input type="text" name="toActno"><br>
  11.     转账金额:<input type="text" name="money"><br>
  12.     <input type="submit" name="转账">
  13.   </form>
  14.   </body>
  15. </html>
复制代码

2.4servlet类实现转账功能


  • 别忘了加注解 @WebServlet("/transfer")
  • 从前端获取用户输入的转账信息
  1. String fromActno = request.getParameter("fromActno");
  2. String toActno = request.getParameter("toActno");
  3. double money = Double.parseDouble(request.getParameter("money"));
复制代码

  • 编写转账业务逻辑代码,连接数据库,进行转账操作(JDBC那一套)

    ​        注意3:开启事务,事务手动提交与事务回滚-------------------------------------------------
    ​                        jdbc会自动提交,开启事务,不让他自动提交
    ​        注意2:在web WEB-INF中添加mysql连接jar包

​        注意1: 转账之前判断余额是否充足,不足则异常,(创建一个异常类)
  1. //余额不足异常类
  2. public class MoneyNotEnoughException extends Exception {
  3.     //构造方法
  4.     public MoneyNotEnoughException() {
  5.     }
  6.     public MoneyNotEnoughException(String msg) {
  7.         super(msg);
  8.     }
  9. }
复制代码
  1. Connection conn = null;
  2. PreparedStatement ps = null;
  3. ResultSet rs = null;
  4. PreparedStatement ps2 = null;        //有了新的sql语句
  5. PreparedStatement ps3 = null;
  6. try {
  7.     //注册驱动
  8.     Class.forName("com.mysql.cj.jdbc.Driver");
  9.     //获取连接
  10.     String url = "jdbc:mysql://localhost:3306/mvc";
  11.     String user = "root";
  12.     String password = "123456";
  13.     conn = DriverManager.getConnection(url,user,password);
  14.    
  15.     //注意3
  16.     //开启事务
  17.    
  18.     //获取预编译的sql对象
  19.     String sql = "select id,balance from t_act where actno = ? ";
  20.     ps = conn.prepareStatement(sql);
  21.     ps.setString(1,fromActno);
  22.     //执行sql语句,返回结果集
  23.     rs = ps.executeQuery();
  24.    
  25.     //拿到结果集后处理结果集
  26.     //因为只有一条结果,if即可
  27.     if (rs.next()){
  28.         //取出余额
  29.         double balance = rs.getDouble("balance");
  30.         if (balance < 0){
  31.             //余额不足
  32.             throw new MoneyNotEnoughException("余额不足");
  33.         }
  34.         //程序走到这里已经说明余额充足,不必加else,因为if中如不足则exception
  35.         
  36.         
  37.         //下面转账,实现功能
  38.         //act01 - 10000
  39.         //act02 + 10000
  40.         String sql2 = "update t_act set balance = balance - ? where actno = ? ";
  41.                 ps2 = conn.prepareStatement("sql2");
  42.         ps2.setDouble(1,money);
  43.         ps2.setString(2,fromActno);
  44.         int count = ps2.executeUpdate(); //执行更新,并返回更新的条数
  45.         
  46.         //---------------------模拟异常--------------------------------
  47.            //此处模拟一个异常,此时钱转出,未转入
  48.                 String s = null;//空指针异常
  49.                                 //试验证明,出问题。引入事务
  50.                 s.toString();
  51.                  //---------------------模拟异常--------------------------------
  52.         
  53.         String sql3 = "update t_act set balance = balance + ? where actno = ? ";
  54.         ps3 = conn.prepareStatement("sql3");
  55.         ps3.setDouble(1,money);
  56.         ps3.setString(2,fromActno);
  57.         count += ps3.executeUpdate();
  58.         
  59.         if (count != 2){
  60.             //转账失败,再来异常
  61.             throw new AppException("App异常,请联系管理员");
  62.         }
  63.         
  64.          //提交事务(转账成功肯定能提交了-----------------------------
  65.                 conn.commit();
  66.         //转账成功
  67.             out.print("转账成功");
  68.         
  69.         
  70.         
  71.         
  72.     }
  73. } catch (Exception e) {
  74.    
  75.     //-------------------------------事务回滚--------------------
  76.     try {
  77.         if (conn != null) { //保险起见,不等于null才回滚
  78.             conn.rollback();//只要遇到异常就回滚
  79.         }
  80.     } catch (SQLException ex) {
  81.         ex.printStackTrace();
  82.     }
  83.     //-----------------------------------------------------
  84.    
  85.     //异常处理,发生上述异常后怎么做
  86.     //e.printStackTrace();      不打印异常信息了,搞到前端去
  87.     out.print(e.getMessage());   //getMessage可以获取到上面写的"余额不足"
  88.                                 // 因为构造方法中有参那个,调用父类的massage,父类中还有super继续上调,
  89.                                 //直到一个private的成员变量,那么值就给他了,而getMassage恰好获得他的值
  90. }finally {
  91.     //释放资源
  92.     if (conn != null) {
  93.         try {
  94.             conn.close();
  95.         } catch (SQLException e) {
  96.             e.printStackTrace();
  97.         }
  98.     }
  99.     if (ps != null) {
  100.         try {
  101.             ps.close();
  102.         } catch (SQLException e) {
  103.             e.printStackTrace();
  104.         }
  105.     }
  106.     if (ps2 != null) {
  107.         try {
  108.             ps.close();
  109.         } catch (SQLException e) {
  110.             e.printStackTrace();
  111.         }
  112.     }
  113.     if (ps3 != null) {
  114.         try {
  115.             ps.close();
  116.         } catch (SQLException e) {
  117.             e.printStackTrace();
  118.         }
  119.     }
  120.     if (rs != null) {
  121.         try {
  122.             rs.close();
  123.         } catch (SQLException e) {
  124.             e.printStackTrace();
  125.         }
  126.     }
  127. }
复制代码
下面分析mvc存在的问题
3.分析问题

3.1AccountTransferServlet负责什么业务(业务逻辑是什么)


  • 数据接收
  • 核心业务处理,转账业务
  • 连接数据库,CRUD
  • 页面数据展示
这个servlet负责所有的事情
3.2缺点是什么


  • 代码复用性太差,实现一个功能就要搞一个servlet,比如R,查一个数据就得写一个servlet,可以搞一个专门查数据的方法,查询数据时调用即可。
    原因:没有进行"职能分工",没有独立组件的概念,没有办法进行代码复用,代码之间耦合度太高,扩展力太差
  • 耦合度高导致代码很难扩展。
  • 操作数据库的代码和业务逻辑混杂在一起,编写代码时很容易出错。无法专注业务逻辑。所以才需要分层。
MVC架构模式

1.理论基础


C调用M和V
M:数据处理、业务处理
V:页面展示
2.JDBC工具类封装

jdbc.properties
  1. driver=com.mysql.cj.jdbc.Driver
  2. url=jdbc:mysql://localhost:3306/mvc
  3. user=root
  4. password=123456
复制代码
DBUtil
  1. package bank.utils;
  2. import java.sql.*;
  3. import java.util.ResourceBundle;
  4. /**
  5. * JDBC工具类
  6. * @author d
  7. * @version 1.0
  8. * @since 1.0
  9. */
  10. public class DBUtil {
  11.     private static ResourceBundle bundle = ResourceBundle.getBundle("resources/jdbc");
  12.     private static String driver = bundle.getString("com.mysql.cj.jdbc.Driver");
  13.     private static String url = bundle.getString("jdbc:mysql://localhost:3306/mvc");
  14.     private static String user = bundle.getString("root");
  15.     private static String password = bundle.getString("123456");
  16.     //工具类一般搞个私有的构造方法,因为不让创建对象。工具类中的方法都是静态的,不需要创建对象
  17.     // 为了防止创建对象,故私有化
  18.     private DBUtil(){}
  19.     //DBUtil在类加载时注册驱动
  20.     static {
  21.         try {
  22.             Class.forName(driver);
  23.         } catch (ClassNotFoundException e) {
  24.             e.printStackTrace();
  25.         }
  26.     }
  27.     /**
  28.      * 这里没有使用数据库连接池,直接创建的连接对象
  29.      * 每一次调用这个方法,都是一个新的对象
  30.      * @return 连接对象
  31.      * @throws SQLException
  32.      */
  33.     public static Connection getConnection() throws SQLException {
  34.         Connection connection = DriverManager.getConnection(url, user, password);
  35.         return connection;
  36.     }
  37.     /**
  38.      * 关闭资源
  39.      * @param conn 连接对象
  40.      * @param stmt 数据库操作对象
  41.      * @param rs   结果集对象
  42.      */
  43.     public static void close(Connection conn , Statement stmt, ResultSet rs){
  44.         if (rs != null) {
  45.             try {
  46.                 rs.close();
  47.             } catch (SQLException e) {
  48.                 e.printStackTrace();
  49.             }
  50.         }
  51.         if (conn != null) {
  52.             try {
  53.                 conn.close();
  54.             } catch (SQLException e) {
  55.                 e.printStackTrace();
  56.             }
  57.         }
  58.         if (stmt != null) {
  59.             try {
  60.                 stmt.close();
  61.             } catch (SQLException e) {
  62.                 e.printStackTrace();
  63.             }
  64.         }
  65.     }
  66. }
复制代码
3.DAO与数据对象实体类

3.1DAO

AccountDao是负责Account数据增删改查的

  • 什么是Dao


  • Data Access Object(数据访问对象)

  • Dao是一种设计模式,是j2EE的设计模式之一,不是23种设计模式
  • Dao只负责数据库的CRUD,没有任何业务逻辑
  • 没有业务逻辑,只负责表中数据增删改查对象,有一个特殊称谓:DAO对象
  • 为什么叫做AccountDao呢?


  • 这是因为这个DAO是专门处理t_act这张表的。
  • 如果处理t_user表的话,可以叫做:UserDao
  • 如果处理t_student表的话,可以叫做:StudentDao
时间
2022.08.30

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表