当前位置: 首页 > news >正文

【Java Web】DAO模式及单例模式(含代码示例)

文章目录

    • JDBC封装
    • DAO模式
      • 实体类
      • DAO接口
      • DAO实现类
      • 数据源配置
      • 基础DAO类
      • 业务逻辑层
    • 单例模式
      • 饿汉式
      • 懒汉式

JDBC封装

JDBC(Java Database Connectivity)封装是一种将 JDBC 的基本操作和常见的数据库访问逻辑封装成易于使用的工具类或框架的方法。这样做的目的是为了减少重复代码,提高代码的可读性和可维护性,并且简化数据库访问的过程。

在这里插入图片描述

隔离业务逻辑代码和数据访问代码
隔离不同数据库的实现

实现 JDBC 封装

  • 将所有增删改查操作抽取成接口
  • 定义实体类传输数据
  • 将通用的操作(打开、关闭连接等)封装到工具类
  • 数据库工具类BaseDao:增、删、改、查的通用方法

DAO模式

DAO(Data Access Object 数据存取对象)模式:将数据访问逻辑封装在单独的类中,使得业务逻辑层不需要关心具体的数据库操作细节。

  • DAO接口:定义了对数据库进行访问的方法
  • DAO实现类:实现了DAO接口,提供了具体的数据访问逻辑
  • 实体类:表示数据库中的表或记录
  • 数据源配置:配置数据库连接信息
  • 业务逻辑层:使用DAO接口来处理业务逻辑,而不需要关心具体的数据库操作

DAO 起着转换器的作用,将数据在实体类和数据库记录之间进行转换

在这里插入图片描述

创建包

com.dao             ----放接口文件    UserDao  BaseDao(数据库工具类)com.dao.impl    ----放接口实现类   UserDaoImpl
com.entity||pojo    ----放实体类      User

实体类

代表数据库中的表或记录。每个实体类通常对应一个数据库表,并且包含与表字段相对应的属性。

public class SmbmsUser {private Integer id;          // idprivate String userCode;     // 用户编码private String userName;     // 用户名称private String userPassword; // 用户密码private Integer gender;      // 性别private Date birthday;       // 出生日期private String phone;        // 电话private String address;      // 地址private Integer userRole;    // 用户角色private Integer createdBy;   // 创建者private Date creationDate;   // 创建时间private Integer modifyBy;    // 更新者private Date modifyDate;     // 更新时间@Overridepublic String toString() {// 重写 toString() 方法...}// get&set 方法...
}

DAO接口

定义了对数据库进行访问的方法,通常是增删改查等基本操作。

公共接口

public interface PublicInterface<E> {/*** 根据ID获取单一实体。* @param id 实体的唯一标识* @return 返回Optional包装的实体,如果没有找到则返回空的Optional*/E findById(Integer id);/*** 获取所有实体。* @return 返回包含所有实体的列表*/List<E> findAll();/*** 保存或更新实体。* 如果实体已存在,则执行更新操作;如果不存在,则执行插入操作。* @param e 要保存或更新的实体* @return 操作后的实体*/int save(E e);/*** 删除指定ID的实体。* @param id 要删除的实体ID*/int deleteById(Integer id);
}

SmbmsUser 类接口

public interface SmbmsUserDao extends PublicInterface<SmbmsUser>{/*** 登录* @param name 用户名* @param pwd 密码* @return 用户对象*/public SmbmsUser login(String name, String pwd);
}

DAO实现类

实现了DAO接口,提供了具体的数据访问逻辑。这个类中包含了与数据库交互的具体代码。

