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中可以直接依赖注入)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AutosarMCAL开发——基于EB Gpt驱动

目录 1.Gpt原理2.EB配置以及接口应用2.1 EB配置2.2 接口应用 3.总结 1.Gpt原理 autosar GPT模块&#xff08;General Purpose Timer&#xff0c;通用定时器&#xff09;主要用于汽车ECU中的时间测量、计数和产生定时中断。它支持单次性和周期性定时器&#xff0c;可以在达到预…

Bitvise——进入服务器的快捷方式

第一步&#xff1a;在连接进服务器后&#xff0c;点击左侧的保存配置文件&#xff0c;保存至桌面。 第二步&#xff1a;将保存的配置文件&#xff08;后缀为 .tlp&#xff09;打开方式改为bitvise。 第三步&#xff1a;双击配置文件&#xff08;后缀为 .tlp&#xff09;&#…

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理&#xff0c;在有一定基础认识的前提下&#xff0c;通过阅读kubelet源码&#xff0c;对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管…

Android终端如何快速接入GB28181平台实现实时音视频回传

技术背景 GB28181是由中国国家标准委员会发布的基于IP网络的安防视频监控标准。Android平台GB28181设备对接模块&#xff0c;主要涉及到视频监控领域&#xff0c;可实现不具备国标音视频能力的 Android终端&#xff0c;通过平台注册接入到现有的GB/T28181—2016服务&#xff0…

Ifream实现微前端效果

记得有人曾问过我&#xff0c;老旧的项目内容很多&#xff0c;项目卡&#xff0c;想要改造成类似微前端&#xff0c;领导想要快速&#xff0c;又不想系统重构、而且是不同子系统的协同&#xff0c;要怎么做&#xff1f;对方不想做太大的改造&#xff0c;所以想用ifream的方式动…

如何打造高效办公楼物业管理系统?Java SpringBoot+Vue架构详解,实现智能化管理,提升工作效率

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

【全网最全】2024年数学建模国赛A题30页完整建模文档+17页成品论文+保奖matla代码+可视化图表等(后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片那是获取资料的入口&#xff01; 【全网最全】2024年数学建模国赛A题30页完整建模文档17页成品论文保奖matla代码可视化图表等&#xff08;后续会更新&#xff09;「首先来看看目前已有的资料&#xff0…

Bat的退役前

我们很讨厌bat 语法这版的命令形式后缀尽管古老&#xff0c;可是在涉及细微VS 项目op 时候&#xff0c;它起到了不可忽视且非它不行的效应 我们不想替历史背上厚重的学习包袱&#xff0c;可是我们能忽视BAT 吗 如若进入到 无window时代&#xff0c;我们几乎得全然依仗BAT专家。…

Hiredis的使用

Hiredis的使用 &#x1f4f8;这里安利一个github仓库介绍 图片生成 Socialify 一键生成专业 GitHub 仓库简介图 一、Hiredis的安装与使用 1、下载hiredis软件包&#xff0c; https://github.com/redis/hiredis.git 或者使用git下载到本地 git clone https://github.com/redi…

一文说清什么是数据仓库

01 数据仓库的概念 数据仓库的概念可以追溯到20世纪80年代&#xff0c;当时IBM的研究人员开发出了“商业数据仓库”。本质上&#xff0c;数据仓库试图提供一种从操作型系统到决策支持环境的数据流架构模型。 目前对数据仓库&#xff08;Data Warehouse&#xff09;的标准定义&a…

51单片机-DS1302(RTC实时时钟芯片)

数据手册在主页资源免费贡献 开发板芯片数据手册 https://www.alipan.com/s/nnkdHhMGjrz 提取码: 95ik 点击链接保存&#xff0c;

算法分享——《双指针》

文章目录 ✅[《移动零》](https://leetcode.cn/problems/move-zeroes/)&#x1f339;题目描述&#xff1a;&#x1f697;代码实现&#xff1a;&#x1f634;代码解析&#xff1a; ✅[《复写零》](https://leetcode.cn/problems/duplicate-zeros/)&#x1f339;题目描述&#xf…

Grafana 可视化配置

Grafana 是什么 Grafana 是一个开源的可视化和监控工具&#xff0c;广泛用于查看和分析来自各种数据源的时间序列数据。它提供了一个灵活的仪表盘&#xff08;dashboard&#xff09;界面&#xff0c;用户可以通过它将数据源中的指标进行图表化展示和监控&#xff0c;帮助分析趋…

Linux概述、远程连接、常用命令

Linux介绍 Linux操作系统介绍 Linux操作系统的特点 开源免费安全稳定可移植性好 Linux可以安装在不同的设备上 高性能 Linux的使用领域 应用服务器数据库服务器网络服务器虚拟化云计算嵌入式领域个人PC移动手机 Linux文件系统和目录 /&#xff1a;根目录&#xff0c;唯一/h…

flinkcdc 问题记录篇章

startupOptions 讲解 startupOptions 有三个参数initial、earliest、latest initial&#xff1a;因为binlog中不一定包含所有的数据&#xff0c;那么需要全表扫描所有的表&#xff0c;形成快照。常用于历史数据 earliest&#xff1a;从最早的变更日志开始读取&#xff08;仅增…

linux下进行lvm分区及扩容

目录 LVM存储管理介绍 lvm磁盘扩容有两种方式 创建lvm磁盘 1. 首先先加入第一块儿新的磁盘 2. 对新磁盘 /dev/sdb 进行分区 通过LVM命令创建新卷 1. 创建物理卷 2.创建卷组 并将物理卷加入其中 3. 创建逻辑卷并分配大小 4.格式化刚刚创建的硬盘 5. 挂载磁盘 扩容lvm…

第 2 章:AJAX 的使用

AJAX 的使用 核心对象&#xff1a;XMLHttpRequest&#xff0c;AJAX 的所有操作都是通过该对象进行的。 1. 使用步骤 创建 XMLHttpRequest 对象 var xhr new XMLHttpRequest(); 设置请求信息 xhr.open(method, url);//可以设置请求头&#xff0c;一般不设置 xhr.setReques…

开放式耳机音质好不好?盘点高音质的开放式耳机排行榜10强

开放式耳机音质好不好其实没有准确回答&#xff0c;因为开放式耳机也有其独特的优势特点。 由于开放式耳机的设计原因&#xff0c;所以如果将其与入耳式耳机相比&#xff0c;可能会在音质还原度以及降噪功能方面稍显逊色&#xff0c;当然开放式耳机的音质也并非很差&#xff0…

CAD二次开发IFoxCAD框架系列(26)- 分段测量多段线长度和计算多边形的面积

#region 分段测量多段线长度private static double textHight 10;[CommandMethod(nameof(PolylineDemo))]public void PolylineDemo(){using var tr new DBTrans();if(!tr.LayerTable.Has("标注")){tr.LayerTable.Add("标注",1);}var pso new PromptSel…

【Java】ApiPost请求返回 `406` 状态码(jackson)

Java系列文章目录 补充内容 Windows通过SSH连接Linux 第一章 Linux基本命令的学习与Linux历史 文章目录 Java系列文章目录一、前言二、学习内容&#xff1a;三、问题描述3.1 问题截图3.2 错误简介3.2.1 HTTP状态码 406 Not Acceptable3.2.2 序列化和反序列化 3.3 后端问题位置…