苍穹外卖学习日志 -----20天项目从零到完结-----含软件下载,环境配置,框架学习,代码编写,报错处理,测试联调,每日总结,心路历程等等......

news2024/12/28 8:17:35

年份 2024         基础:Javase   Javaweb

已完结      2024    8.25---9.14    20天


Day-01      8.25

今天开始学习已经晚了,网盘下载了一下文件,做了一些开始项目的准备工作。

本来其实打算用notepad++来写学习日志的,但是那个传不了图片,而且编辑视图没有这个博客看着舒服,所以就决定写在这里了。往后,每日更新,直到项目完结,不知道会用时多久呢,希望20天以内吧,加油。

前置知识

百度网盘限速好烦啊,项目资料下载太慢了,所以项目工程导入可能要等到明天了,今天只能记一些知识点。

初始gitee

居然要用git了,之前只是听说过,有点激动呢,好耶!  原来工程里自带的.gitignore文件使用来指定不存入git仓库文件的,以前看着一堆文件好复杂,一下子清晰多了。

VCS:版本控制系统

            创建一个git远程仓库,选择项目的根目录层,也可以用命令创建仓库

原来IDEA也集成了这个,还以为要登录git来操作呢

注册gitee

注册了gitee,创建了仓库。顺便了解了下git,gitee,github,getlab的区别

刚刚网盘终于下载好了资料,但图书馆马上关门要走了,先部署了下前端界面。后端工程和上传git仓库明天再实践了。

部署前端页面

不能把Nginx文件放在带中文的目录下,怪不得刚刚一直打不开


Day-02      8.26

了解项目结构

终于打开了后端项目,类好多啊,要看不过来了

第一次推送项目到gitee

第一次项目登录测试

前后端联调测试登录到系统时遇到了报错,无法登录

原因:没有修改默认工程中配置的数据库连接信息,密码没有修改。修改配置信息后正常登录了。

Nginx反向代理

前端请求并不是直接发送到后端服务器,而是先发送到Nginx服务器,然后再由Nginx服务器发送请求到后端服务器。所以前端的请求路径和后端controller的接收路径是不一样的。

提高访问速度:大概是因为后端响应的数据会在Nginx做缓存,下次前端再访问相同路径的资源,就不用发送请求到后端,而是直接由Nginx直接响应给前端。

负载均衡

MD5加密

登录功能完善:对明文进行加密后存储

knife4j学习

使用介绍

代码实现

感受:

相比postman来说,确实有不少优势

               1.不用打开一个新的应用了,通过Spring框架,可以直接在浏览器访问界面

                2.更换数据进行测试时更方便,只需要输入数据值即可

          与Yapi的区别:

                       Yapi是设计阶段使用的,用于管理和维护接口

                        Swagger是在开发阶段使用的框架,帮助后端人员做后端的接口测试

生成接口文档的常用注解:

好处:1.可以用作代码解释,使代码可阅读性提高

            2.可以和生成的接口文档中的内容相对应,提高接口文档的可阅读性

全天总结:

今天还没有正式进入到开发阶段,算是把所有的前置知识完成了。明天开始进入开发阶段,希望进展可以快一点吧。感觉用了两天才完成前置内容的学习有点点慢,后面不能松懈了。

另:

刚刚发现博客可以添加标题,把每日的日期都设为标题,这样导航看起来方便多了哈哈。

        用剪映做了一个封面,默认封面有点丑,受不了哈哈。原来的是这样的。


Day-03      8.27

今日情况

今天开始写项目已经是下午八点了,本来可以早两个小时,但是趴桌子上不小心睡着了,睡了两个小时,可能是因为今天有点感冒。不说了,赶紧开始写接口了,看还来不来的及完成今天的任务。

开发体会

一个小细节:便于后期统一拦截请求,记录日志等等。

DTO用处

先设计新增员工的DTO:当前端提交的数据和实体类的属性差别较大时,建议使用DTO来封装数据。

        其实也可以直接用emplyee来封装接收数据,但是在开发中要尽量使用对应的DTO精确的做到前端传过来什么,后端就封装什么。

绿色注解