public class SmbmsUserDaoImpl extends BaseDao implements SmbmsUserDao {@Overridepublic SmbmsUser login(String name, String pwd) {try{if(getConnection()){// 3.准备 SQL 语句String sql = "select id,userCode,userName,userPassword from smbms_user " +"where userCode = ? and userPassword = ?";ResultSet res = query(sql,name,pwd);// 6.处理 resultSet 结果集SmbmsUser smbmsUser = null;while(res.next()){smbmsUser = new SmbmsUser();smbmsUser.setId(res.getInt("id"));smbmsUser.setUserCode(res.getString("userCode"));smbmsUser.setUserName(res.getString("userName"));smbmsUser.setUserPassword(res.getString("userPassword"));}return smbmsUser;}} catch (Exception e) {e.printStackTrace();} finally {closeResources(); // 释放资源}return null;}@Overridepublic SmbmsUser findById(Integer id) {// ...}@Overridepublic List<SmbmsUser> findAll() {try{if(getConnection()){String sql = "select id,userCode,userName,userPassword from smbms_user";ResultSet res = query(sql);List<SmbmsUser> list = new ArrayList<>();while(res.next()){SmbmsUser smbmsUser = new SmbmsUser();smbmsUser.setId(res.getInt("id"));smbmsUser.setUserCode(res.getString("userCode"));smbmsUser.setUserName(res.getString("userName"));smbmsUser.setUserPassword(res.getString("userPassword"));list.add(smbmsUser);}return list;}} catch (Exception e) {e.printStackTrace();} finally {closeResources(); // 释放资源}return null;}@Overridepublic int save(SmbmsUser smbmsUser) {try {if (getConnection()) {String sql = "INSERT INTO smbms_user (userCode, userName, userPassword) " +"VALUES (?, ?, ?)";return update(sql, smbmsUser.getUserCode(), smbmsUser.getUserName(), smbmsUser.getUserPassword());}} catch (Exception e) {e.printStackTrace();} finally {closeResources(); // 释放资源}return 0;}@Overridepublic int deleteById(Integer id) {try {if (getConnection()) {return update("DELETE FROM smbms_user WHERE id = ?",id);}} catch (Exception e) {e.printStackTrace();} finally {closeResources(); // 释放资源}return 0;}
}

数据源配置

数据源配置通常在单独的文件中定义,例如 jdbc.propertiesapplication.properties

使用属性文件来管理数据库连接信息,需要创建 .properties文件存储配置,并在 Java 代码中读取这些属性。

# jdbc.properties 数据格式为 " 键 = 值 "
mysql.driver = com.mysql.cj.jdbc.Driver
mysql.url = jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
mysql.username = root
mysql.userpwd = root

Java 中提供了 Properties 类来读取配置文件

/*** @Description: 读取JDBC.properties文件* 饿汉模式*/
public class ConfigManager {private static Properties properties = new Properties();// 只运行一次static {try {InputStream is = ConfigManager.class.getClassLoader().getResourceAsStream("jdbc.properties");// 将字节流转换为 properties 对象properties.load(is);System.out.println(properties.getProperty("mysql.driver"));} catch (IOException e) {throw new RuntimeException(e);}}public static String getString(String key){return properties.getProperty(key);}
}

基础DAO类

BaseDao 类封装了与数据库连接、执行查询和更新操作以及释放资源相关的通用功能。是一个基础的数据访问对象类。

提供了以下功能:

