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

Java项目——苍穹外卖(一)

Entity、DTO、VO

Entity(实体)

  • Entity 是表示数据库表的对象,通常对应数据库中的一行数据。它通常包含与数据库表对应的字段,并可能包含一些业务逻辑。

DTO(数据传输对象)

  • 作用:DTO 是用于在不同层之间传输数据的对象,通常用于网络传输或服务间调用。DTO 主要用于减少网络请求的次数,携带数据而不包含业务逻辑。
  • 特点:DTO类通常只包含数据字段和相应的getter和setter方法,不包含任何业务逻辑。它们可能包含与Entity类相似的字段,但也可能根据需要进行裁剪或扩展

 VO(视图对象)

  • 位置:虽然VO这个术语不如DTO和Entity那样普遍,但在一些项目中,你可能会看到vo包用于存放视图对象。
  • 作用:VO主要用于封装返回给前端的数据。它们可以被视为DTO的一种特殊形式,专门用于视图层的数据展示。VO可以根据前端的需求进行定制,包含前端需要展示的所有数据,以及可能的前端逻辑(如格式化数据)
  • 特点:VO类与DTO类似,主要关注数据的封装和传输,但更侧重于前端展示的需求。它们可能包含与Entity或DTO不同的字段,或者对字段进行不同的封装和格式化。

举例

对于数据库中的employee表:

@Data
@Builder//构建器注解,此类的对象可以使用builder方法进行构建
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String username;private String name;private String password;private String phone;private String sex;private String idNumber;private Integer status;//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime updateTime;private Long createUser;private Long updateUser;}
@Data
public class EmployeeDTO implements Serializable {private Long id;private String username;private String name;private String phone;private String sex;private String idNumber;}

 总结

Entity:

  • 与数据库表对应,包含数据的持久化逻辑。
  • 主要用于数据库操作,在数据访问层与数据库交互时使用。
  • 封装数据库操作的细节
  • 属性通常与数据库表字段一一对应

DTO:

  • 用于层与层之间的数据传输,不包含业务逻辑。
  • 用于系统内部数据传输,在服务层调用中传递数据。
  • 封装业务逻辑的细节
  • 可以包含额外的或部分的属性

VO:

  • 用于封装返回给前端的数据,可能包含前端展示所需的特定逻辑。
  • 在展示层向用户展示数据时使用
  • 封装展示逻辑的细节
  • 可以包含额外的或部分的属性

公共字段填充(AOP)

问题分析

在增加或查询操作中,设置下列字段时代码冗余,不便于后期维护

实现思路

技术点:枚举、注解、AOP、反射

一、创建枚举类

/*** 数据库操作类型* 枚举类*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT}

二、创建自定义注解类

/*** 自定义注解,用于标识某个方法需要进行功能字段自动填充处理* 这个类可以作为一个注解进行使用*/
@Target(ElementType.METHOD)//指定当前的自定义注解只能加在方法上
@Retention(RetentionPolicy.RUNTIME)//固定写法
public @interface AutoFill {//数据库操作类型:UPDATE INSERT(只有增加和修改操作涉及公共字段填充)OperationType value();
}

三、在切入点方法上加入自定义注解,并指定其属性(更新操作/插入操作)

四、创建切面类,在切面类中实现通知逻辑

/*** 自定义切面类,实现公共字段自动填充处理逻辑*/
@Aspect//设置当前类为切面类,告诉spring这个类是用来做AOP的
@Component//通知类(切面类)必须配置成Spring管理的bean
@Slf4j
public class AutoFillAspect {//此切入点表达式前半部分锁定mapper包下所有类所有方法,后半部分锁定方法中加入了AutoFill注解的方法@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut(){}/*** 前置通知,在通知中进行公共字段的赋值*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint){log.info("开始进行公共字段自动填充");//1.获取当前被拦截的方法上的数据库操作类型MethodSignature signature = (MethodSignature) joinPoint.getSignature();//获得方法签名对象,并向下转型为MethodSignatureAutoFill antoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象OperationType operationType = antoFill.value();//获得数据库操作类型//这三行的代码最终作用是获得注解中的数据库操作类型,也就是 @AutoFill(value = OperationType.UPDATE)中的value//2.获取当前被拦截的方法的参数--实体对象Object[] args = joinPoint.getArgs();//获取通知点方法的参数if(args == null || args.length == 0){//如果没有参数则直接返回return;}Object entity = args[0];//3.准备赋值的数据LocalDateTime now = LocalDateTime.now();//update_time的值Long currentId = BaseContext.getCurrentId();//update_user的值//4.根据当前不同的操作类型,为对应的属性通过反射来赋值if(operationType == operationType.INSERT){//新增操作为4个公共字段赋值try {//4.1通过反射获取这四个方法//使用常量类AutoFillConstant中的常量代替方法名,防止自己写写错Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//4.2通过反射调用获取到的四个方法为对象属性赋值setCreateTime.invoke(entity,now);//entity中存的是Employee//这行代码:使用entity对象调用setCreateTime方法,给方法传递参数nowsetCreateUser.invoke(entity,currentId);setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);} catch (Exception e) {e.printStackTrace();}}else if(operationType == operationType.UPDATE){//修改操作为2个公共字段赋值try {Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);setUpdateTime.invoke(entity,now);setUpdateUser.invoke(entity,currentId);} catch (Exception e) {e.printStackTrace();}}}
}

