CQWM
知识储备
nginx 前端代理和负载均衡器
https://blog.csdn.net/weixin_30305735/article/details/96851920?fromshare=blogdetail&sharetype=blogdetail&sharerId=96851920&sharerefer=PC&sharesource=&sharefrom=from_link
jwt相关的内容,看看登录的代码
tips
todo标签页
java配置类
01
前端后端搭建
前端开启nginx
后端熟悉几个子模块的结构
pojo:dto,vo,entity
使用git来进行版本控制
本地仓库--远程仓库--push
数据库环境搭建
前后端联调
打断点走了一下登录过程
Nginx反向代理和负载均衡的概念

好处:提高访问速度,进行负载均衡,保证后端服务安全
反向代理配置 80端口是http的默认端口,8080不是标准端口(开发测试环境、反向代理、Tomcat 等 Web 服务器常用 8080 来跑服务)
负载均衡配置 负载均衡策略:轮询,权重
完善登录功能
进行了md5加密
接口文档和swagger
swagger使用方式
Knife4j 是为Java MVC框架集成Swagger生成Api文档的增强解决方案。
导入knife4j的maven坐标--在配置类中加入相关配置--设置静态资源映射,否则接口文档页面无法访问
02
新增员工
比较简单
测试过程注意添加了token全局参数,jwt相关内容之后再看
完善了两个问题:录入的用户名已经存在;创建人id是固定值
1.全局异常处理器怎么个用法 业务层只需要 throw 异常,不用自己写 try-catch,所有异常都会被全局处理器拦截并转换成统一的响应格式
自定义异常处理的三步
2.threadlocal

客户端发起的每一次请求都会对应一个单独的线程,token解析出用户,然后存入threadlocal,同一个线程内又进行新增员工,可以读取到用户id
分页查询
1.接收的不是json格式的数据,@GetMapping查询条件是通过 URL 查询参数传过来的,所以不需要 @RequestBody
注:@RequestBody 是用来接收 请求体(Request Body)里的 JSON 数据,这通常用于 POST / PUT / DELETE 请求
GET 用于获取资源,参数通过 URL 传递;POST 用于提交资源,参数通过请求体传递
2.返回的不是result,而是专门设计的PageResult(数量加上list集合)
3.pageHelper的底层原理
service实现类通过threadlocal存进去page和每页记录数,mapper层再取出来用
4.日期规格化处理 TODO
全局消息转换器是是什么 209
启用禁用,编辑员工
1.查询类的操作result需要指定泛型,其他的可以不指定(不需要返回数据)
2.mybatis中set标签会自动处理多余的逗号
3.编辑员工涉及到两个接口
根据id查询员工信息,编辑员工信息
03
公共字段自动填充
1.反射机制
硬编码 软编码

硬编码:想更换对象必须改源码加重新编译
软编码:可以在运行中发生变化,不需要重新编译
反射就是将对象和类里面的属性或者方法进行反射操作,
2.自定义注解
自定义注解的本质是 给代码打标签,配合 反射机制,框架或程序就能根据注解来执行特定逻辑
// 自定义注解
@Target(ElementType.METHOD) // 使用范围:只能用在方法上
@Retention(RetentionPolicy.RUNTIME) // 生命周期:运行时保留
public @interface MyLog {
String value() default ""; // 注解属性,默认值为空
int level() default 1; // 注解属性,默认值为 1
}
public class UserService {
@MyLog(value = "新增用户", level = 2)
public void addUser(String name) {
System.out.println("添加用户: " + name);
}
}
//注解本身不会执行任何逻辑,需要结合 反射 来读取和处理。
public class AnnotationTest {
public static void main(String[] args) throws Exception {
Method method = UserService.class.getMethod("addUser", String.class);
if (method.isAnnotationPresent(MyLog.class)) {
MyLog myLog = method.getAnnotation(MyLog.class);
System.out.println("操作: " + myLog.value() + ", 等级: " + myLog.level());
}
}
}
3.aop
aop的底层也是通过动态代理实现的
横向切入各个业务层方法,对他们进行统一编程
几个概念的再熟悉:连接点,切入点,通知,切面,切面类

