MVC架构模式

  • 分析AccountTransferServlet类都负责了什么?
    • 数据接收
    • 核心的业务处理
    • 数据库表中数据的crud操作
    • 负责了页面的数据展示
    • 做了很多
  • 在不使用MVC架构模式的前提下,完成银行账户转账的缺点:
    • 代码的复用性太差。因为没有进行职能分工,没有独立组件的概念,所以没有办法进行代码复用。代码和代码之间的耦合度太高,扩展力太差
    • 耦合度高,导致代码很难扩展
    • 操作数据库的代码业务逻辑代码写在一起,很容易出错,无法专注业务逻辑的编写
    • 全部都写在了一个Servlet类中

MVC架构模式的理论基础

  • 理解系统为什么要分层?
    • 这样可以降低代码的耦合度,扩展力强,组件的可复用性增强
  • MVC是一种软件架构模式(是一种软件架构设计思想,不止Java开发中用到,其它语言也需要用到),它将应用分为三块:
    • M(Model:数据/业务):负责业务处理及数据收集(包含了业务逻辑层和持久层)
    • V(View:视图/展示) :负责页面的展示(负责数据的展示)
    • C(Controller:控制器):负责调度。它是一个调度中心,它来决定什么时候调用Model来处理业务,什么时候调用View视图来展示数据。
    • MVC架构模式如下所示:

  • MVC架构模式的描述:①前端浏览器发送请求给web服务器,web服务器中的Controller接收到用户的请求,Controller将前端提交的数据进行封装,②然后Controller调用Model来处理业务,Model处理完业务后返回处理后的数据给Controller,③Controller再调用View来完成数据的展示,最终将结果响应给浏览器,浏览器进行渲染展示页面。

面试题:什么是三层模型,并说一说MVC架构模式与三层模型的区别?

三层模型:

三层架构中哪些是MVC架构的部分: 

现代的开发方式大部分都是MVC架构模式结合三层模型一起用。

MVC 和三层模型都采用了分层结构来设计应用程序,都是降低耦合度,提高扩展力,提高组件复用性。

区别在于:

  • 三层模型更关注业务逻辑组件的划分
  • MVC架构模式关注整个应用程序的层次关系和分离思想。

JavaEE设计模式之DAO

  • 什么是DAO
    • Data Access Object(数据库访问对象),DAO是一种设计模式,属于JavaEE的设计模式之一。
    • DAO类(Mapper类):负责做数据库表增删改查的类,在里面定义了一些操作数据库表crud的方法,没有任何处理业务逻辑的方法在里面
    • (做XXX数据库表crud的Mappp类 就叫做XXXMapper)
    • DAO对象:专门做数据表增删改查的对象,没有任何的业务逻辑。
    • 注意:一般情况下,一张表对应一个DAO对象
    • DAO类中一般有这些方法
      • insert方法、delete方法、update方法、select方法、selectAll方法
  • 例如t_act账户信息表的DAO类
package mvc;

import utils.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * AccountDao负责做数据表的crud
 */