  • 获取数据库连接。
  • 执行查询操作并返回结果集。
  • 执行增删改操作并返回受影响的行数。
  • 释放数据库连接和 PreparedStatement 对象。
public class BaseDao {protected Connection conn = null;protected PreparedStatement stat = null;/*** 获得 conn 对象* @return*/public boolean getConnection() {try {// 1.加载驱动Class.forName(ConfigManager.getString("mysql.driver"));// 2.创建 Connection 对象(通过 DriverManager)conn = DriverManager.getConnection(ConfigManager.getString("mysql.url"), ConfigManager.getString("mysql.username"), ConfigManager.getString("mysql.userpwd"));return true;} catch (Exception e) {e.printStackTrace();}return false;}/*** 查询*/public ResultSet query(String sql, Object... objs) throws Exception{// 4.赋值 PreparedStatement 对象(通过 Connection)stat = conn.prepareStatement(sql);// 5.执行 SQL 语句(通过 PreparedStatement)if(objs != null){for (int i = 0; i < objs.length; i++) {stat.setObject((i + 1),objs[i]);}}return stat.executeQuery();}/*** 增删改*/public int update(String sql,Object... objs) throws Exception{// 4.赋值 PreparedStatement 对象(通过 Connection)stat = conn.prepareStatement(sql);// 5.执行 SQL 语句(通过 PreparedStatement)if(objs != null){for (int i = 0; i < objs.length; i++) {stat.setObject((i + 1),objs[i]);}}return stat.executeUpdate();}/*** 释放资源*/public void closeResources(){// 7. 关闭资源try {if(stat != null) stat.close();if(conn != null) conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}
}

业务逻辑层

使用DAO接口来处理业务逻辑,而不需要关心具体的数据库操作。

public class Main {public static void main(String[] args) {SmbmsUserDao smbmsUserDao = new SmbmsUserDaoImpl();// 测试登录SmbmsUser smbmsUser = smbmsUserDao.login("liming","0000000");if(smbmsUser != null){System.out.println("登录成功!"+smbmsUser.getUserName()+"欢迎您!");} else {System.out.println("账号或密码错误,登录失败!");}// 测试添加用户SmbmsUser newUser = new SmbmsUser();newUser.setUserCode("yier");newUser.setUserName("yier");newUser.setUserPassword("1234567");int addResult = smbmsUserDao.save(newUser);if (addResult > 0) {System.out.println("新用户添加成功!");} else {System.out.println("新用户添加失败!");}// 测试查询所有List<SmbmsUser> allUsers = smbmsUserDao.findAll();System.out.println(allUsers);// 测试根据 ID 查询// 假设我们要查询刚刚添加的用户SmbmsUser foundUser =  smbmsUserDao.findById(newUser.getId());if (foundUser != null) {System.out.println("该用户为: " + foundUser);} else {System.out.println("该用户不存在");}// 测试删除用户// 假设我们要删除刚刚添加的用户int i = smbmsUserDao.deleteById(newUser.getId());if (i > 0) {System.out.println("用户删除成功!");} else {System.out.println("用户删除失败!");}}
}

单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点。这种模式通常用于那些需要频繁实例化然后销毁的对象,或者创建对象需要消耗大量资源的情况。单例模式可以确保系统中某个类的唯一性,避免由于多实例导致的数据不一致等问题。

