Skip to content

HarlIvyisrio/XDU-take-out-owl

 
 

Repository files navigation

Day2开发笔记

  1. service层接收employeeDTO之后不能直接传入下一层,要转换为实体对象,使用 BeanUtils.copyProperties(employeeDTO, employee);

Day3开发笔记

  1. 当涉及多张表使用逻辑外键关联时(例如 dish_id),由于在插入主表数据时无法立即获得主表的 id,因此在主表的 insert 语句中应该使用 useGeneratedKeys="true"keyProperty="id",以便在插入主表后,自动获取生成的主键,并将其用于副表的外键关联。<insert id="insert" useGeneratedKeys="true" keyProperty="id">

    • useGeneratedKeys="true":让 MyBatis 在插入主表时自动获取生成的主键
    • keyProperty="id":把生成的主键值赋给主表实体(例如 Dish 类的 id 属性),以便后续插入副表时使用
  2. 分页查询使用的DTO类与普通DTO类不同,分页查询 DTO 会包含 page(页码)、pageSize(每页大小)等分页参数。根据这些参数,数据库查询就能知道从哪一页开始查询,并且限制每页显示多少数据。

  3. 分页查询service层逻辑:

    • controller层从用户请求中接收参数后,设置用户请求中的分页参数,使用 PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
      • employeePageQueryDTO.getPage():表示当前页码。
      • employeePageQueryDTO.getPageSize():表示每页显示的条数。
    • 执行分页查询,使用 mapper对象.pageQuery(分页DTO对象)使用page列表对象接受以便进行后续操作
    • 获取分页结果,page.getTotal()为总记录数,page.getResult()为当前页面数据
    • 返回分页结果,这里要注意参数名称和前端名称一致
  4. DTO与VO的区别:

    • DTO(Data Transfer Object):用于在不同层之间传递数据,通常会包含一些额外的处理逻辑(如分页信息、过滤条件等),而且可以是 可变的,通常用于业务逻辑层的交互。
    • VO(Value Object):更倾向于传递 业务值 或者是 前端展示层 所需的数据,通常会是 不可变的,并且不含有业务逻辑。
  5. 连接操作可以让你把不同表中有关联的数据结合起来,生成一个包含多表数据的结果集。通过连接,可以:

    • 获取多个表中相关的数据。
    • 在一个查询中完成多个表的查询任务。
    • 避免冗余数据,通过不同的表结构进行更高效的数据存储。
  6. 不同类型的连接可以根据需求得到不同的结果:

    • INNER JOIN:只返回两表中都有匹配记录的行。
    • LEFT OUTER JOIN (LEFT JOIN):返回左表的所有行和右表匹配的行。如果右表没有匹配行,右表字段会返回 NULL
    • RIGHT OUTER JOIN (RIGHT JOIN):返回右表的所有行和左表匹配的行。如果左表没有匹配行,左表字段会返回 NULL
    • FULL OUTER JOIN:返回两表中所有的行,如果某一表没有匹配行,对应的字段为 NULL
  7. 关于controller层接收前端参数的注解

    • @RequestParam:获取查询参数或表单数据,获取简单的查询字符串或表单数据
    • @RequestBody:获取请求体中的数据并转换为 Java 对象(常用于 JSON、XML),
    • @PathVariable:获取 URL 路径中的变量部分。/{id}
    • @RequestHeader:获取请求头中的参数。
    • @CookieValue:获取请求中的 Cookie 参数。
    • @ModelAttribute:将请求参数绑定到 Java 对象(适用于表单数据)。
    • @RequestPart:用于处理文件上传等多部分请求。
  8. 今日总结:增删改查注意事项

    插入:controller层注意传入参数前的注解;service层注意DTO类与普通类的转换

    删除:注意判断删除前的条件,能否删除

    修改:多张表关联时先修改主表(插入删除同理),再根据逻辑外键修改附表

    查询:xml文件书写sql语句时注意多表连接的逻辑,sql语句头部foreach collection=“此处名字与mapper方法传入的形参名一致”例如:

    <foreach item="id" collection="ids" open="(" close=")" separator=",">
            #{id}
    </foreach>
    

