• 【苍穹外卖 | 项目日记】第二天


    前言:

            坦率的讲今天有点水,课也多,上了一天课,中午下课后和晚上十一点多跑完步回来写了两个接口

    0f526593ea354ea69e92d64dcbf9e025.png

    目录

    前言:

    今日完结任务:

     今日收获:

    1.实现了公共字段填充功能

    2.实现了文件上传接口

    杂项知识点:

    总结:


     

     

    今日完结任务:

    • 实现了公共字段填充功能
    • 实现了文件上传接口

     今日收获:

    1.实现了公共字段填充功能

    我们的项目开发中会牵扯大量的数据表,而这些数据表中有一些重叠的字段,我们把他们叫做公共字段,例如菜品种类表和员工表里面都有修改人/时间 以及 创建人/时间 四个公共的字段,而且代码也基本一致,都是给对象赋值然后传递到mapper层进行数据库操作,而大量相似的代码会造成代码的冗余,因此我们对此方面进行优化:
    优化前:
    915dcc3c18c54bfe8e703660c970d638.png

    我们优化的思想是AOP思想

    【Spring知识点介绍 | 第二篇】什么是AOP_我是一盘牛肉的博客-CSDN博客

    简单的来讲,就是把所有需要对这四个字段进行修改的方法提前进行拦截,在我们的 通知 中就对这四个字段进行赋值,然后再进行被拦截的方法。(由此可以看出我们这里的通知是前置通知

    拦截我们这里采用的方法是自定义注解,自定义一个方法注解,被该注解标记的方法会被拦截器拦截。

    2dce00d4ef1840a99d49d6d1adb9705a.png

    这里简单贴一部分代码:
    be51070879cf49a9aaece593d8011697.png

    使用AOP思想的好处就是我们在不改动源代码的前提下 实现了对目标代码的优化,这对于大型项目有很大的优点。

    此外在这个方法中我还学到了两个注解:
    1.@target注解

    @Target 是 Java 注解中的一个元注解,用于指定注解可以应用的目标元素类型。它可以用来约束一个注解可以在哪些地方使用。@Target 注解包含一个 value 属性,其值是一个枚举数组,表示注解可以应用的目标元素类型。常见的目标元素类型包括:

    • ElementType.TYPE:可以应用在类、接口、枚举等类型上。
    • ElementType.FIELD:可以应用在字段上。
    • ElementType.METHOD:可以应用在方法上。
    • ElementType.PARAMETER:可以应用在方法参数上。
    • ElementType.CONSTRUCTOR:可以应用在构造函数上。
    • ElementType.LOCAL_VARIABLE:可以应用在局部变量上。
    • ElementType.ANNOTATION_TYPE:可以应用在注解上。
    • ElementType.PACKAGE:可以应用在包上。

    2.@Retention注解

    @Retention 是 Java 注解中的一个元注解,用于指定注解的保留策略,即注解在何时生效。它可以用来约束一个注解可以保留多长时间。@Retention 注解包含一个 value 属性,其值是一个枚举类型 RetentionPolicy 的枚举常量。

    常见的保留策略包括:

    • RetentionPolicy.SOURCE:注解仅保留在源代码中,编译时会被忽略。这意味着在编译后的字节码中不会包含该注解。
    • RetentionPolicy.CLASS:注解保留在编译后的字节码中,但在运行时不可见。这是默认的保留策略,如果在注解上没有明确指定保留策略,默认为 CLASS。
    • RetentionPolicy.RUNTIME:注解保留在编译后的字节码中,并在运行时可见。这意味着可以通过反射机制在运行时获取并解析注解信息。

    2.实现了文件上传接口

    这里的文件上传主要是图片文件,我们整体的思路是 利用阿里云OSS服务器,把图片上传到阿里云的OSS服务器后,利用后端接收OSS服务器返回的图片URL,然后再返回给前端,前端调用URL进行图片回显。

    其实这个接口整体的思路很简单,没有什么创新的点,在这里我也简单的贴出来一部分代码:

    37fd903b20ad40c4b8d9017b01087f15.png
    92961cb870b24cf293301937375be52c.png

     在写这个接口的时候,我们把AliyunOSSutils  对象交给了IOC容器管理,并在实现方法中自动装配,实现了解耦

    这里我介绍一下这个代码中给我启发性的两点:
    1.使用UUID生成文件名

    这里我们使用的OSS云服务需要给上传后的文件命名,而重复的命名会导致文件被覆盖,因此我们使用UUID工具类来生成一串随机数,把这个随机数作为文件名,这样文件就不会被覆盖。

    2.不要把配置类写死

    我们在配置类文件中配置aliyunOSS位置信息的时候,不要直接写死,应该写成这种格式(即让A配置类引用B配置类)

    96445c2f773a4c3fa802b98443d3593d.png

    也就是说引用另一个配置类中的信息,这是因为我们的项目会经历开发,测试,维护三个阶段,而这三个阶段可能使用的数据库等等配置类不一致,因此我们不要在配置类中把配置类写死

    而是再写一个配置类,例如dev(开发配置类),让目标配置类引用开发配置类:

    647de1af05f14f5a82d601bfcc9832c7.png

    引用dev中的配置类 

    18d4f435b03a4627ae9b5d6b8d0240a5.png

    这样当我们切换环境的时候,直接修改active中的配置类就好了,而不用在配置类中一个一个修改。

    杂项知识点:

    什么叫做逻辑外键:

    逻辑外键是在关系数据库中的一个概念,它是通过程序或规则实现的关联关系,而不是通过数据库引擎的外键约束来实现的。在逻辑外键中,没有在数据库模式中显式定义外键约束,但是应用程序或业务规则会处理相关的关联逻辑。

    简单的说:逻辑外键就是在数据库中并没有使用外键的形式把两张表关联起来,而是在业务层用代码实现对表进行逻辑关系绑定。

    通过反射来拿到一个类的方法

    这个知识点的应用场景是公共字段填充功能,我们先贴代码再进行解释

    f4acfe6e15004b149e5da9e1d82a005f.png

    我们利用连接点拿到了第一个参数(这里我们默认第一个参数就是需要进行字段填充的对象),而此时arg的类型并不明确,他可能是emplyee,也可能是category。因此我们无法直接用arg来调用对应的参数方法。

    而这里我们的解决思路是利用反射

    1. Method setCreateTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
    2. Method setCreaterUser = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
    3. Method setUpdateTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
    4. Method setUpdateUser = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, long.class);

    我们取第一条解释一下:

    首先,arg.getClass() 返回 arg 对象的运行时类,即获取到 arg 对象的类对象。接着,getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class) 是调用类对象的 getDeclaredMethod 方法,并传入两个参数。第一个参数是要获取的方法的名称,AutoFillConstant.SET_CREATE_TIME 表示要获取的方法名。第二个参数是方法的参数类型,LocalDateTime.class 表示要获取的方法的参数类型为 LocalDateTime。
    getDeclaredMethod 方法会返回一个 Method 对象,表示指定名称和参数类型的方法。如果找不到对应的方法,会抛出 NoSuchMethodException 异常。
    然后,将获取到的方法对象赋值给 setCreateTime 变量。

    而我们通过反射就拿到了类中的方法

    之后再利用invoke方法进行赋值,就完成了对象字段的填充

    1b48118919b141ddaab7bb7fe8e3a219.png

    由此我们可以看出反射也是一个很高级的知识点,它使得我们能对未知类型的对象进行调用其类中的特有方法。 

    总结:

            今天虽然实现的接口少,但是我的收获也很大,明天的课很少,打算一直在宿舍些项目了。写项目真的是一个很畅快的过程。

    如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

    69e9169c980f43e0aad31ff9ada88a9c.png

     

     

  • 相关阅读:
    根据文章段落内容自动插入图片php版
    【23种设计模式】装饰模式(九)
    Go数据结构队列
    网络电视机顶盒怎么样?内行揭晓网络电视机顶盒排名
    【java面试】Redis篇
    教程二 在Go中使用Energy创建跨平台应用 - 创建应用
    RunnerGo 支持UI自动化的测试平台
    一个WPF开发的、界面简洁漂亮的音频播放器
    最大值和最小值之差达标的子数组数量
    2、自然语言和单词的分布式表示(中)
  • 原文地址:https://blog.csdn.net/fckbb/article/details/133758671