总结

1、创建枚举类,其中有插入、修改操作变量

2、创建自定义注解类,其中属性引用枚举类的变量

  • @Target(ElementType.METHOD)//指定当前的自定义注解只能加在方法
  • @Retention(RetentionPolicy.RUNTIME)//固定写法3、

3、在mapper层中的插入、修改方法上加入自定义注解,并通过属性指定其操作类型(插入或修改)

4、创建切面类,进行切入点表达式和通知的实现

  • @Aspect//设置当前类为切面类,告诉spring这个类是用来做AOP的
  • @Component//通知类(切面类)必须配置成Spring管理的bean

文件上传

利用阿里云实现文件上传功能,将文件上传并存储到阿里云存储空间,并返回文件的访问地址,以便在前端可以回显文件

一、在sky-common中的properties包下创建AliOssProperties类

@Component
@ConfigurationProperties(prefix = "sky.alioss")//将配置文件中sky.alioss的相关属性值赋给此类中的成员
@Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;//Bucket名称
}

 二、在sky-common中的utils包下创建AliOssUtil类

 此类实现upload方法,实现文件上传功能,此方法返回文件的访问路径

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;/*** 文件上传** @param bytes* @param objectName* @return*///将文件上传到阿里云并返回文件的请求路径//第一个参数:文件的字节数组,第二个参数:拼接uuid后的新文件名public String upload(byte[] bytes, String objectName) {// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {// 创建PutObject请求。ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}//文件访问路径规则 https://BucketName.Endpoint/ObjectNameStringBuilder stringBuilder = new StringBuilder("https://");stringBuilder.append(bucketName).append(".").append(endpoint).append("/").append(objectName);log.info("文件上传到:{}", stringBuilder.toString());return stringBuilder.toString();}
}

三、在sky-server模块下的config包中创建OssConfiguration类

       此配置类用于创建AliossUtil对象:实现aliOssUtil方法,此方法将AliOssProperties对象作为参数传入,方法内读取AliOssProperties中的四个属性,将其包装为AliossUtil对象返回,并将这个AliossUtil交给ioc容器管理,需要时可以直接依赖注入(注入的AliossUtil对象的四个属性已经赋过值)

       此类相当于一个中间媒介,关联AliOssProperties类和AliOssUtil,接收一个AliOssProperties并将其转换为一个AliOssUtil后返回,本质就是将AliOssProperties中从.yml中读取到的四个属性值赋给AliOssUtil中相应的四个属性

这四个属性的的去向总结为:

.yml(人为预先定义好四个属性的值)--->AliOssProperties类(利用注解从.yml中读取四个属性)-->OssConfiguration类(从类中方法接收的参数AliOssProperties对象中读取四个属性,并封装为AliOssUtil对象)-->AliOssUtil对象(OssConfiguration类中方法的返回值)

@Configuration
@Slf4j
public class OssConfiguration {@Bean@ConditionalOnMissingBean//保证整个容器中只有一个AliOssUtil对象public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);return new AliOssUtil(aliOssProperties.getEndpoint(),aliOssProperties.getAccessKeyId(),aliOssProperties.getAccessKeySecret(),aliOssProperties.getBucketName());}
}

四、在controller层中创建CommonController类