4.实现思路 这个切入在mapper层进行的before切入,个人理解是mapper层偏底层,如果在业务层切入的话会需要重复处理(可能两个业务都调用了update)
- 自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法
- 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值
- 在 Mapper 的方法上加入 AutoFill 注解
自定义注解的作用是用于标识某个方法需要进行自动填充处理,进行准确的切入(切入点表达式的两种写法中的一种)
为什么要通过反射为公共字段赋值? 因为对象是不固定的,可能是employee,可能是category,等于传递来了一个动态的对象(entity可以是dog可以是cat)
不同的实体类都会有这些字段,不可能在切面里写死某个实体类的 setter(否则每新增一个实体类,就得改切面)➡️ 所以就需要一种 “通用、动态” 的方式,来操作不同类上的相同字段。
新增菜品
1.阿里云对象存储服务
配置属性类 作用:把散落在配置文件里的键值对,自动绑定到一个 Java 对象里,方便我们在代码中直接使用
主配置文件,开发阶段配置文件dev,生产环境的配置文件
配置类 就是一个用来 替代 XML 配置文件 的 Java 类。核心任务是:告诉 Spring 容器要管理哪些 Bean,以及如何创建这些 Bean
配置项通过配置属性类加载封装成一个对象-->配置类用来根据这些配置创建和管理 Bean
2.为什么上传文件到阿里云服务器后前端可以回显
后端会返回一个url,前端拿到这个 URL 后,把它赋给 <img src="..."> 或者 <video src="...">,于是就能显示出来
3.具体业务实现不复杂
由于需要对两个表进行插入操作,需要设置事务;userGeneratedKeys和keyProperty的使用,获取主键值并将主键值赋给某个属性
删除菜品
1.@PathVariable用于绑定路径参数,@RequestPrarm用于绑定查询参数(对多值参数的处理:Spring MVC 会动态分割字符串然后封装到集合对象中)
呃呃呃mp还是方便多了
编辑菜品
1.涉及四个接口
上传文件+根据id回显查询+修改菜品信息+根据类型查询分类(下拉选项表)
2.根据id查询回显时没返回分类名称?
直接前端拿到数据
3.编辑菜品信息时口味相关属性的dishId需要进行设置
前端没有传来dishId
05
redis回忆
1.redis的java客户端
jedis lettuce spring datet redis
2.使用方式
maven坐标导入--yml配置数据源--编写配置类--通过redisTemplate操作Redis
3.配置类
4.redis使用时候value有乱码怎么办
redistemplate可以接收任意object作为之写入redis,只不过写入前会把object序列化成字节形式。默认使用JDk序列化,可能会有乱码问题
方法一:自定义RedisTemplate的序列化方式,序列化就是java对象和redis存储的字节形式之间的桥梁
key和hashkey采用string序列化,value和hashvalue采用JSON序列化
方法二:使用stringredistemplate,读出或者写入redis时手动完成与对象与JSON之间的转化
07
缓存菜品和套餐
1.redis是内存操作,访问数据库是磁盘io操作
缓存菜品手动实现,缓存套餐通过缓存框架spring cache实现
2.缓存框架spring cache的使用

key都是通过注解的参数动态来获得的
用户端的查询,管理端的增删改都需要进行相关与缓存有关的处理
08
用户下单
订单支付
1.微信小程序支付时序图

重要的两步:商户系统调用微信支付服务后台生成预支付交易单;微信小程序调起支付
跳过
10
基于Spring Task实现订单状态定时处理
1.一款定时任务框架
2.component和bean注解的区别
在 Spring 中,@Component 和 @Bean 都用于将对象交给 Spring 容器管理,但它们的使用方式、场景和原理不同
@Component 用于类上,是自动扫描注册的;@Bean 用于方法上,是手动注册的。

WebSocket实现来单提醒和客户催单
1.webSocket是基于TCP的一种新的网络协议,它实现了浏览器与服务器的全双工通信

长连接,双向数据交互,底层TCP
2.为什么使用websocket?
服务端需要主动实时推送消息给客户端,而不是依赖客户端轮询请求。
客户催单阶段的通信过程是用户小程序通过http请求通知到后端,服务端通过websocket实时推送消息给客户端
3.实现类中paySuccess是怎么调用到的
支付成功后,由微信的服务器回调到paySuccessNotify controller方法,而在这个controller里面调用到了paySuccess方法
11
为什么要将 beginTime、endTime 和 status 封装成 Map 传给 orderMapper.sumByMap(map) 方法,而不是直接将它们作为方法参数传递
- 兼容 MyBatis 动态 SQL MyBatis 的 XML 映射文件中通过 #{key} 引用参数时,Map 提供灵活的键值访问方式。
- 易于扩展 将来如果要添加更多查询条件(如店铺ID、支付方式等),使用 Map 只需增加 put(),无需修改方法签名。
- 保持接口统一性 所有查询方法参数形式统一,便于维护多个类似接口。
Apache Echarts
一款基于JavaScript的数据可视化图表库
12
可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作
实现步骤:设计excel模版文件--查新近三十天的数据--将数据写入模板文件--通过输出流将文件下载到客户端浏览器
在模版基础上添加数据
HttpServletResponse 是 Java Web 编程中用于 向客户端发送响应数据 的接口,是 Servlet API 的一部分。它由 Servlet 容器(如 Tomcat)提供,在处理 HTTP 请求时作为方法参数传入。

浙公网安备 33010602011771号