Day4开发笔记

  1. 查询操作时controller层返回值使用普通类还是VO类如何判断?
    • 普通类(POJO):适用于直接返回数据库模型的情况,没有特殊要求的时候用这个就足够。
    • VO 类:适用于需要定制化数据格式或进行字段加工、处理的情况,尤其在前后端分离的项目中尤为常见。
  2. 关于查询操作中xml文件的resultType
    • resultType 用来告诉 MyBatis 查询结果应该如何映射到 Java 对象。
    • 当你执行查询时,数据库返回的是一组 行记录(每一行都是一个数据库表的记录),而 MyBatis 会将每一行记录转换成一个 Java 对象。
    • resultType="Dish" 表示每一行记录都应该映射成 Dish 类型的对象。
  3. 为什么 parameterType 可以是 ListresultType 通常是 List 里的元素类型?
    • parameterType:当你传递多个参数时,通常需要将它们作为集合传递,这时使用 List 作为 parameterType 可以更方便地处理多个参数。MyBatis 会自动拆解 List,并将每个元素作为单独的参数传递到 SQL 查询中
    • resultType:查询的结果集是多行数据,每一行数据对应一个实体(或 POJO),所以 resultType 是这个实体的类型。当查询结果是多行时,MyBatis 会将每一行映射为一个对象,最终返回一个包含这些对象的 List
  4. Id数据通常用Long型保存
  5. 书写sql逻辑时,#{}相关注意事项
    • #{} 中的名称应当与方法参数的名称一致,或者使用 @Param 注解指定自定义名称。
    • #{} 用于参数占位符,它会被方法传入的实际参数值所替代。
    • 使用 @Param 注解时,可以自定义参数名称,不必与方法参数名一致。
  6. 涉及到多张表的更新时,可以先改主表内容然后删除副表再插入新内容进入副表
  7. set中子句加逗号where中不用