public class AccountDao {
    /**
     * 插入账户信息
     * @param act 账户信息
     * @return
     */
    public int insert(Account act){
        //声明和操作数据库相关的对象
        Connection connection = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            //获取数据库连接对象
           connection = DBUtil.getConnection();
           //获取预编译的数据库操作对象
           String sql = "insert into t_act(actno,balance)values(?,?,)";
           ps = connection.prepareStatement(sql);
           ps.setString(1, act.getActno());
           ps.setDouble(2,act.getBalance());
           //执行SQL语句
           count = ps.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //关闭数据库资源
            DBUtil.close(connection,ps,null);
        }
        return count;
    }

    /**
     * 根据主键删除账户信息
     * @param id 主键
     * @return
     */
    public int deleteById(Long id){
        Connection connection = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            connection = DBUtil.getConnection();
            String sql = "delete from t_act where id = ?";
            ps = connection.prepareStatement(sql);
            ps.setLong(1,id);
            count = ps.executeUpdate();
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,ps,null);
        }
        return count;
    }

    /**
     * 更新账户信息
     * @param act 账户信息
     * @return
     */
    public int update(Account act){
        Connection connection = null;
        PreparedStatement ps = null;
        int count = 0;
        try {
            connection = DBUtil.getConnection();
            String sql = "update t_act set balance = ?,actno = ? where id = ?";
            ps = connection.prepareStatement(sql);
            ps.setDouble(1,act.getBalance());
            ps.setString(2, act.getActno());
            ps.setLong(3,act.getId());
            count = ps.executeUpdate();
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,ps,null);
        }
        return count;
    }

    /**
     * 根据账户查询一条账户信息,返回一个封装好的Account对象
     * @param actno 账号
     * @return
     */
    public Account selectByActno(String actno){
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        Account act = null;
        int count = 0;
        try {
            connection = DBUtil.getConnection();
            String sql = "select id,actno,balance from t_act where actno = ?";
            ps = connection.prepareStatement(sql);
            ps.setString(1,actno);
            resultSet = ps.executeQuery();
            if(resultSet.next()){
                Long id = resultSet.getLong("id");
                Double balance = resultSet.getDouble("balance");
                //将属性值封装成对象
                act = new Account();
                act.setId(id);
                act.setBalance(balance);
                act.setActno(actno);

            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,ps,resultSet);
        }
        return act;
    }

    /**
     * 获取所有账户信息
     * @return
     */
    public List<Account> selectAll(){
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        List<Account> list = new ArrayList<>();
        int count = 0;
        try {
            connection = DBUtil.getConnection();
            String sql = "select id,actno,balance from t_act";
            ps = connection.prepareStatement(sql);
            resultSet = ps.executeQuery();
            while (resultSet.next()){
                Long id = resultSet.getLong("id");
                String actno = resultSet.getString("actno");
                Double balance = resultSet.getDouble("balance");
                //将这些数据封装成对象
//                Account act = new Account();
//                act.setId(id);
//                act.setActno(actno);
//                act.setBalance(balance);
                Account act = new Account(id,actno,balance);
                //添加到集合中
                list.add(act);
            }
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,ps,resultSet);
        }
        return list;
    }
}

pojo==javabean==domain实体类

pojo==javabean==domain类:专门用于封装数据的类

pojo对象:简单的对象,专门用于封装数据的对象,也叫作为javabean对象,domain对象。

业务逻辑层的抽取及业务类的实现

  • service翻译为:服务,业务。
  • 在service业务类 中只编写纯业务代码,业务类一般起名为XxxService、XxxBiz。如AccountService类是专门处理Account业务的一个类。
  • 一个业务对应业务类中的一个方法

MVC架构模式和三层架构的关系

先来说三层架构:

用户发送请求过来后:

  • 表现层调用业务逻辑层进行业务处理,
  • 业务逻辑层再调用持久层去操作数据库;
  • 之后再将数据的处理结果一层一层的返回到表示层

代码实现:

  • 用户发送请求过来到控制器,
  • 在控制器类的处理器方法中使用业务逻辑层的对象调用相关业务方法,
  • 在业务逻辑类中又使用持久层对象调用其操作数据库表的方法。

三层架构图:

MVC架构模式和三层架构的关系:

  • MVC中的控制器和视图是三层架构中的表示层
  • MVC的Model是三层架构中的其余部分

不同功能的类放在不同的包下

  • 三层架构中:
    • servlet、jsp是表示层
    • service是业务逻辑层
    • 持久层是dao
  • 在MVC架构模式中
    • bean、dao、service都属于M
    • jsp是V
    • servlet是C

web包是放servlet类的

层与层之间是通过接口调用的,也就是面向接口编程,需要先在每个包中创建接口,然后再创建一个和接口同级的包叫imple,里面创建接口的实现类

ThreadLocal类源码分析及概述

源码

  • ThreadLocal(线程局部变量类)其实就是在ThreadLocal类中定义了个Map<Thread,T>集合,key存储的是当前线程,value存与当前线程绑定的数据(对象)
  • 作用:提供线程的局部(本地)变量,它是每个线程私有的(局部)本地变量,使用ThreadLocal存储的数据是线程安全的 。通过ThreadLocal使程序中不同位置获取到的数据库连接对象是同一个

package com.threadlocal;


import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义一个ThreadLocal类
 */
public class MyThreadLocal<T> {
    /**
     * 创建了一个Map集合,用于存储和当前线程 绑定 的数据(对象)
     */
    private Map<Thread,T> map = new HashMap<>();

    /**
     * 向ThreadLocal变量中绑定数据:把当前线程和对象(数据)绑定
     */
    public void set(T obj){
        map.put(Thread.currentThread(),obj);
    }

    /**
     * 从ThreadLocal中获取当前线程对应的对象(数据)
     * @return
     */
    public T get(){
        return map.get(Thread.currentThread());
    }