此类用来对前端文件上传的请求进行响应,前端传来一个文件参数

  1. 在此类中构造新的文件名称(uuid拼接原始文件名后缀)
  2. 调用AliOssUtil中的upload方法进行文件上传(方法参数为文件的字节数组和新文件名字符串)
  3. 上传方法返回值为文件的访问路径,将其封装为Result类型响应给前端
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {@Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* @param file* @return*/@PostMapping("/upload")@ApiOperation("文件上传")public Result<String> upload(MultipartFile file){log.info("文件上传:{}",file);try {//获取原始文件名String originalFilename = file.getOriginalFilename();//将原始文件名的后缀截取出来String extension = originalFilename.substring(originalFilename.lastIndexOf("."));//构造新文件名称(uuid拼接原始文件名后缀)String objectName = UUID.randomUUID().toString() + extension;//获取文件的请求路径String filePath = aliOssUtil.upload(file.getBytes(), objectName);return Result.success(filePath);} catch (IOException e) {log.error("文件上传失败:{}",e);}return null;}
}

总结

文件上传功能的核心为CommonController类和AliOssUtil类

  • CommonController类用来对前端请求进行响应,调用依赖注入的AliOssUtil对象的upload方法进行文件上传,并返回文件的请求路径
  • AliOssUtil类用来实现upload方法进行文件上传功能,实现的前提是已获取到四个属性的值
  • 剩下的AliOssProperties类和OssConfiguration类是用来创建AliOssUtil对象(将其四个属性赋值)并将其交给ioc容器(以便在CommonController中可以直接依赖注入)

相关文章:

Java项目——苍穹外卖(一)

Entity、DTO、VO Entity&#xff08;实体&#xff09; Entity 是表示数据库表的对象&#xff0c;通常对应数据库中的一行数据。它通常包含与数据库表对应的字段&#xff0c;并可能包含一些业务逻辑。 DTO&#xff08;数据传输对象&#xff09; 作用&#xff1a;DTO 是用于在…...

20240908 每日AI必读资讯

新AI编程工具爆火&#xff1a;手机2分钟创建一个APP&#xff01; - AI初创公司Replit推出的智能体——Replit Agent。开发环境、编写代码、安装软件包、配置数据库、部署等等&#xff0c;统统自动化&#xff01; - 操作方式也是极其简单&#xff0c;只需一个提出Prompt的动作…...

HNU-2023电路与电子学-实验3

写在前面&#xff1a; 本次实验是完成cpu设计的剩余部分&#xff0c;整体难度比上一次要小&#xff0c;细心完成就能顺利通过全部测评 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能&#xff0c;设计 8 重 3-1 多路复用器。 3.分析模型机的功能…...

html基础语法 看这一篇就够了!

HTML 一 概念 html:html 文件根标签 head:编写页面相关的属性 title:页面标题 body:页面内容展示信息 二 DOM 树&#xff1a; 所有的标签都是 html 的子标签 head 和 body 是兄弟标签&#xff0c;同一级别 head 和 title 为父子标签 1.第一个程序 <html><head>…...

【redis】redis的特性和主要应用场景

文章目录 redis 的特性在内存中存储数据可编程的扩展能力持久化集群高可用快 redis 的应用场景实时数据存储缓存消息队列 redis 的特性 redis 的一些特性&#xff08;优点&#xff09;成就了它 在内存中存储数据 In-memory data structures MySQL 主要是通过“表”的方式来…...

部署后端WebSocket服务到AWS云服务器

目录 1.创建AWS账户2.选择EC2实例3.配置EC2实例4.使用VSCode连接到EC2实例5.部署WebSocket服务6.配置域名和SSL&#xff08;可选&#xff09;7.监控和维护 1.创建AWS账户 如果你还没有AWS账户&#xff0c;你需要先在AWS官网注册一个。 2.选择EC2实例 登录到AWS管理控制台。搜…...

常见的集合

1、Collection 单列集合的根接口 遍历方法 Collection<String> c new ArrayList<>(); c.add("赵敏"); c.add("小昭"); c.add("素素"); c.add("灭绝"); System.out.println(c); //[赵敏, 小昭, 素素, 灭绝]//1、迭代器遍…...

Swift知识点---RxSwift学习

1. 什么是RxSwift RxSwift是Swift函数响应式编程的一个开源库&#xff0c;由Github的ReactiveX组织开发、维护 RxSwift的目的是&#xff1a;让数据/事件流 和 异步任务能够更方便的序列化处理&#xff0c;能够使用Swift进行响应式编程 RxSwift本质上还是观察者模式&#xff…...

驾驭不断发展的人工智能世界

从很多方面来看&#xff0c;历史似乎正在重演。许多企业正争相采用生成式人工智能 (Gen AI)&#xff0c;就像它们争相采用云计算一样&#xff0c;原因也是一样的&#xff1a;效率、成本节约和竞争优势。 然而&#xff0c;与云一样&#xff0c;GenAI 仍是一项发展中的技术&…...

冒泡排序——基于Java的实现

简介 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法&#xff0c;适用于小规模数据集。其基本思想是通过重复遍历待排序的数组&#xff0c;比较相邻的元素并交换它们的位置&#xff0c;以此将较大的元素逐步“冒泡”到数组的末尾。算法的名称源于其运行过程…...

Mendix 创客访谈录|Mendix赋能汽车零部件行业:重塑架构,加速实践与数字化转型

在当前快速发展的技术时代&#xff0c;汽车行业正经历着前所未有的数字化转型。全球领先的汽车零配件制造商面临着如何利用最新的数字技术优化其制造车间管理的挑战。从设备主数据管理到生产执行工单管理&#xff0c;再到实时监控产量及能耗&#xff0c;需要一个灵活、快速且高…...

船舶机械设备5G智能工厂物联数字孪生平台,推进制造业数字化转型

船舶机械设备5G智能工厂物联数字孪生平台&#xff0c;推进制造业数字化转型。在当今数字化浪潮推动下&#xff0c;船舶制造业正经历着前所未有的变革。为了应对市场的快速变化&#xff0c;提升生产效率&#xff0c;降低成本&#xff0c;并增强国际竞争力&#xff0c;船舶机械设…...

什么是jsonp请求

JSONP&#xff08;JSON with Padding&#xff09;是一种解决跨域请求问题的技术。它允许网页从不同的域名请求数据&#xff0c;而不受同源策略的限制。JSONP 通过动态创建 script 标签来实现跨域请求&#xff0c;因为 script 标签不受同源策略的限制。 一、工作原理 客户端&a…...

【C++】STL容器详解【上】

目录 一、STL基本概念 二、STL的六大组件 三、string容器常用操作 3.1 string 容器的基本概念 3.2 string 容器常用操作 3.2.1 string 构造函数 3.2.2 string基本赋值操作 3.2.3 string存取字符操作 3.2.4 string拼接字符操作 3.2.5 string查找和替换 3.2.6 string比…...

助贷行业的三大严峻挑战:贷款中介公司转型债务重组业务

大家是否察觉到一种趋势&#xff1f;现如今&#xff0c;众多贷款辅助服务机构与专注于债务再构的公司之间形成了紧密的“联动”。有的选择将获取的贷款需求转介给债务重组方&#xff0c;有的则直接下场&#xff0c;动用自身资本参与债务重组业务。这一现象背后&#xff0c;究竟…...

力扣第42题 接雨水

前言 记录一下刷题历程 力扣第42题 接雨水 接雨水 原题目&#xff1a;给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&…...

轻松录制每一刻:探索2024年免费高清录屏应用

你不会还在用一些社交工具来录屏吧&#xff1f;现在的市面上有不少免费录屏的软件了。别看如软件是免费的&#xff0c;它的功能比起社交工具的录屏功能来说全面的多。这次我就分享几款我用过的录屏工具。 1.福晰录屏大师 链接直达&#xff1a;https://www.foxitsoftware.cn/R…...

【小沐学OpenGL】Ubuntu环境下glfw的安装和使用

文章目录 1、简介1.1 OpenGL简介1.2 glfw简介 2、安装glfw2.1 直接命令二进制安装2.2 源码安装 3、测试glfw3.1 测试1&#xff0c;glfwglew3.2 测试2&#xff0c;glfwglad3.3 测试3 结语 1、简介 1.1 OpenGL简介 OpenGL作为图形界的工业标准&#xff0c;其仅仅定义了一组2D和…...

[数据集][目标检测]汽油检泄漏检测数据集VOC+YOLO格式237张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;237 标注数量(xml文件个数)&#xff1a;237 标注数量(txt文件个数)&#xff1a;237 标注类别…...

图文解析保姆级教程:Postman专业接口测试工具的安装和基本使用

文章目录 1. 引入2. 介绍3. 安装4. 使用 此教程摘选自我的笔记&#xff1a;黑马JavaWeb开发笔记16——请求&#xff08;postman、简单参数、实体参数、RequestParam映射&#xff09;想要详细了解更多有关请求各种参数介绍的知识可以移步此篇笔记。 1. 引入 在当前最为主流的开…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...