  • 单一实例:整个系统运行期间,只存在一个该类的实例。
  • 私有构造器:防止外部通过new关键字直接创建实例。
  • 自行创建实例:在类内部自行创建唯一的实例。
  • 静态私有对象:定义一个静态私有的成员变量来保存这个唯一的实例。
  • 全局访问点:提供一个公共的方法,使外界能够获取到这个实例。

饿汉式

(Eager Initialization)

这种方式在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。这是线程安全的实现。

/*** @Description: 读取JDBC.properties文件* 饿汉模式*/
public class ConfigManager {private static Properties properties = new Properties();// 只运行一次static {try {InputStream is = ConfigManager.class.getClassLoader().getResourceAsStream("jdbc.properties");// 将字节流转换为 properties 对象properties.load(is);System.out.println(properties.getProperty("mysql.driver"));} catch (IOException e) {throw new RuntimeException(e);}}public static String getString(String key){return properties.getProperty(key);}
}

懒汉式

(Lazy Initialization, 线程不安全)

这种方式延迟了实例的创建,直到第一次使用时才进行初始化。但是这种方法不是线程安全的,在多线程环境下可能会产生多个实例,因此需要用到 synchronized 关键字。

/*** @Description: 读取JDBC.properties文件* 懒汉模式*/
public class ConfigManager1 {private static ConfigManager1 configManager1 = null;private static Properties properties = new Properties();public ConfigManager1(){try {InputStream is = ConfigManager1.class.getClassLoader().getResourceAsStream("jdbc.properties");// 将字节流转换为 properties 对象properties.load(is);System.out.println(properties.getProperty("mysql.driver"));} catch (IOException e) {throw new RuntimeException(e);}}public synchronized static ConfigManager1 getConfigManager1(){if(configManager1 == null){configManager1 = new ConfigManager1();}return configManager1;}public  String getString(String key){return properties.getProperty(key);}
}public class Singleton {private static Singleton instance;// 私有构造函数private Singleton() {}// 提供一个全局访问点public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

在整个程序运行期间,有且仅有一个实例。若违背这一点,所设计的类就不是单例类。

单例模式懒汉模式饿汉模式
概念在类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例在类加载的时候就完成初始化
特点类加载速度快,但是运行时获取对象的速度较慢(时间换空间)类加载较慢,但获取对象速度快(空间换时间)
延迟加载(lazy loading)具备不具备
线程安全线程不安全线程安全

相关文章:

【Java Web】DAO模式及单例模式(含代码示例)

文章目录 JDBC封装DAO模式实体类DAO接口DAO实现类数据源配置基础DAO类业务逻辑层 单例模式饿汉式懒汉式 JDBC封装 JDBC&#xff08;Java Database Connectivity&#xff09;封装是一种将 JDBC 的基本操作和常见的数据库访问逻辑封装成易于使用的工具类或框架的方法。这样做的目…...

深入探讨SEO分析技巧助力网站流量提升

内容概要 在当前的数字化时代&#xff0c;SEO分析的重要性不言而喻。它是提升网站流量的关键工具&#xff0c;帮助站长有效地优化网站内容和结构。通过系统的SEO分析&#xff0c;站长可以掌握用户搜索行为和需求&#xff0c;从而制定出更具针对性的内容策略。例如&#xff0c;…...

Chrome 130 版本开发者工具(DevTools)更新内容

Chrome 130 版本开发者工具&#xff08;DevTools&#xff09;更新内容 一、网络&#xff08;Network&#xff09;面板更新 1. 重新定义网络过滤器 网络面板获新增了一些过滤条件&#xff0c;这些过滤条件是根据反馈重新设计的&#xff0c;特定于类型的过滤条件保持不变&…...

深度学习基础知识-残差网络ResNet

目录 一、ResNet 的核心思想&#xff1a;残差学习&#xff08;Residual Learning&#xff09; 二、ResNet 的基本原理 三、ResNet 网络结构 1. 残差块&#xff08;Residual Block&#xff09; ResNet 的跳跃连接类型 2. 网络结构图示 四、ResNet 的特点和优势 五、ResNe…...

Linux云计算个人学习总结(二)

高级文件系统 一、RSYNC概述 1、作用&#xff1a;快速的文件复制工具&#xff08;支持本地和远程&#xff09;&#xff0c;以及删除、查看等基本功能。 2、特点&#xff1a;支持实时&#xff08;inotify、sersync&#xff09;的增量备份工具3、模式&#xff1a;检查模式&#…...

Java入门(7)--网络编程

Java网络编程&#xff1a;构建网络应用的基石 &#x1f310; &#x1f3af; 掌握Java网络编程&#xff0c;打造强大的网络应用&#xff01; 在上一篇文章中&#xff0c;我们探讨了Java的I/O操作和反射机制。今天&#xff0c;让我们深入学习Java网络编程&#xff0c;了解如何构建…...

[思考记录]思维局限,以为懂了

最近配合整理一些内容&#xff0c;找到较早期的某些产品设计资料在翻阅回顾。在这次回顾过程中&#xff0c;发现当时自己的理解存在很多局限。 以资源体系的设计为例&#xff0c;那时自认为已经“懂了”&#xff0c;对相关的概念、作用关系、组成及实现等都有一定的了解&#x…...

力扣题目解析--最长公共前缀

题目 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示例 2&#xff…...

不画饼——研究生学习和赚钱的平衡点

在现代社会中&#xff0c;年轻人面临着学习和赚钱之间的矛盾。尤其是在经济压力日益增大的背景下&#xff0c;如何在这两者之间找到合适的平衡点&#xff0c;成为了许多学生和职场新人面临的重要问题。本文将探讨在何种情况下应该听从老师的建议&#xff0c;专注于学习&#xf…...

华为实时视频使用FLV播放RTSP流

import flvjs from ‘flv.js’; 安装flv <video style"width:100%;height:100%;" ref"videoHWRef" ></video>// src 华为rtsp流 rtsp://admin:Huaweivideo10.10.8.151:554/xxx/trackID1// url 需要后端提供视频源地址playVideo() {if (fl…...

JAVA设计模式之【建造者模式】

1 定义 建造者模式&#xff08;Builder Pattern&#xff09;使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 2 类图 产品类&#xff08;Product&#xff09;&#xff1a;表示被创建的复杂…...

【jvm】为什么Xms和Xmx的值通常设置为相同的?

目录 1. 说明2. 避免性能开销3. 提升稳定性4. 简化配置5. 优化垃圾收集6. 获取参数6.1 代码示例6.2 结果示例 1. 说明 1.-Xms 和 -Xmx 参数分别用于设置堆内存的初始大小&#xff08;最小值&#xff09;和最大大小。2.在开发环境中&#xff0c;开发人员可能希望快速启动应用程…...

windows查看net网络监听端口命令和工具(ipconfig、netstat、tasklist、TCPView)

文章目录 使用命令提示符(CMD)查看网络连接和配置使用 netstat 命令查看监听端口查看特定的端口查看TCP监听端口tasklist查看对应进程ID的程序Get-NetTCPConnection 命令使用 TCPView工具使用命令提示符(CMD) 查看网络连接和配置 ipconfig :显示所有网络 适配器的当前 TC…...

JAVA-数据结构- 二叉搜索树

1.搜索树 前面我们已经使用C语言学习完了二叉树&#xff0c;懂得了一些二叉树的基本性质已经实现方法 https://mp.csdn.net/mp_blog/creation/editor/139572374&#xff0c;本文我们来一起进行二叉树的衍生-二叉搜索树 1.1 概念 二叉搜索树又称二叉排序树&#xff0c;它或者是…...

深入研究 RAG 流程中的关键组件

我们已经看到了整个RAG流程&#xff0c;并获得了第一手的实践经验&#xff0c;您可能会对RAG流程中一些组件的使用和目的存在很多疑惑&#xff0c;比如RunnablePassthrough。在本节中&#xff0c;我们将进一步了解这些关键组件。 RAG的核心模型思想是将一个复杂的任务分解为多…...

新手如何学习python并快速成为高手

英雄Python入门到精通链接&#xff1a;https://pan.quark.cn/s/57162ec366a9 学习Python作为新手&#xff0c;有以下几个步骤&#xff1a; 学习基本概念和语法&#xff1a;首先&#xff0c;你需要学习Python的基本概念和语法。可以通过在线教程、书籍或者视频教程来学习。了解…...

Linux历史命令history增加执行时间显示

Centos系统默认历史命令显示如下 为了更好的溯源&#xff0c;获取执行命令的准确时间&#xff0c;需要增加一些配置 设置环境变量 vim /etc/profile 在最下面添加以下环境配置 export HISTTIMEFORMAT"%Y-%m-%d %H:%M:%S " 立即刷新该环境变量 source /etc/pro…...

从 vue 源码看问题 — 你知道 Hook Event 吗?

前言 在之前的几篇文章中&#xff0c;都有提到 vue 中调用生命周期钩子时是通过 callHook() 方法进行调用的&#xff0c;比如在初始化篇章中调用 beforeCreate 和 created 生命周期钩子方式如下: 那么接下来一起来了解下到底什么是 Hook Event &#xff1f; Hook Event 是什…...

信息安全工程师(68)可信计算技术与应用

前言 可信计算技术是一种计算机安全体系结构&#xff0c;旨在提高计算机系统在面临各种攻击和威胁时的安全性和保密性。 一、可信计算技术的定义与原理 可信计算技术通过包括硬件加密、受限访问以及计算机系统本身的完整性验证等技术手段&#xff0c;确保计算机系统在各种攻击和…...

每日OJ题_牛客_相差不超过k的最多数_滑动窗口_C++_Java

目录 牛客_相差不超过k的最多数_滑动窗口 题目解析 C代码 Java代码 牛客_相差不超过k的最多数_滑动窗口 相差不超过k的最多数_牛客题霸_牛客网 (nowcoder.com) 描述&#xff1a; 给定一个数组&#xff0c;选择一些数&#xff0c;要求选择的数中任意两数差的绝对值不超过 …...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...