苍穹外卖中一些知识点和问题

注意一个贼坑的点:以前的Jdk版本是21,全都改成17后maven编译依然报错:无效的目标发行版:21,加上这三行即可正常启动:

复制代码
<maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.release>17</maven.compiler.release>

尤其是最后一行!

@ExceptionHandler
  • 作用范围 :只能处理当前 Controller 类中抛出的异常。
  • 用法:写在某个方法上,指定该方法处理哪些异常类型。
  • 缺点:每个 Controller 都要重复写,无法全局复用。
  • 没有括号(即没有显式指定 value = {...})时,Spring 会自动根据方法参数中声明的异常类型,来推断这个处理器能处理哪些异常。
@RestControllerAdvice
  • 作用范围全局生效 !可以捕获所有 Controller 中抛出的异常
  • 本质 :是 @ControllerAdvice + @ResponseBody 的组合。
    • @ControllerAdvice:增强型切面,作用于所有 @Controller@RestController
    • @ResponseBody:让返回值直接作为 JSON 响应体(而不是视图名)

✅ 所以 @RestControllerAdvice = 全局异常处理器 + 返回 JSON

通过结合上述两者一起使用。

@BuilderLombok 提供的一个注解,用于自动生成"建造者模式(Builder Pattern)"的代码 ,让你能以链式、可读性强、安全的方式创建对象 ,尤其适用于有多个参数(尤其是可选参数)的类。要求类必须有全参数构造函数。

负载均衡也是基于反向代理来做的。

在Mybatis中如果只有一个参数那么sql语句中写成类似#{name}即可,而不可#{user.name}。但是如果存在两个即以上的参数时每个参数前面需要使用@Param("user1"),@Param("user2")这种,且这时候要变成#{user1.name},#{user2.name}。

注意在原代码中并未及时清理ThreadLocal应该重写afterCompletion在里面释放:

preHandle

  • 执行时机Controller 方法执行之前
  • 作用
    • 常用于权限校验、身份认证(如 JWT 验证)、日志记录等。
    • 可以决定是否继续执行后续流程。
  • 返回值含义
    • true:继续执行下一个拦截器或目标 Controller 方法。
    • false:中断请求处理链,不再调用 Controller 和后续拦截器(但已执行的 preHandle 对应的 afterCompletion 仍会执行!)。

postHandle

  • 执行时机Controller 方法执行完毕之后,但在视图渲染(View 渲染)之前
  • 作用
    • 可用于修改 ModelAndView(比如添加通用数据、统一错误处理等)。
    • 适合做"后置处理",但注意此时响应还没有提交(response 还未写回客户端)。

afterCompletion

  • 执行时机整个请求完成之后(包括视图渲染),即"清理阶段"

SpringMvc中如果请求参数非Json而是Query,则不需要加@RequestBody或其他注解

limit x,y表示跳过x行(从0计数),取y行

由于格式转化问题导致Java中LocalDateTime转为Json时会成为数组,解决方法如下:

语法 出现场景 作用 是否安全 示例
#{} MyBatis XML 预编译参数(防注入) ✅ 安全 WHERE name = #{name}
${} MyBatis XML 字符串直接替换 ❌ 危险 ORDER BY ${column}
{xxx} Spring MVC 路径 提取 URL 路径变量 ✅ 安全 @GetMapping("/user/{id}")
${xxx} Spring 配置/@Value 引用配置属性 ✅ 安全 @Value("${app.name}")
{} SLF4J 日志 日志参数占位 ✅ 安全 logger.info("Hello {}", name)

@Target:指定注解可以用在哪些程序元素上

@Target 用来限制你的注解可以标注在哪些 Java 元素上。如果不加 @Target,默认该注解可以用于任何地方。

常见的 ElementType 取值包括:
ElementType 说明
TYPE 类、接口(包括注解)、枚举
FIELD 字段(成员变量)
METHOD 方法
PARAMETER 方法参数
CONSTRUCTOR 构造器
LOCAL_VARIABLE 局部变量
ANNOTATION_TYPE 注解类型本身
PACKAGE
TYPE_PARAMETER 类型参数(Java 8+)
TYPE_USE 类型使用(Java 8+)

@Retention:指定注解的保留策略(生命周期)

@Retention 决定了注解在什么阶段可用(是否保留在字节码中,能否在运行时通过反射读取)。