    /**
     * 删除ThreadLocal中的数据,删除当前线程对应的数据库连接对象
     */
    public void remove(){
        map.remove(Thread.currentThread());
    }
}

概述

介绍:

ThreadLocal 并不是一个Thread,而是Thread的局部变量。

ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

客户端发送的每一次请求,都是单独的一个线程。

常用方法:

public void set(T value) 设置当前线程线程 局部变量值

public T get() 获取当前线程的线程 局部变量值。

public void remove() 移除当前线程的线程 局部变量值

ThreadLocal的应用场景

  1. 线程上下文传递:在不同的线程中传递上下文信息,例如将用户信息和请求ID存储在ThreadLocal中,在后续的请求处理链中可以方便的访问。
  2. 数据库连接管理:在使用数据库连接池的情况下,可以把数据库的连接存储在ThreadLocal中,这样每个线程可以独立管理自己的数据库连接,从而有效减少线程间的竞争,提高资源利用率(Mybatis中的SqlSession对象使用了ThreadLocal存储当前线程的数据库会话信息)
  3. 事务管理:在需要手动管理事务时,使用ThreadLocal存储事务的上下文,每个线程可以独立控制自己的事务,保证事务的隔离性(Spring中的TransactionSynchronizationManager类使用了ThreadLocal存储事务的上下文信息)
  4. 总结:在使用ThreadLocal中需要避免出现内存泄漏的问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/942998.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

打破视障壁垒,百度文心快码无障碍版本助力视障IT从业者就业无“碍”

有AI无碍 钟科&#xff1a;被黑暗卡住的开发梦 提起视障群体的就业&#xff0c;绝大部分人可能只能想到盲人按摩。但你知道吗&#xff1f;视障人士也能写代码。 钟科&#xff0c;一个曾经“被黑暗困住”的人&#xff0c;他的世界&#xff0c;因为一场突如其来的疾病&#xff0c…

【RAG实战】语言模型基础

语言模型赋予了计算机理解和生成人类语言的能力。它结合了统计学原理和深度神经网络技术&#xff0c;通过对大量的样本数据进行复杂的概率分布分析来学习语言结构的内在模式和相关性。具体地&#xff0c;语言模型可根据上下文中已出现的词序列&#xff0c;使用概率推断来预测接…

48页PPT|2024智慧仓储解决方案解读

本文概述了智慧物流仓储建设方案的行业洞察、业务蓝图及建设方案。首先&#xff0c;从政策层面分析了2012年至2020年间国家发布的促进仓储业、物流业转型升级的政策&#xff0c;这些政策强调了自动化、标准化、信息化水平的提升&#xff0c;以及智能化立体仓库的建设&#xff0…

Matlab环形柱状图

数据准备&#xff1a; 名称 数值 Aa 21 Bb 23 Cc 35 Dd 47 保存为Excel文件后&#xff1a; % Load data from Excel file filename data.xlsx; % Ensure the file is in the current folder or provide full path dataTable readtable(filena…

flask后端开发(3):html模板渲染

目录 渲染模板html模板获取路由参数 gitcode地址&#xff1a; https://gitcode.com/qq_43920838/flask_project.git 渲染模板 这样就能够通过html文件来渲染前端&#xff0c;而不是通过return了 html模板获取路由参数

15 break和continue

while True: content input("请输入你要喷的内容") print("发送给下路",content) #上述的程序如果没有外力干扰&#xff1a;程序会一直进行输入下去 #break:就能让当前这个循环立即进行停止 while True: content input("请输入…

Python9-作业2

记录python学习&#xff0c;直到学会基本的爬虫&#xff0c;使用python搭建接口自动化测试就算学会了&#xff0c;在进阶webui自动化&#xff0c;app自动化 python基础8-灵活运用顺序、选择、循环结构 作业2九九乘法表三种方式打印九九乘法表使用两个嵌套循环使用列表推导式和…

微信小程序 不同角色进入不同页面、呈现不同底部导航栏

遇到这个需求之前一直使用的小程序默认底部导航栏&#xff0c;且小程序默认入口页面为pages/index/index&#xff0c;要使不同角色呈现不同底部导航栏&#xff0c;必须要在不同页面引用不同的自定义导航栏。本篇将结合分包&#xff08;subPackages&#xff09;展开以下三步叙述…

表达式语句、复合语句和空语句

欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;表达式语句、复合语句和空语句 发布时间&#xff1a;2024.12.26 隶属专栏&#xff1a;C语言 目录 1. 表达式语句定义作用常见类型赋值语句函数调用语句 2. 复合语句定义作用变量作用域 3. 空语句定义作用 1. 表达式…

