年份 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 元素上的元数据的结构。这种写法定义了注解的一个成员(也称为注解元素)。
注解成员定义
在注解类型中定义成员时,通常遵循以下规则:
- 方法签名:注解成员看起来像一个方法签名,但没有方法体。
- 返回类型:注解成员必须具有一个返回类型,可以是基本类型、枚举类型、类类型、其他注解类型,甚至是这些类型的数组。
- 没有参数:注解成员通常没有参数列表。
- 默认值:可以为注解成员提供默认值。
枚举类
也是第一次见,Javase时候好像没学
方法签名
这个以前也鲜有听说,记录一下。
在Java中,方法的签名(method signature)是指方法的名称、参数列表以及返回类型(有时还包括异常列表)。具体来说,方法签名由以下几部分组成:
- 方法名称:标识方法的名字。
- 参数列表:包括参数的类型、顺序和数量。
- 返回类型:方法执行后返回的值的类型。
在某些上下文中,方法签名还包括方法的异常列表,即方法声明中抛出的异常类型。
方法签名的重要性
方法签名在Java中非常重要,主要用于以下几个方面:
- 方法重载(Overloading):在同一类中,多个方法可以有相同的名字,只要它们的参数列表不同即可。这意味着方法签名必须唯一。
- 方法调用:在调用方法时,虚拟机根据方法签名找到正确的实现。
- 反射:在运行时通过反射访问方法时,需要知道方法签名才能正确调用。
有关向下转型的一些疑问
疑问: 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
时确实是得到了一个方法签名对象,而不是其他类型的签名对象。这有助于避免运行时错误。
对第二行代码的详细解释
-
signature
对象:这是从JoinPoint
对象获取的方法签名信息。signature
实际上是一个Signature
接口的实现,这里通过向下转型为MethodSignature
类型来获取更多方法相关的细节。 -
getMethod()
方法:MethodSignature
类提供了getMethod()
方法,该方法返回一个java.lang.reflect.Method
对象,该对象代表了被拦截的具体方法。 -
getAnnotation(Class<T> annotationClass)
方法:Method
对象提供了getAnnotation
方法,该方法用于获取指定类型的注解。传递给getAnnotation
方法的是一个Class
对象,表示我们想要获取的注解类型
将方法添加到异常签名列表和用try catch包围有什么区别
区别总结
-
责任划分:
- 异常签名列表:方法声明了可能抛出的异常,调用者负责处理这些异常。
try-catch
块:方法内部处理异常,调用者无需关心这些异常。
-
代码复杂度:
- 异常签名列表:增加调用者的复杂度,需要处理或重新声明异常。
try-catch
块:减少调用者的复杂度,但可能增加方法内部的复杂度。
-
透明性:
- 异常签名列表:调用者明确知道方法可能抛出的异常,增强了透明性。
try-catch
块:调用者可能不知道方法内部的异常处理逻辑,降低了透明性。
-
耦合度:
- 异常签名列表:增加了调用者和被调用者之间的耦合度。
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="pageQuery"<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,我爱你。
但,长路漫漫,还需上下求索,加油。
最近有喜欢尼采的一句话,就用来结尾吧。
我该如何获得成功? 放弃思考,努力攀登。
-------------------- 就此搁笔,以上与君共勉,祝乘风破浪,所愿皆所得。----------------------------