RetentionPolicy 说明
SOURCE 仅保留在源码中,编译时丢弃(如 @Override@SuppressWarnings
CLASS 保留在 .class 文件中,但 JVM 加载时不保留(默认值)
RUNTIME 保留在运行时,可通过反射获取(如 Spring 的 @Autowired

在 Java 注解中,如果定义了一个名为 value 的成员,那么在使用注解时可以省略成员名,直接写值。这是 Java 的语法糖。

java 复制代码
@AutoFill(OperationType.INSERT)
//等价于
@AutoFill(value = OperationType.INSERT)

只有当注解中"只有一个成员"或者"其他成员都有默认值"时,才能使用这种简写。

@ConditionalOnMissingBeanSpring Boot 提供的一个条件注解(Conditional Annotation) ,用于只有在 Spring 容器中不存在指定类型的 Bean 时,才创建当前的 Bean

String:

方法 搜索方向 返回值
indexOf(...) 从前往后(左 → 右) 第一次出现的位置(最小索引)
lastIndexOf(...) 从后往前(右 → 左) 最后一次出现的位置(最大索引)

在 Spring 框架中,@Service 注解通常加在 Service 的实现类(Impl)上,而不是接口上。

java 复制代码
<insert id="insert" useGeneratedKeys="true" keyProperty="id">

1. useGeneratedKeys="true"

含义:

告诉 MyBatis:这个插入操作会使用数据库自动生成的主键(比如 MySQL 的 AUTO_INCREMENT,请把生成的主键值取回来。

默认值:
  • 默认是 false
  • 如果你不设为 true,即使数据库生成了 ID,MyBatis 也不会去获取它。

keyProperty="id"

含义:

指定 将数据库生成的主键值赋给 Java 对象的哪个属性

  • 这里的 "id" 是你的实体类(比如 User)中的字段名。
  • 插入成功后,MyBatis 会自动把生成的主键值设置到 user.setId(生成的ID)。即调用Getter方法即可获得。

在 MyBatis 的 <foreach> 标签中,collection 属性的值必须与传递给该 SQL 语句的参数中的变量名一致

@SpringBootTest 是 Spring Boot 测试框架中最核心、最常用的注解之一。

它的主要作用是:告诉 Spring Boot 去寻找主配置类(通常带有 @SpringBootApplication 的类),并基于此启动一个完整的 Spring 应用上下文(ApplicationContext)

  • Bean 唯一性标准 :仅取决于 Bean Name ,与包名、@RequestMapping 路径无关。
  • 默认规则 :若未指定名称,Spring 默认将类名首字母小写作为 Bean Name。
  • 冲突场景 :不同包下若有同名类 (如 com.a.Usercom.b.User),默认生成的 Bean Name 均为 user,会导致 启动报错 (BeanDefinitionOverrideException) 或 后者覆盖前者

解决方案

  1. 显式命名(推荐):在注解中指定唯一名称。

    @RestController("userV1") // 强制指定不同名称
    public class UserController { ... }

在 Java 中,throwthrows 虽然拼写相似且都与异常处理有关,但它们的作用、位置和使用场景完全不同。

简单的一句话总结:

  • throw :是动作 。用来在代码块内部手动抛出一个具体的异常对象
  • throws :是声明 。用在方法签名上,告诉调用者"这个方法可能会抛出某种异常,你要小心处理"。
特性 @RequestMapping @RestController
类型 映射注解 (Mapping Annotation) 构造型注解 (Stereotype Annotation)
主要用途 定义 URL 路径映射 定义一个返回数据的 REST API 控制器类
使用位置 类上 或 方法上 只能用在类上
返回视图 (JSP/HTML) 支持 (配合 @Controller) 不支持 (永远返回数据)
返回 JSON/数据 需额外加 @ResponseBody 默认支持 (内置了 @ResponseBody)
常见场景 传统 MVC (服务端渲染) 或 自定义复杂映射 前后端分离项目 (Vue/React + Spring Boot)
专用注解 等价于 @RequestMapping 的写法 用途场景
@GetMapping @RequestMapping(method = RequestMethod.GET) 查询数据 (最常用)
@PostMapping @RequestMapping(method = RequestMethod.POST) 新增数据 / 提交表单
@PutMapping @RequestMapping(method = RequestMethod.PUT) 修改/更新全部数据
@DeleteMapping @RequestMapping(method = RequestMethod.DELETE) 删除数据
@PatchMapping @RequestMapping(method = RequestMethod.PATCH) 部分修改数据

RedisTemplate.keys(pattern) 方法的作用是:根据给定的通配符模式(Pattern),查找并返回当前数据库中所有匹配的 Key 的集合。和redis中keys一样的效果。

@CachePut的用法:

@Options 注解在 MyBatis 中是一个配置容器 ,它的主要作用是为当前的 SQL 语句(通常是 @Insert, @Update, @Delete)提供额外的执行选项和行为控制

复制代码
@Options(useGeneratedKeys = true, keyProperty = "id")

表示使用数据库的自增机制,并将生成的主键回填到 Java 对象的指定属性中。

复制代码
@CacheEvict(value = "myCache", allEntries = true)表示删除以myCache前缀的所有key

@JsonFormat 是在 JSON 序列化 (Java对象转JSON字符串)和 反序列化 (JSON字符串转Java对象)的瞬间被使用的。即在Controller层返回数据与接受数据时搭配@RequestBody使用。

1. 放哪里?

直接加在 实体类的字段 上。

2. 干什么用?

控制 JSON 转换时的 日期格式时区

复制代码
// 格式:年-月-日 时:分:秒,时区设为上海
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;

@DateTimeFormat 注解主要用于处理从前端到后端的数据绑定 。它的作用是在接收 HTTP 请求时,告诉 Spring 如何将请求参数中的字符串 格式(如 "2026-04-03")正确地解析并转换为 Java 的日期时间对象(如 LocalDateLocalDateTime)。

特性 @DateTimeFormat @JsonFormat
作用方向 请求进入 (Request) 响应出去 (Response)
核心功能 将字符串解析为 Java 日期对象 将 Java 日期对象序列化为字符串
所属框架 Spring Framework Jackson Library
典型场景 接收前端传来的查询参数、表单数据 将后端实体对象转换为 JSON 格式返回给前端

COALESCE(a, b) = 如果 aNULL,就返回 b;否则返回 a

@PathVariable("id")

告诉 Spring:"请把 URL 路径中名为 id 的那个占位符的值,绑定到这个方法参数上。"

@EnableCaching

这个注解用于开启 Spring 的注解式缓存支持

  • 作用 :激活 Spring 的缓存机制,让你可以使用 @Cacheable@CachePut@CacheEvict 等注解来管理缓存。

@EnableScheduling

这个注解用于开启对计划任务(定时任务)的支持

  • 作用 :激活 Spring 的定时任务功能,让你可以使用 @Scheduled 注解来定义周期性执行的任务。

@EnableTransactionManagement

这个注解用于开启注解式的声明式事务管理支持

  • 作用 :激活 Spring 对事务的管理能力,让你可以使用 @Transactional 注解来保证数据库操作的一致性。
向上转型 ------ 自动的

"子类对象赋值给父类引用"

  • 规则: 父类 obj = new 子类();
  • 特点: 自动进行,不需要强制转换。
  • 限制: 转型后,只能调用父类中定义的方法,不能调用子类特有的方法。
向下转型 ------ 手动的

"父类引用转回子类对象"

  • 规则: 子类 obj = (子类) 父类引用;
  • 特点: 必须强制转换,否则编译报错。
  • 风险: 如果父类引用原本指向的不是该子类对象,运行时会抛出 ClassCastException
  • 你的代码场景(取值时):
    当你从 Map 取出数据时,你拿到的是 Object。如果你想把它当数字用,通常需要向下转型(或者自动拆箱)。
特性 LocalDate LocalDateTime
包含信息 仅年、月、日 年、月、日、时、分、秒、纳秒
时间精度 到天 到纳秒
典型用途 生日、节假日、按天统计 订单时间、日志时间、任务调度
  1. 无时区信息 :两者都不包含时区信息,它们代表的是"本地"的日期或时间。例如,LocalDateTime2026-04-03T10:30:00 无法区分是北京时间的10:30还是伦敦时间的10:30。
  2. 不可变性:它们都是不可变的(immutable)。任何对日期或时间的修改操作(如增加一天)都会返回一个新的实例,而不是修改原有对象,这使得它们是线程安全的。

LocalDateTime.MIN

  • 所属类: java.time.LocalDateTime
  • 表示内容: 表示 Java LocalDateTime 类所能支持的绝对最小日期和时间
  • 具体值: 它的值是 -999999999-01-01T00:00,即公元前一亿年1月1日的零点。这是一个具体的、固定的时间点。
  • 用途: 通常用于需要表示一个"最早可能时间"的场景,作为一个时间范围的下限。

🕐 LocalTime.MIN

  • 所属类: java.time.LocalTime

  • 表示内容: 表示一天中的最小时间,即午夜的开始。

  • 具体值: 它的值是 00:00。它不代表任何具体的日期,只代表一天中的这个时刻。

  • 用途: 用于处理一天内的时间范围,例如判断当前时间是否在 00:00 之后,或者作为一天时间计算的起点。

  • &:开启特殊符号模式。

  • gt:符号的名字(greater than)。

  • ;结束特殊符号模式(这就是你问的那个分号的作用)。

相关推荐
Rsun045512 小时前
5、Java 原型模式从入门到实战
java·开发语言·原型模式
lxh01132 小时前
最接近的三数之和
java·数据结构·算法
重生的黑客2 小时前
Linux:Makefile 自动化构建与进度条实战
linux·运维·自动化
我登哥MVP2 小时前
【SpringMVC笔记】 - 3 - 获取请求数据
java·spring boot·spring·servlet·tomcat·maven·intellij-idea
Predestination王瀞潞2 小时前
彻底解决IDEA Console控制台乱码(Python可供参考第一部分)
java·ide·intellij-idea
发发就是发2 小时前
资源管理:I/O端口与内存映射
linux·服务器·驱动开发·单片机·嵌入式硬件·fpga开发
坤坤藤椒牛肉面2 小时前
linux中断:顶半部与底半部
linux·运维·服务器
辞旧 lekkk2 小时前
【Git】远程操作与标签管理
linux·git·学习·萌新
web守墓人2 小时前
【linux】Mubuntu发布,将完整的ubuntu arm装进手机应用中
linux·arm开发·ubuntu