Linux arm 编译安装glibc-2.29

重要的话说三遍&#xff1a; &#xff01;&#xff01;&#xff01;&#xff01;&#xff01;不要轻易自己去安装glibc&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; &#xff01;&#xff01;&#xff01;&#xff01;&#xff01;不要轻易自己去安装glibc&a…

20241225在ubuntu22.04.5下使用smartmontools命令查看ssd的寿命

20241225在ubuntu22.04.5下使用smartmontools命令查看ssd的寿命 2024/12/25 15:10 rootrootrootroot-ThinkBook-16-G5-IRH:~$ sudo apt install smartmontools rootrootrootroot-ThinkBook-16-G5-IRH:~$ sudo fdisk -l Disk /dev/nvme0n1: 3.73 TiB, 4096805658624 bytes, 800…

大数据学习之Redis 缓存数据库二,Scala分布式语言一

一.Redis 缓存数据库二 26.Redis数据安全_AOF持久化机制 27.Redis数据安全_企业中该如何选择持久化机制 28.Redis集群_主从复制概念 29.Redis集群_主从复制搭建 30.Redis集群_主从复制原理剖析 31.Redis集群_哨兵监控概述 32.Redis集群_配置哨兵监控 33.Redis集群_哨兵监控原理…

Datawhale AI 冬令营学习笔记-零编程基础制作井字棋小游戏

井字棋小游戏是通过豆包MarsCode实现的&#xff0c;没有改动任何的代码&#xff0c;全部是通过对话让AI进行优化和改进。 开始进入正题&#xff1a;进入豆包MarsCode在线IDE&#xff0c;直接点击上方蓝字&#xff0c;或复制链接打开: 豆包 MarsCode - 编程助手。 IDE界面&…

vscode+编程AI配置、使用说明

文章目录 [toc]1、概述2、github copilot2.1 配置2.2 使用文档2.3 使用说明 3、文心快码&#xff08;Baidu Comate&#xff09;3.1 配置3.2 使用文档3.3 使用说明 4、豆包&#xff08;MarsCode&#xff09;4.1 配置4.2 使用文档4.3 使用说明 5、通义灵码&#xff08;TONGYI Lin…

Redis数据结构和内部编码以及单线程架构

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Redis数据结构和内部编码以及单线程架构 收录于专栏[redis] 本专栏旨在分享学习Redis的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 …

虚拟机Hyper-V,安装网络宝塔Docker

我下载的是centos-min大小1G&#xff0c;安装后没网络&#xff0c; 关闭防火墙&#xff0c;网络&#xff0c;修改onBootyes,这里需要看下network-Scripts下有什么文件。 然后就可以访问网络了 虚拟机的设置也是默认就好 网络需要设置允许共享-重要 urlhttps://download.bt.cn/i…

红魔电竞PadPro平板解BL+ROOT权限-KernelSU+LSPosed框架支持

红魔Padpro设备目前官方未开放解锁BL&#xff0c;也阉割了很多解锁BL指令&#xff0c;造成大家都不能自主玩机。此规则从红魔8开始&#xff0c;就一直延续下来&#xff0c;后续的机型大概率也是一样的情况。好在依旧有开发者进行适配研究&#xff0c;目前红魔PadPro平板&#x…

Linux-----进程处理(文件IO资源使用)

下面代码是通过父进程和子进程对同一个文件IO资源进行操作&#xff0c;父进程和子进程都对这个进程进行写入操作&#xff0c;我们都知道这两个进程实际上是并发的&#xff0c;所以需要一个同步机制来去操作同一个资源&#xff08;后面再深入去说明同步的api&#xff0c;这里使用…

EdgeX Core Service 核心服务之 Core Command 命令

EdgeX Core Service 核心服务之 Core Command 命令 一、概述 Core-command(通常称为命令和控制微服务)可以代表以下角色向设备和传感器发出命令或动作: EdgeX Foundry中的其他微服务(例如,本地边缘分析或规则引擎微服务)EdgeX Foundry与同一系统上可能存在的其他应用程序…

【LeetCode】94.二叉树的中序遍历

题目链接&#xff1a; 94.二叉树的中序遍历 题目描述&#xff1a; 题解&#xff1a;&#xff08;递归算法实现二叉树中序遍历&#xff09; 二叉树的中序遍历&#xff1a;按照访问左子树——根节点——右子树的方式遍历这棵树&#xff0c;而在访问左子树或者右子树的时候我们按…