学会了生成绿色注解,快捷键是输如/**,然后点回车

又增加一个知识点

开启驼峰命名以后,在DAO层写接口的时候,就不用吧"_"改成大写字母了,会自动转换的

自定义常量

不得不说,用自己定义的常量来写代码,感觉好优雅,看着好舒服啊。

TODO用法

后续需要处理的任务用 TODO 标记,看着也赏心悦目,而且后期还可以直接定位,不会忘记。

测试代码

实际开放中大多Swagger进行测试,因为一般前端代码还没有开发好

在测试新增员工接口时,jwt令牌没有传递无法登录,可以设置全局参数,传递进去自己获取的一个jwt令牌,这样后续的测试就不会每次都会被卡住了。

参数名称为token,是因为我们再配置文件中,将前端传递过来的请求头中的参数名称设置为token

测试新增员工接口时,发生报错

猜测大概是mapper接口中的驼峰命名那块有问题

大概现在的版本不支持自动转换了,于是修改代码

修改后,利用接口文档测试通过

SQLIntegrityConstraintViolationException

在前后端联调测试中,输入的账号名称不小心填成了admin,结果遇到这个报错,记录一下

SQLIntegrityConstraintViolationException:

Duplicate entry 'admin' for key 'employee.idx_username'

经过翻译,大概意思是:键重复 报错,因为数据库中已经有这个用户名了,用户名有唯一约束

后续的测试就不再这么详细的记录了,遇到问题的话还是会记录一下的。

全天总结

今天大概只能写完这一个接口了,本来打算自己完成这个接口,但是代码写的不规范。跟着视频写了一遍,代码规范多了。后面习惯了这种书写规范后大概写接口就快了,加油。今天没有完成既定的任务量,看后面能不能多写点,给补回来吧,加油。

不过不得不说,还是学到了不少呢。

这种条理清晰的项目结构,简直太优雅了!忍不住感叹一下,我好喜欢!


Day-04      8.28

今天学了下Springboot原理。然后还有一些其他事情耽误了,

所以没有推进项目,明天继续吧,加油。

不过学习了一些Springboot原理之后,再去写项目,会感觉清晰很多。看到哪个都知道大概是什么是什么,对项目的理解也更深了。


Day-05      8.29

又没能写项目。只学完了之前web开发课程中  Springboot原理部分。


Day-06      8.30

新增员工完善

需求:新增员工时,如何记录操作员的id,信息。

用到的技术:ThreadLocal 

原理:向Tomcat服务器发送的一次请求,是在同一个线程中。

测试:在拦截器,Controller,servece中的获取的线程ID一致,结果如下。

ThreadLocal常用方法

当前项目已经做了一个工具类,直接调用即可。

新增员工业务代码完善完成

利用管理员账号添加数据,无误,推送代码

员工分页查询

mybatis的分页查询插件

业务代码如下

前后端联调成功

Pagehelper 的pageStart底层

就是用的ThreadLocal技术,将分页的参数存到ThreadLocal中,然后到动态sql的时候再自动帮我拼接上。但当然还有很多好处,使得代码简化了很多。

员工分页查询完善

存在问题:后端返回的最后操作时间是一个数组,前端展示的时候就少了标点

解决方案

采用方案二完成代码

联调测试成功

消息转换器

定义:     在 Spring MVC 和 Spring Boot 中,消息转换器(Message Converters)主要用于处理 HTTP 请求和响应中的数据序列化和反序列化。例如,当客户端发送一个 JSON 格式的请求体时,消息转换器会将这个 JSON 字符串转换成 Java 对象;同样,当服务端需要返回 JSON 格式的响应时,消息转换器会将 Java 对象转换成 JSON 字符串。

我的理解:     在消息发送前,也就是消息发给前端之前,会统一拦截消息,然后根据拦截器的配置来转换拦截到的信息。完成后再放行消息。     Spring会提供一个消息拦截器的集合,是List集合,存放所有的消息拦截器。     自己新增消息拦截器就要重写继承了web配置类的类中的方法extendMessageConverters。       新增的办法就是创建一个消息转换器对象,然后给其设置我们自己编写的对象转换器,再将其加入Spring的消息转换器队列,设置优先级为最高。

全天总结:

        已经开始三天了,课程中Day2的接口还没有开发完,后续需要调整一下时间安排了,否则这个项目会拖很久。得安排时间早中晚都有足够的时间去写项目才行。

        写代码时候也发现了很多残留的问题。最主要的就是mysql那块,基础不牢,虽然知道仔细学一遍肯定就没问题了,但是总是懒得去复习,导致写操作数据库那部分的代码时候,就得参考视频,不能独立完成,得尽快复习下mysql才行。


Day-07      8.31

修改员工账号状态

原本打算就写一条改statue 的sql,但是根据视频提示

可以考虑去一些更具有泛用性的sql语句。

写sql遇到报错

“应为 <statement> 或 DELIMITER,得到 'status'”

根据错误信息 “应为 <statement> 或 DELIMITER,得到 'status'”,可以推测生成的 SQL 语句中可能出现了类似 status 的标识符,但 MySQL 解释器期望的是一个 SQL 语句或分隔符。这可能是由于动态 SQL 生成过程中出现了问题。

全部变量都变红了,但代码肯定没问题,只好把注入语言给关掉试试 能不能运行。关掉以后展示如下:

测试没有问题,可能是一写其他原因吧。

编辑员工

在查询回写员工时看到一个细节

涉及到密码的地方,进行手动加密

编辑员工

代码越写越熟练了,用到了前面的BeanUtils和ThreadLocal

前后的联调测试通过

不过有一个疑问,这个路径参数问什么时long,而不是它的封装类,我记得之前好像说用封装类的好处很多,这里为什么不用呢?

回答:      在Spring MVC中,使用基本数据类型(如int, long等)作为路径变量时,如果传入的值不符合该类型的定义(例如为null或者无法转换为该类型),那么将会导致404 Not Found错误,因为基本数据类型不能为null

然而,当使用其对应的包装类(如Integer, Long)时,如果路径变量不能解析为正确的数值,则会返回null。这可以让你在控制器方法中更好地处理这种情况,例如检查是否为null然后采取适当的措施,可能是返回一个错误响应或者抛出一个异常。

总结:是我看错了,确实用的是大写的Long,是包装类,不过也解决了我的问题。

导入菜品分类代码

完成,测试通过


Day-08        9.1

今天是周日,休息了一天。


Day-09        9.2

不知不觉已经九月份了呢,昨天没有注意日期,本以为今天是九月一日,结果发现已经是九月的第二天了。项目的进度大不如预期,原本打算跟着视频的进度走,但是已经过去了八天,才完成视频进度中第二天的全部内容。至少得在九月前写完这个项目,但也用不了这么久吧,希望在九月中旬之前完成它。 

公共字段填充

AOP: 在操作持久层,调用mapper接口时,统一拦截需要自动填充的方法,然后自动填充。

             使用自定义注解的方式,来标记所有需要拦截的方法。

注解类

第一次见到这种写法,去查了一下

OperationType value(); 这种写法是 Java 注解(annotation)中特有的。在 Java 中,注解类型(annotation type)定义了可以附加到类、方法、字段等 Java 元素上的元数据的结构。这种写法定义了注解的一个成员(也称为注解元素)。

注解成员定义

在注解类型中定义成员时,通常遵循以下规则:

  1. 方法签名:注解成员看起来像一个方法签名,但没有方法体。
  2. 返回类型:注解成员必须具有一个返回类型,可以是基本类型、枚举类型、类类型、其他注解类型,甚至是这些类型的数组。
  3. 没有参数:注解成员通常没有参数列表。
  4. 默认值:可以为注解成员提供默认值。

枚举类

也是第一次见,Javase时候好像没学

方法签名

这个以前也鲜有听说,记录一下。

在Java中,方法的签名(method signature)是指方法的名称、参数列表以及返回类型(有时还包括异常列表)。具体来说,方法签名由以下几部分组成:

  1. 方法名称:标识方法的名字。
  2. 参数列表:包括参数的类型、顺序和数量。
  3. 返回类型:方法执行后返回的值的类型。

在某些上下文中,方法签名还包括方法的异常列表,即方法声明中抛出的异常类型。

方法签名的重要性

方法签名在Java中非常重要,主要用于以下几个方面:

  1. 方法重载(Overloading):在同一类中,多个方法可以有相同的名字,只要它们的参数列表不同即可。这意味着方法签名必须唯一。
  2. 方法调用:在调用方法时,虚拟机根据方法签名找到正确的实现。
  3. 反射:在运行时通过反射访问方法时,需要知道方法签名才能正确调用。

有关向下转型的一些疑问

疑问:    MethodSignature signature = (MethodSignature) joinPoint.getSignature(),把方法进行向下转型,是因为父类不具有 子类的某些特有方法,只有转为子类才可以调用这些方法吗

回答: 

 是的,将 joinPoint.getSignature() 的结果向下转型为 MethodSignature 类型,是因为 Signature 接口是一个泛型接口,它提供了方法签名的基本信息,但并不包含所有方法相关的信息。而 MethodSignature 类实现了 Signature 接口,并提供了更多与方法相关的细节,包括方法对象本身、参数类型等。

疑问:     向下转型是必要的吗,为什么设计方法的时候,不直接返回子类型的对象呢?

回答:

在设计 JoinPoint 接口的 getSignature() 方法时,返回 Signature 接口而不是直接返回 MethodSignature 类型的原因主要是为了灵活性和通用性。以下是几个主要原因:

1. 通用性

Signature 接口是一个通用接口,它可以表示多种类型的签名,不仅仅是方法签名。例如,它还可以表示构造函数签名、字段签名等。因此,getSignature() 方法返回 Signature 接口,这样可以适用于多种类型的签名。

2. 多态性

Java 中的多态性允许我们编写更灵活的代码。通过返回 Signature 接口,我们可以编写更通用的代码,而不需要关心具体的签名类型。在运行时,我们可以根据具体的需求进行类型转换,从而获得所需的信息。

3. 扩展性

通过返回 Signature 接口,未来的扩展变得更加容易。如果将来需要支持新的签名类型(例如新的语言特性),只需要实现 Signature 接口并提供相应的方法即可。这样,现有的代码无需修改即可继续工作。

4. 类型安全

虽然返回 Signature 接口可能会导致在使用时需要进行类型转换,但这实际上也是一种类型安全的保障。通过显式的类型转换,我们可以确保在使用 MethodSignature 时确实是得到了一个方法签名对象,而不是其他类型的签名对象。这有助于避免运行时错误。

对第二行代码的详细解释

  1. signature 对象:这是从 JoinPoint 对象获取的方法签名信息。signature 实际上是一个 Signature 接口的实现,这里通过向下转型为 MethodSignature 类型来获取更多方法相关的细节。

  2. getMethod() 方法MethodSignature 类提供了 getMethod() 方法,该方法返回一个 java.lang.reflect.Method 对象,该对象代表了被拦截的具体方法。

  3. getAnnotation(Class<T> annotationClass) 方法Method 对象提供了 getAnnotation 方法,该方法用于获取指定类型的注解。传递给 getAnnotation 方法的是一个 Class 对象,表示我们想要获取的注解类型

将方法添加到异常签名列表和用try catch包围有什么区别

区别总结

  1. 责任划分

    • 异常签名列表:方法声明了可能抛出的异常,调用者负责处理这些异常。
    • try-catch 块:方法内部处理异常,调用者无需关心这些异常。
  2. 代码复杂度

    • 异常签名列表:增加调用者的复杂度,需要处理或重新声明异常。
    • try-catch 块:减少调用者的复杂度,但可能增加方法内部的复杂度。
  3. 透明性

    • 异常签名列表:调用者明确知道方法可能抛出的异常,增强了透明性。
    • try-catch 块:调用者可能不知道方法内部的异常处理逻辑,降低了透明性。
  4. 耦合度

    • 异常签名列表:增加了调用者和被调用者之间的耦合度。
    • try-catch 块:减少了耦合度,但可能导致方法内部逻辑更加复杂。

适用场景

  • 异常签名列表:适合于那些需要调用者显式处理的异常,特别是那些需要业务逻辑层面处理的异常。
  • try-catch 块:适合于那些方法内部可以自行处理的异常,或者那些不需要调用者特别处理的异常。

选择哪种方式取决于具体的业务需求和设计考虑。在实践中,通常会结合使用这两种机制来达到最佳的效果。

前后端联调测试

问题:updateuser在修改和创建员工时都赋值失败。

解决:

检查mapper 层自定义注解,全部添加了,没有问题。

检查AOP方法,发现反射调用SetUpdateUser时,传递的参数错了,导致赋值失败

修改如下:

再次测试:  数据库修改成功

文件上传

出现报错

大致猜测:id为空,可能阿里云的秘钥之前没用删掉了   但查询后发现没问题

                  那就应该是依赖注入的时候没注入成功

检查配置类如下

返现原始代码中,前缀如下

重新调整配置类结构

还是报错,仔细检查发现还是写错了,因为我配置本来是粘贴的之前代码,所以没注意

测试成功:

虽然图片没加载出来,但是确实上传成功了。

其实好久没复习文件上场都有点忘了,现在回忆一下刚刚好,又记起来了。

新增菜品

获取插入菜品后主键id的值

在sql语句中配置两个参数值   使用主键id   将id封装到对象的id中

@Tran

一个业务逻辑中要给处理多张表时

前后端联调测试

报错 UnsatisfiedDependencyException

搜索可能得错误来源

org.springframework.beans.factory.UnsatisfiedDependencyException 是 Spring 框架中的一个异常,它表明 Spring 容器在装配 Bean 时无法满足某个依赖关系。这通常是因为容器找不到所需的 Bean 或者在创建依赖 Bean 时遇到了问题。

排查半天无果,突然想起来,自己刚刚给新增菜品的mapper接口写xml文件后,忘记删@inset注解了,删掉以后运行正常。

报错  BindingException

介绍:  

org.apache.ibatis.binding.BindingException 通常表示在 MyBatis 中存在绑定错误,例如参数绑定不正确或 SQL 语句中的参数引用不存在等问题。

查找发现,是xml映射文件中 value值没有正确传输

修改后,前后端联调,报了一个未知错误,是显示在前端页面的。

发现去掉添加口味以后,报错消失。

查找半天,几乎要崩溃了!!!!!!!!!!!!

最后发现是在添加菜品Id到口味列表时,把setDishId,误写成了setID,修改正确后如下

联调测试圆满成功,加入了两个我爱吃的菜,嘻嘻

全天总结

今天用于写代码的时间,比以往多了很多,但是进度还是赶不上视频的日期进度,今天只完成了视频中Day3的一半,最多三分之二,但估计也就是个一半吧。

继续加油吧,希望后面熟练以后,可以写的快一点。目前经常被一些小错误耽误时间。


Day-09        9.3

菜品分类查询

第一次写查询语句用到左外连接,还有起别名。蛮新奇的,以前学过但已经忘得差不多的知识突然有了用处,感觉还是蛮奇妙的。  根据创建时间降序排序,这个倒是见过,算是复习了。

这是目前为止我写过最复杂的一条sql了哈哈。

测试发现有问题,提示码400,排查中

Result type not match for select

报错全名 :       Result type not match for select id=&quot;pageQuery&quot;<br/>srcType:<br/>targetType: com.sky.vo.DishVO

他mapper接口一直报这个错,不明所以

错误原因:              这个错误信息表明,在使用 MyBatis 执行查询时,返回的结果类型与你期望的结果类型不匹配。具体来说,错误提示指出在执行 ID 为 "pageQuery" 的查询时,返回的结果类型与 com.sky.vo.DishVO 类型不一致。

大概是没有指定返回类型吧,一般语句都不用制定的,但可能复杂一点的要指定,他表的字段对应的是Dish对象,我这次返回需要的是DishVO,所以可能需要再slect标签写明返回值类型。

修改后报错消失

HttpMessageNotReadableException

报错全称:

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.sky.result.Result<com.sky.result.PageResult> com.sky.controller.admin.DishController.page(com.sky.dto.DishPageQueryDTO)]

报错分析:            

org.springframework.http.converter.HttpMessageNotReadableException 异常通常发生在 Spring MVC 或 Spring Boot 应用中,当控制器方法期望从请求体中读取数据,但请求体中没有提供数据或者数据格式不符合预期时。

错误信息 “Required request body is missing” 表明控制器方法期望从请求体中读取一个 DishPageQueryDTO 对象,但实际上请求体为空或格式不正确。

解决方案分析:    感觉可能是前端的问题,先用Swagger测试一下试试

使用postman测试,发生报错ReflectionException

ReflectionException

org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'category_id' in 'class com.sky.dto.DishPageQueryDTO'

推测:      数据库的字段名和实体类属性对应错误

是这里写反了,修改如下

修改后查询通过,但是没查到数据

怀疑是sql代码存在问题,因为视频是几年前的了,sql语法可能会有一些变化

修改如下

前端还是一直不能测试成功,依旧是这个异常HttpMessageNotReadableException

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.sky.result.Result<com.sky.result.PageResult> com.sky.controller.admin.DishController.page(com.sky.dto.DishPageQueryDTO)]

就在我快要被这个异常折磨 疯掉的时候,我检查代码突然发现我在DishPageQueryDTO对象前面多加了一个@Requestbody,这个纯属是写习惯了,但好像就是错在这里。

修改后,前端查询成功,噗,这就是基础掌握不好的原因了。

@RequestBody 详解

控制器方法中存在一个问题:@GetMapping 注解与 @RequestBody 注解的组合不合理。@GetMapping 通常用于处理 GET 请求,而 @RequestBody 通常用于处理 POST 请求中的请求体数据。

问题分析
GET 请求与请求体:
@GetMapping 用于处理 HTTP GET 请求,这种类型的请求通常不包含请求体数据。
@RequestBody 注解用于从请求体中读取数据,这通常用于 POST 请求。
请求体数据:
如果你想在 GET 请求中传递数据,通常使用 URL 查询参数(如 ?param=value)而不是请求体。

对于 GET 请求:使用 @GetMapping 并通过查询参数传递数据。
对于 POST 请求:使用 @PostMapping 并通过 @RequestBody 从请求体中读取数据。


呼,要死了,但是还得继续,花费了将近3h,总算结束了这一个接口。

好无语啊!


删除菜品

嘶,看着有点小烦,麻烦。休息一会儿吧,有点累了。

呼,没想到删除一个菜品还这么复杂的业务逻辑,好歹是 写完了

前后端联调测试

删除了我喜欢的大盘鸡,本来是起售状态,但是由于起售停售功能还没开发,就直接去数据库修改状态了,然后删除,就成功了。

完美收官!!

修改菜品

呼,刚写完删除菜品,好累,休息一会会。


Day-10        9.4

呼,不小心休息到第二天了

根据id查询菜品

写业务层代码时候发现持久层已经有这个方法了,但是用不了,点过去才发现,原来是之前写,删除菜品的时候,需要查询起售状态,所以写过一条 sql了

当时视频里,写的是查询全部字段,返回一个Dish对象,我还想着为什么不直接只查询状态,原来是为了增加接口的泛用性,现在是深有体会啊。

独立开发完毕,联调测试时,只有口味没有显示

嘶,方法忘传参数了,怪不得。修改后,查询成功。

增加一个小细节:不需要改表的操作,不用开事务管理

修改菜品

修改口味的sql想了半天,感觉问题比较多,不太好实现

去看视频,发现采取了一种最最最原始的方式,噗,好玩哈哈哈

修改口味 = 删除所有该菜品的原始口味 + 添加新增的口味

独立开发,测试成功

出现重大失误,导致测试出现问题,修改菜品一直未知错误

原因:没有在自己写完接口以后仔细对照视频检查,导致代码出现bug,耽误很多时间

1.数据传输用的DTO,我写成了VO

2.新增口味时,忘记给新增的口味传递菜品id的值了

总结:

完成,今天到此结束了,视频中Day3的接口全部完成了。

本来应该再多写点的,但是今天还要复习大物,明天有个补考。

以后对照视频检查代码的时候要仔细才行啊。项目越大,越是不能出一点点错,差了点逻辑 就要报错,报错还很难自己找bug。


Day-11        9.5

Client      客户端,所以对应英文缩写为   cli

第十一天,Redis ,启动!

Redis入门

首先,配置文件,搜pass ,设置一个密码,redis默认没有密码

设置密码以后,不输入密码就连接的话

提示:需要 NOAUTH 认证

原来这里需要打开两个命令行窗口,一个用于连接服务,另一个用于连接客户端。前面没有看清楚,浪费了好多时间。

unknown command 'key'   错误命令

成功密码连接

图形化界面的使用也需要先启动redis服务

Redis常用数据类型

Redis常用命令

Redis 的 Java客户端

Spring Date Redis

全天总结: 

今天由于还有些其他事情,所以学习的就到这里为止了,不多,但还好,本人可以接受。


Day-12        9.6

今天调整了一下壁纸和桌面布局等等,花费了不少时间,预计学习时间也不会太多,但是很值得,现在的桌面太好看了,心情愉悦啊。

修改店铺状态

接口文档分类

需求:根据用户端和管理端,生成两份接口文档,便于查找和测试。

嘶,本来刷新半天不好,还以为是代码出错了,感谢红字大佬。

视频中Day-5完结!

HttpClient

测试成功


Day-13        9.7

微信小程序

开发流程

打开程序

查看Ngix 端口号

目录:

E:\nginx-1.26.1\skyTakeaway-Nginx\nginx-1.20.2\conf

微信小程序代码导入

测试成功。但接口还没写,所以报错了。

微信登录

突然发现一万五千行,地址信息,嘶,水代码行数啊。

配置文件为什么两份

配置文件为什么要分两份的原因找到了,一份只是引用,另一份实际保存配置信息


Day-14        9.8

微信登录测试

报错

解决

再修改

再修改

测试通过

拦截器配置复习

定义用户拦截器类

注册,配置拦截器

管理端套餐相关代码导入

嘶,这个都隔了好久了,再加上现在学到了用户端,都有点点乱套了。不过还好还好,仔细梳理了一下,才把代码正确的导进去。

真的,一下子导入好多代码,而且代码有点点乱套,导入进去以后,真的心里一点谱都没有,再加上一次性修改了这么多代码,都不知道该的是哪个代码了,就怕一报错,整个代码都得从新来过。

怀着忐忑的心去测试,结果通过了!!

呼,还好我之前学的扎实,要是弄不明白这项目结构什么的,还真要栽在这里了。

新增套餐,查询套餐测试无误

起售,停售套餐测试无误

修改套餐无误

小程序页面展示测试无误

添加购物车失败,这是后续课程代码了

呀呼,阶段性大胜利!

好啦,今天到此为止啦,本来周天是休息的,但是由于昨天没写多久代码,所以今天加个班。

呼,顶着巨大的压力,还完成任务的感觉太好了。

开心开心开心。

哇哇哇

呀呀呀呀

耶耶耶耶

哈哈哈哈


阶段胜利,开心,庆祝,撒花!



Day-15        9.9

今天开学了,后续的项目时间肯定受到影响,不过我会尽力客服的。

今天争取完成视频Day-7的内容。

缓存菜品,套餐

序列化器相关

Redis 的 SET 命令本身并不直接支持对象的序列化。当你使用 Redis 的客户端库(如 Jedis、Lettuce 等)在 Java 应用程序中与 Redis 交互时,通常需要手动处理对象的序列化和反序列化。

Redis 的 SET 命令
Redis 的 SET 命令用于将键值对存储到 Redis 中。它接受一个键和一个值作为参数,并将值存储为字符串形式。这意味着你不能直接将 Java 对象存储到 Redis 中,而是需要先将对象转换成字符串或其他可存储的格式。

一些 Redis 客户端库提供了内置的支持,可以在一定程度上自动化这个过程。例如,Spring Data Redis 支持序列化器配置,可以自动序列化和反序列化对象。

注意事项
虽然 Spring date base 的默认序列化器是    JdkSerializationRedisSerializer 很方便,但它也有一些缺点:

序列化效率:Java 的序列化机制相对较慢,特别是在处理大量数据时。
序列化格式:序列化后的字节数组通常较大,占用较多内存。
兼容性:序列化后的字节数组在不同 Java 版本之间可能不兼容。
因此,在生产环境中,你可能会选择其他更高效的序列化库,如 Jackson、Gson、Kryo 或 Protocol Buffers 等,以提高性能和减少存储空间的占用。

我们项目中,将其序列化器改为了一个课程附带的字符序列化器。

通过序列化器,就可以自动对传入的java对象进行序列化,转为字符串类型,然后存储到redis当中。

缓存菜品测试

性能对比

在起售删除缓存的代码部分,突然发现我的起售停售菜品接口没写,立马写了一个。

因为mapper接口的修改菜品是动态sql,所以只需要写到service层的代码,调mapper接口就行。

一次搞定

Spring Cache

框架优势

这个框架提供了一系列的注解,简化代码。且支持多个非关系型数据库。

常用注解

@EnableCaching  注解使用

介绍:加到启动类上,用于开启缓存注解功能

@CachePut 注解使用

注解中key参数的写法很灵活,用的是spEL 表达式,

                            有多种方式可选,优先最直观的第一种即可

 @Cacheable 使用方法

细节:  如果查到有缓存,则根本不会执行下面的方法。

             如果没有缓存,则会通过反射调用下面的方法,把返回结果,即案例中的user缓存到

              redis的缓存中,key的名就是已经通过前面的代码生成好的key

注意:这个注解中,参数key的 spEL表达式参数没有result的写法了,

                具体的可以查看源码中的注释

@CacheEvict  使用方法

删除一个拼接后的key,删除的参数列表和上述方法类似。

删除所有缓存,参数列表加一个allEntries参数

Redis    key的树形目录结构

简介:Redis中的key也是可以树形展示的,

            虽然key本身都是单独存储的,但是在展示界面可以树形结构展示。

目录分隔标准:以冒号为分隔,就是 :这个冒号。

如果有两个冒号,中间会多一个Empty包。

刚刚完成了一篇关于Spring Cache 的文章,花了不少时间,距离今天的目标还差不少呢,以及晚上十点了,回宿舍再写写代码吧那就。

缓存套餐

代码逻辑梳理

用户端:  查询套餐的时候缓存数据

管理端: 增删改的操作时候,删除缓存数据

测试

缓存数据库正常

性能对比

日志输出正常

添加购物车

报错:无法自动装配

原因:           自动装配Bean,没有依赖注入成功。

               Mapper接口没加@Mapper注解,但本质上还是没有加@Compont注解。

搞定!

只是一个不起眼的错误,但一下子让我更理解了自动配置,依赖注入那些知识。

添加购物车

 这是迄今为止遇到过逻辑最复杂的一个接口了!!!

接口测试:

前端请求发送成功

控制台正常

数据库数据插入成功

查看购物车

业务逻辑比较简单,独立开发完毕。

接口测试

小程序显示无误,请求发送正常

后端控制台日志正常

最后一个接口了,好困,2:40了,写完再睡吧

清空购物车

逻辑简单,独立开发完成。

测试:

小程序页面显示正常,请求发送成功

后端控制台日志正常

没有单个删除的接口?

我就说怎么没有一个一个删的接口,原来有这个接口,只不过是 后面的代码了

点击减号还是有日志记录的

全天总结

此时已经凌晨三点了,我居然在宿舍里凌晨敲了三个半小时的代码,真离谱啊。

我靠,但是好开心啊,今天完成了视频里一整天的课程量。

突破突破啊。

重大突破!!!

激动,好困,但还是非常激动!

耶耶耶耶耶耶耶!

啊啦啦啦啦啦啦啦~

再接再厉,加油加油。


Day-16        9.10

这个git警告是什么意思

删除购物车单条数据

难点分析:

 在删除数据时,要考虑到这个数据的数量,大于1则数量-1,等于1则之间删除数据

独立完成代码实现

接口测试

小程序界面显示无误

后端控制台日志正常

地址簿代码导入

业务介绍:

导入完成

测试无误

用户下单

业务介绍

数据库设计

不得不说,这个orders表的字段是真的多啊!

有意思的弹幕

代码实现

最复杂的逻辑又更新了。。。。。

测试

写完代码累死了,都不想测试了。

万一测试出错了还得改,呜呜,好累。

呼,还好正常启动了

新建地址,设为默认成功

小程序界面显示正常

最后点击去支付,无反应,可能是代码还没写

支付功能

前置知识

微信支付时序图的关键步骤

微信下单接口简介 (预支付)

预支付结果返回给商家后,商家再进行签名(确保数据安全),然后返回结果给用户确认支付

然后用户界面就会弹起微信支付窗口

微信支付介绍

商户端需要调用的接口

小程序端需要调用的接口

微信支付功能实现

两个需要考虑的问题:

        1.调用过程如何保证数据安全

        2.微信后台如何调用到商户系统

调用过程如何保证数据安全

微信后台如何调用商户系统

运行以下命令,就可以获得一个临时域名

我运行获得的临时域名

                                                                临时域名成功打开接口文档

微信支付配置项

后面的流程解析大概看了一下,还行,虽然不能准确的知道每个细节,但是大概流程还是明白的。

不用了解太具体,到此为止吧,提交代码的时候也没有报错。

视频Day-8 代码 全部完成

现在是晚上9点,提前完成任务了。一会儿做点什么呢......


Day-17        9.11

昨晚什么也没做,玩了一会儿,十一点半就睡觉了。

百度地图服务账号创建

先创建了百度地图的账号,因为后面的代码要用到这个功能,但是居然要等三天吗?

希望尽快申请成功吧

取消订单

难度:  简单

代码:

各个状态的订单数量统计

难度:简单

问题:就是业务层代码,不知道能不能一次统计全部的 三个状态数据

                聚合函数倒是想到了

代码:

完成订单

难度:简单

代码:

拒单

难度:简单

代码:

修改一下

接单

难度:简单

代码:

查询订单详情

难度:中等

代码:

派送订单

难度:简单

代码:

订单搜索

难度:困难

        说实话,代码有点多,而且逻辑和我想的差一些,后面的两个补充的方法都直接copy了

代码:

管理端代码全部完成!

报错

错误

修正

管理端代码测试:

成功,但是插入数据太麻烦了,就没插入数据

用户端代码导入

修改完成

测试

总结

        虽然最后水了用户端的代码,但是其实逻辑都差不多,还好还好。

        今天也是写了不少代码,果然自己一个人写起来,还是会碰到一些问题,不过最后还是在写好的项目代码帮助下完成了设计开发。

        嗯,最近都保持的不错,每天可以学完视频里一整天对应的内容。中秋节放假时候,去长城玩玩吧,还不知道能不能去成,到时候再说吧哈哈。


Day-18        9.12

待完成任务

对了,昨天的百度地图接口优化原接口还没写。后面得学着写一下。

Spring  Task

用处

可以实现一些定时处理功能。

                如,支付界面过时以后,自动把订单状态改为已取消。

                       订单派送成功后,一定时间内,自动把订单状态改为已完成。

介绍

cron表达式

作用:用于设置任务的触发条件。

案例:

使用方式

这是一个很小的框架,都没有自己的jar包。可怜呢。

主要的工作就是写,自定义定时任务类。

超时自动处理任务  功能开发

实现方式

因为不需要发送请求,所以就不用设计接口了,定义一个定时任务类,直接操作数据库就行了。

代码实现

想想,居然还是第一次在项目sql中用到 <  这个条件匹配符

功能测试

报错

测试成功,一个小问题

发现一个小细节:   

        在处理任务时候,不用jwt校验,因为只有前端发动的请求才会被拦截器拦截,而这个是直接操作数据库。

WebSocket

介绍

作用

客户端浏览器和服务端进行双休数据传输,向浏览器推送消息。

        实现,客户催单,来单提醒等功能。

WebSocket 与 Http  协议对比

应用场景

请求方式

实现步骤

来单提醒

需求分析

实现逻辑

代码开发

需要注入对象,websocket服务对象

功能测试

报错

原因: 网络服务连接错误,排查一下去

管理端连接没问题

之前这里没配置,刚刚配置好以后,小程序端有页面了,但是访问服务端数据失败

我知道为什么小程序没有响应了,和那个报错没关系

是我当时把这个配置给配置上了

但是对应的配置类面下面这个代码我是注释掉的。所以小程序报错了。

之前的话两段代码都是注释的,所以正常运行。

而这个数据库查不到,只不过是因为没有启动Redis服务

启动redis后,下程序没问题了

但我这个小程序还是无法  去支付

看了下信息

提交不到请求,是不是因为这是个POSTMapping

因为没办法支付,所以直接后台修改了订单状态。

因为没有订单支付这个功能,所以直接把这个提醒消息又写到了管理端的接单逻辑下面做测试。

测试通过!!! 有铃声,而且有提示信息!!!!

催单测试

原来只有待接单的订单才能催单啊,我找了半天没找到按钮在哪里,服啦!

不过,有铃声,有提示,测试成功!

测试注意事项

别忘了获得一个公网IP,以便服务端可以给你的浏览器响应数据。用cplor那个软件。

然后配置 那个回调地址

 

啧啧啧,不过我们好像不用,这个是需要微信支付成功才需要回调,如果没有支付功能的话,就不用管这个也行。

果然测试过了,不用什么公网IP,都行,只要代码正确就行,不调用微信支付的接口的话,以上注意事项都不用管了!!!!

全天总结

        今天也是凌晨学了三小时,才完成今天的任务。不错不错,继续努力。好困啊,都懒得写了。总之今天的测试本来很崩溃的,花了好多时间,不过一下子测试了很多功能,通过的时候也很开心哈哈哈。睡觉睡觉,已经凌晨三点了。


Day-19        9.13

Apache Echarts

作用

             数据统计,展示报表。

示例:

介绍

总结

营业额统计

需求分析设计

接口设计

代码开发

测试

不报错,但也没有绘制好的表格

报错原因: controller的地址写错了

修改后

是动态sql少了一个and关键词,修改后,测试成功

用户统计

独立开发完成   

测试一次成功,哈哈哈!

销量top10

代码导入

 订单统计

代码导入

数据统计功能总测试

管理端显示正常

控制台正常


Day-20        9.14

工作台模块

工作台代码导入

完成

工作台测试

没有问题

Apache POI

介绍


应用场景

Excel写入文件

Excel读取文件

导出数据Excel报表

需求分析和设计



模版文件

为了避免用代码直接写文件版式过于复杂。

会创建一个模版文件,先读取数据,再像表格写入数据。

代码实现

测试

报错

解决了,少了文件名后缀,改进后如下

测试成功,联动上了哈哈,文章里的文章

这个营业额导出的有问题,只有13号那天数据是对的,但是排查代码逻辑,没有找到错误。

算啦,不管了,也不是什么大问题。

刚小程序下了个订单,246,今天就只有这一个订单。但是它写的今日数据却是754,是总营业额

大概知道问题了,就是统计每日数据的那个接口写错了。

检查了,但是没有问题啊,每日营业额统计的代码。

OK,就到这里了,完工!

最后一次提交推送代码


万千感慨

        其实,多少感觉有些不可思议。

        在开始项目之前,曾觉得这个项目这么大,要写到猴年马月啊。  但是又踌躇满志想着20天就要搞定它。

        刚开始的十天左右进度很慢很慢,想着20天肯定完成不了,甚至想着在10月之前把它给写完都觉得已经很不错了。

        今天是9.14 ,就在刚刚完成了最后一部分的代码。没想到居然刚刚好20天,感慨万千啊。

        此时的开心如此的真切,难以言表,我永远也不会忘记。

        lyf,我爱你。

        但,长路漫漫,还需上下求索,加油。

        最近有喜欢尼采的一句话,就用来结尾吧。

        我该如何获得成功?    放弃思考,努力攀登。

       -------------------- 就此搁笔,以上与君共勉,祝乘风破浪,所愿皆所得。----------------------------

       

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何给bat文件替换好看的图标

最近遇到软件运行在Windows系统&#xff0c;通过bat文件启动&#xff0c;但是bat文件的图标不好看&#xff0c;而且作为启动快捷方式放桌面看上去跟其他软件不搭调&#xff0c;于是得给bat文件换个软件图标。 软件ico图标 Windows系统下使用.ico文件作为软件图标。另外favicon…

go libreoffice word 转pdf

一、main.go 关键代码 完整代码 package mainimport ("fmt""github.com/jmoiron/sqlx""github.com/tealeg/xlsx""log""os/exec""path/filepath" ) import _ "github.com/go-sql-driver/mysql"import &q…

Python练习宝典:Day 1 - 选择题 - 基础知识

目录 一、踏上Python之旅二、Python语言基础三、流程控制语句四、序列的应用 一、踏上Python之旅 1.想要输出 I Love Python,应该使用()函数。 A.printf() B.print() C.println() D.Print()2.Python安装成功的标志是在控制台(终端)输入python/python3后,命令提示符变为: A.&…

数业智能心大陆:职场倦怠的新解法

什么是职业倦怠&#xff1f; 在职场中&#xff0c;职业倦怠的表现形式丰富多样。从数业智能心大陆 AI 心理咨询平台的数据来看&#xff0c;职业倦怠呈现出多种状态。教师可能对教学不再满怀热情&#xff0c;精心备课也成为过去式&#xff1b;情绪上容易烦躁、易怒&#xff0c;在…

【d47_2】【Java】【力扣】1791.找出星型图的中心节点

思路 直接判断 edges[0][0] edges[0][1] edges[1][0] edges[1][1] 谁重复了 例如&#xff1a; [ [1,2] [2,3] ....],那么中心节点一定是2 代码 class Solution {public int findCenter(int[][] edges) {for (int i0;i<1;i){if (edges[1][0]edges[0][i]) {return edg…

车载软件调试工具系列---Trace32简介UI界面简介

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

java项目之常规应急物资管理系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的常规应急物资管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息。 项目简介&#xff1a; 基于SpringBootVue的…

TikTok流量不佳:是网络环境选择不当还是其他原因?

TikTok&#xff0c;作为全球短视频社交平台的佼佼者&#xff0c;每天都有海量的内容被上传和分享。然而&#xff0c;很多用户和内容创作者发现&#xff0c;他们的TikTok视频流量并不理想。这引发了一个问题&#xff1a;TikTok流量不佳&#xff0c;是因为网络环境选择不当&#…

S3C2440定时器

ee一、构造 二、设置相关位 1、MPLLCON寄存器&#xff08;配置MPLL寄存器&#xff0c;进行倍频&#xff09; 根据下列表格的想要输出的频率进行选择&#xff0c;选择完毕之后&#xff0c;对该寄存器进行设置 2、时钟分频控制&#xff08;CLKDIVN&#xff09;寄存器 根据不…

AD19基础应用技巧:交叉选择/跳转到器件/镜像粘贴/元器件矩形区域排列/选择过滤器/捕捉对象等设置

目录 1. 原理图<>PCB跳转2. 镜像粘贴3. 矩形区域排列4.选择过滤器5. 捕捉的对象Object for Snapping的设置 6.Grids/Guides/Axes1. **Grids&#xff08;网格&#xff09;**2. **Guides&#xff08;参考线&#xff09;**3. **Axes&#xff08;坐标轴&#xff09;**捕捉模式…

基于python的文本聚类分析与可视化实现,使用kmeans聚类,手肘法分析

1、数据预处理 由于在数据分析之前数据集通常都存在数据重复、脏数据等问题&#xff0c;所以为了提高 数据分析结果的质量&#xff0c;在应用之前就必须对数据集进行数据预处理。数据预处理的方法通常有清洗、集成、转换、规约这四个方面&#xff0c;接下来详细介绍这对爬取…

学习记录:js算法(四十二): 寻找两个正序数组的中位数

文章目录 寻找两个正序数组的中位数我的思路网上思路 总结 寻找两个正序数组的中位数 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,3], n…

力扣72-编辑距离(Java详细题解)

题目链接&#xff1a;力扣72-编辑距离 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5.如果没有ac打印dp数组 利于debug。 每一个dp…

网络层协议 —— IP协议

目录 0.前言 1.IP协议的格式 2.IP地址 2.1IP地址的划分 国际间IP地址的划分 公有IP 私有IP 特殊的IP地址 国内IP地址的划分 2.2IP地址不足问题 2.3IP地址的功能 2.4如何使用IP地址 2.5IP地址的构成 3.网段划分 以前的方案 现在的方案 4.认识宏观网络 5.路由 …

MySQL篇(事务 - 基础)

目录 一、简介 二、事务操作 1. 数据准备 2. 未控制事务 2.1. 测试正常情况 2.2. 测试异常情况 3. 控制事务 3.1. 控制事务一 查看/设置事务提交方式 提交事务 回滚事务 3.2. 控制事务二 开启事务 提交事务 回滚事务 3.3. 转账案例 四、事务的好处 五、事务四…

入门数据结构JAVA DS——二叉树的介绍 (构建,性质,基本操作等) (1)

前言 二叉树的概念和性质 二叉树的基本概念 二叉树的种类 二叉树的性质 二叉树的构建存储与遍历 存储 构建 遍历 前序遍历 后序遍历 中序遍历 层序遍历 二叉树的基本操作 获取树中结点个数 获取叶子结点个数 获取第K层结点的个数 获取二叉树的高度 检测值为v…

C++ —— vector 的模拟实现

目录 前言 1. vector深度剖析 2. 基础框架 3. 核心接口 3.1 reserve 3.2 push_back 和 pop_back 3.3 print 3.4 insert 3.5 erase 3.6 resize 4. 拷贝构造 4.1 构造与析构 4.2 拷贝构造 4.3 赋值重载 4.4 迭代器区间 5. 使用memcpy拷贝问题 前言 接:C —— 关于…

FX5 CPU模块和以太网模块的以太网通信功能

FX5 CPU模块和以太网模块的以太网通信功能的概要如下所示。 CPU模块的内置以太网端口的通信规格如下所示。 1、与MELSOFT的直接连接 不使用集线器&#xff0c;用1根以太网电缆直接连接以太网搭载模块与工程工具(GX Torks3)。无需设定IP地址&#xff0c;仅连接目标指定即可进行…

学习Java(一)类和对象

package demo.ceshi;public class Puppy {private int age;private String name;//构造器public Puppy( String name){this.name name;System.out.println("公主的名字叫&#xff1a;"name);}//设置age的值public void setAge(int age){this.age age;System.out.pr…

数值计算 --- 平方根倒数快速算法(中)

平方根倒数快速算法 --- 向Greg Walsh致敬&#xff01; 1&#xff0c;平方根倒数快速算法是如何选择初值的?WTF中的神秘数字究竟是怎么来的&#xff1f; 花开两朵&#xff0c;各表一枝。在前面的介绍中&#xff0c;我们已经知道了这段代码的作者在函数的最后使用了NR-iteratio…