坦率的讲今天有点水,课也多,上了一天课,中午下课后和晚上十一点多跑完步回来写了两个接口
目录
我们的项目开发中会牵扯大量的数据表,而这些数据表中有一些重叠的字段,我们把他们叫做公共字段,例如菜品种类表和员工表里面都有修改人/时间 以及 创建人/时间 四个公共的字段,而且代码也基本一致,都是给对象赋值然后传递到mapper层进行数据库操作,而大量相似的代码会造成代码的冗余,因此我们对此方面进行优化:
优化前:
我们优化的思想是AOP思想
简单的来讲,就是把所有需要对这四个字段进行修改的方法提前进行拦截,在我们的 通知 中就对这四个字段进行赋值,然后再进行被拦截的方法。(由此可以看出我们这里的通知是前置通知)
拦截我们这里采用的方法是自定义注解,自定义一个方法注解,被该注解标记的方法会被拦截器拦截。
这里简单贴一部分代码:
使用AOP思想的好处就是我们在不改动源代码的前提下 实现了对目标代码的优化,这对于大型项目有很大的优点。
此外在这个方法中我还学到了两个注解:
1.@target注解
@Target 是 Java 注解中的一个元注解,用于指定注解可以应用的目标元素类型。它可以用来约束一个注解可以在哪些地方使用。@Target 注解包含一个 value 属性,其值是一个枚举数组,表示注解可以应用的目标元素类型。常见的目标元素类型包括:
2.@Retention注解
@Retention 是 Java 注解中的一个元注解,用于指定注解的保留策略,即注解在何时生效。它可以用来约束一个注解可以保留多长时间。@Retention 注解包含一个 value 属性,其值是一个枚举类型 RetentionPolicy 的枚举常量。
常见的保留策略包括:
这里的文件上传主要是图片文件,我们整体的思路是 利用阿里云OSS服务器,把图片上传到阿里云的OSS服务器后,利用后端接收OSS服务器返回的图片URL,然后再返回给前端,前端调用URL进行图片回显。
其实这个接口整体的思路很简单,没有什么创新的点,在这里我也简单的贴出来一部分代码:
在写这个接口的时候,我们把AliyunOSSutils 对象交给了IOC容器管理,并在实现方法中自动装配,实现了解耦
这里我介绍一下这个代码中给我启发性的两点:
1.使用UUID生成文件名
这里我们使用的OSS云服务需要给上传后的文件命名,而重复的命名会导致文件被覆盖,因此我们使用UUID工具类来生成一串随机数,把这个随机数作为文件名,这样文件就不会被覆盖。
2.不要把配置类写死
我们在配置类文件中配置aliyunOSS位置信息的时候,不要直接写死,应该写成这种格式(即让A配置类引用B配置类)
也就是说引用另一个配置类中的信息,这是因为我们的项目会经历开发,测试,维护三个阶段,而这三个阶段可能使用的数据库等等配置类不一致,因此我们不要在配置类中把配置类写死。
而是再写一个配置类,例如dev(开发配置类),让目标配置类引用开发配置类:
引用dev中的配置类
这样当我们切换环境的时候,直接修改active中的配置类就好了,而不用在配置类中一个一个修改。
什么叫做逻辑外键:
逻辑外键是在关系数据库中的一个概念,它是通过程序或规则实现的关联关系,而不是通过数据库引擎的外键约束来实现的。在逻辑外键中,没有在数据库模式中显式定义外键约束,但是应用程序或业务规则会处理相关的关联逻辑。
简单的说:逻辑外键就是在数据库中并没有使用外键的形式把两张表关联起来,而是在业务层用代码实现对表进行逻辑关系绑定。
通过反射来拿到一个类的方法
这个知识点的应用场景是公共字段填充功能,我们先贴代码再进行解释
我们利用连接点拿到了第一个参数(这里我们默认第一个参数就是需要进行字段填充的对象),而此时arg的类型并不明确,他可能是emplyee,也可能是category。因此我们无法直接用arg来调用对应的参数方法。
而这里我们的解决思路是利用反射
- Method setCreateTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
- Method setCreaterUser = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
- Method setUpdateTime = arg.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
- 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方法进行赋值,就完成了对象字段的填充
由此我们可以看出反射也是一个很高级的知识点,它使得我们能对未知类型的对象进行调用其类中的特有方法。
今天虽然实现的接口少,但是我的收获也很大,明天的课很少,打算一直在宿舍些项目了。写项目真的是一个很畅快的过程。
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!