Day5开发笔记

  1. Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件

    • MySQL:是关系型数据库,设计时就是为了持久化存储数据,它能够确保数据不会丢失,即使是断电或系统崩溃之后,也能恢复。
    • Redis:默认情况下是内存数据库,数据存储在内存中,速度非常快,但它本身并不提供完全的持久化机制
    • 在一些特定的场景下,如果数据量较小、对持久化要求不高且高访问频率要求很高,理论上是可以全用 Redis 的。例如,缓存系统、消息队列、排行榜等。但是,对于大规模的业务应用,尤其是需要数据持久化、复杂查询和事务支持的系统,完全使用 Redis 可能会带来数据丢失、管理困难、性能瓶颈等问题。
  2. redis常用数据类型

    • 字符串(string):普通字符串,Redis中最简单的数据类型

      • 底层实现
        • Redis 使用 SDS(Simple Dynamic String) 作为字符串的底层数据结构。SDS 是一种更加高效的字符串表示方式,避免了传统 C 字符串的许多缺点,如定长、频繁复制等。
        • SDS 具有动态扩展和自适应大小的特性,可以有效减少内存浪费。
        • SDS 会存储字符串的长度信息,避免每次计算字符串长度的开销。
      • 应用场景:常用于存储文本、计数器、标记等。
    • 哈希(hash):也叫散列,类似于Java中的HashMap结构

      • 底层实现
        • Redis 使用 哈希表(Hash Table)来实现哈希类型的数据结构。
        • 在内部,Redis 会根据哈希表的大小和负载因子决定是否重新哈希(即扩展哈希表)。
        • Redis 中的哈希表采用线性探测法来处理哈希冲突,确保哈希表的操作仍然是高效的。
      • 应用场景:存储对象的属性(如用户资料),配置信息、缓存的数据对象等。
    • 列表(list):按照插入顺序排序,可以有重复元素,类似于Java中的LinkedList

      • 底层实现
        • Redis 列表底层使用 双向链表(ziplist 或 linkedlist)。
        • Ziplist:当列表较小或元素较少时,Redis 会选择使用 Ziplist(压缩的顺序列表)。Ziplist 是一个内存优化的顺序结构,能够节省存储空间。
        • Linkedlist:当列表较大或操作频繁时,Redis 会切换到双向链表,支持快速的插入和删除操作。
      • 操作效率:O(1) 时间复杂度的从两端插入和删除操作,适合需要快速插入/删除数据的场景。
      • 应用场景:消息队列、任务队列、历史记录等。
    • 集合(set):无序集合,没有重复元素,类似于Java中的HashSet

      • 底层实现
        • Redis 使用 哈希表(Hash Table) 来实现集合。在集合中,每个元素的值本身就是一个键,值总是空的。
        • 为了提高性能,Redis 在内部使用一个优化的哈希表数据结构,能够实现 O(1) 的查找、插入和删除操作。
      • 应用场景:存储独立项、标签系统、去重操作、实时计数等。
    • 有序集合(sorted set/zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素

      • 底层实现
        • Redis 使用 跳表(Skip List)哈希表(Hash Table) 组合的方式来实现有序集合。
        • 跳表是一个类似于多级索引的结构,能够高效地执行范围查询和排序操作。它支持 O(log N) 时间复杂度的插入、删除、查询等操作。
        • 哈希表用来存储元素和分数的映射,以便高效的查找和更新。
      • 应用场景:排行榜、按分数排序的消息队列、实时排名系统等。
  3. @RestController("user") 中的 "user" 是为控制器类指定一个 bean 名称,这个名称可以用来在 Spring 上下文中唯一标识该控制器,类似注解也有相同用法。

  4. static与final关键字的使用

    • staticfinal 经常一起使用,特别是在定义常量时。static 确保常量是类级别的,所有实例共享;final 确保常量的值一旦设置就不能修改。

    • 使用 static 的场景

      • 类级别共享的数据:如果变量是属于类而不是某个实例,应该使用 static。例如,类的常量、计数器、配置等。
      • 工具方法或常用函数:如果某个方法不依赖于对象实例,而是可以通过类直接调用,那么可以考虑使用 static,比如 Math.max()Arrays.sort()
      • 性能优化:如果某个方法可以被类直接调用,不依赖实例,使用 static 可以避免对象创建的开销。
    • 使用 final 的场景

      • 常量:如果某个变量的值在整个应用中都不应该改变,应该使用 final 来修饰。例如,public static final double PI = 3.14159;
      • 防止修改的类、方法或变量:如果某个方法不应该被重写,某个类不应该被继承,或者某个变量的值不应该改变,应该使用 final
      • 提高代码安全性:如果希望某个值在系统中不可改变,使用 final 可以避免无意中的修改,增强代码的健壮性。

Day6开发笔记

  1. HttpClient:是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。 HttpClient的核心API:

    • HttpClient:Http客户端对象类型,使用该类型对象可发起Http请求。
    • HttpClients:可认为是构建器,可创建HttpClient对象。
    • CloseableHttpClient:实现类,实现了HttpClient接口。
    • HttpGet:Get方式请求类型。
    • HttpPost:Post方式请求类型。

    HttpClient发送请求步骤:

    • 创建HttpClient对象
    • 创建Http请求对象
    • 调用HttpClient的execute方法发送请求
  2. 微信登陆功能开发

    • Controller层首先接收Service层传来的User对象;然后根据用户密钥、超时时间、userId关联用户的map对象生成jwt令牌;封装UserVO对象。
    • Service层将传入的登录码转换为json对象,进而获取其中的openid;根据openid判断用户是否已注册,若未注册直接进行注册。
    • Mapper层在用户注册时起作用,插入新用户
  3. 用户发送请求并得到结果的整个过程的总结

    • 前端将用户名和密码以 POST 请求的形式发送到后端的登录接口创建HttpClient对象
    • 后端会验证用户名和密码。如果验证通过,后端会创建一个包含用户信息的 JWT 令牌。创建Http请求对象
    • 后端将JWT令牌返回给前端,前端通常将令牌存储在 localStoragesessionStorage 中。
    • 后续每次用户访问需要身份验证的接口时,前端都会将存储的JWT令牌添加到请求头中发送。
    • 后端会有一个 JWT拦截器(通常是 FilterInterceptor),它会在请求到达具体的 Controller 之前检查请求头中的 JWT 令牌。有效则保存,无效会抛401。
    • 如果JWT令牌验证成功,后端的Controller会接收到请求,并执行相应的业务逻辑。
    • Controller处理完请求后,将结果以HTTP响应的形式返回给前端。

Day7开发笔记

  1. 使用redis缓存热点数据

    • 手写定义:创建redisTemplate对象以便使用相关方法(如opsForValue.get/set)操作数据库,判断查询内容是否已存在,若无则加入redis中,有则直接使用而不用访问磁盘中的mysql。
    • 使用注解:
      • @EnableCaching,开启缓存注解功能,通常加在启动类上
      • @Cacheable,在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中
      • @CachePut,将方法的返回值放到缓存中
      • @CacheEvict,将一条或多条数据从缓存中删除
  2. 新增购物车数据时出现了不报错但不更新购物车表的问题:

    • 原因:没有添加用户jwt拦截器导致接收不到userId,而购物车表与用户id关联,在拦截器生效之前,可能因为没有身份信息,查询语句无法正确执行,导致购物车表的数据无法显示。
    • 解决:在WebMvc配置类中添加用户jwt拦截器
    registry.addInterceptor(jwtTokenUserInterceptor)
    .addPathPatterns("/user/**")
    .excludePathPatterns("/user/user/login")
    .excludePathPatterns("/user/shop/status");
    

Day8开发笔记

  1. 支付功能一般不自己实现,需要申请商家权限,比较复杂

Day9开发笔记

  1. 分页查询传参时status通常是包装类型Integer,表示可以为null,灵活适配数据库查询语句
  2. 为什么使用 CollectionUtils.isEmpty() 而不是 !ordersList.isEmpty()
    • 能处理 null 情况,避免 NullPointerException
    • ordersList.isEmpty() 需要先确保 ordersList不为 null,否则会抛出 NullPointerException
  3. 接单拒单和完成订单本质上是改变订单状态的操作,通常只新建对象并修改特定字段,然后将新对象传入update方法:
    • 防止不必要的字段更新
      • orders 只包含 idstatus确保只更新 status,不会改动其他字段。
    • 防止“脏数据”
      • 避免更新 ordersDB 中的所有字段,只改 status
    • 优化数据库操作
      • update(orders) 只更新 status,减少 SQL 语句的复杂度,提高性能。

Day10开发笔记

  1. Spring Task

    • Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。(注意:需要在启动类添加注解 @EnableScheduling 开启任务调度)
    • 使用cron表达式,其实就是一个字符串,来定义任务触发的时间
  2. WebSocket

    • 基于TCP的新的网络协议它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输。
    • HTTP协议和WebSocket协议对比:
      • HTTP是短连接,WebSocket是长连接
      • HTTP通信是单向的,基于请求响应模式,WebSocket支持双向通信
      • HTTP和WebSocket底层都是TCP连接
  3. WebSocket使用方法:定义一个哈希表,然后把要传输的内容写入,使用JSON.toJSONString()方法把哈希表转为JSON格式对象,然后调用如webSocketServer.sendToAllClient()方法将内容传输到前端。

About

XDU-take-out

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 41.5%
  • CSS 24.0%
  • HTML 19.0%
  • Java 5.9%
  • SCSS 3.1%
  • Vue 3.1%
  • Other 3.4%