2025年8月29日¶
面试题¶
请描述一下 @RequestParam、@RequestBody、@PathVariable 这几个注解的应用场景及作用?详细描述¶
@RequestParam
作用:用于获取请求中的查询参数或表单参数,把这些值绑定到方法参数上。
应用场景:
- URL 查询字符串:如
GET /users?page=1&size=10
,接收分页参数。 - 表单提交:处理简单的表单字段,如搜索关键字、状态筛选。
- 多值参数:如
ids=1&ids=2
,收集到List
。
@RequestBody
作用:用于获取请求体中的数据,并自动反序列化成 Java 对象。
应用场景:
- JSON 提交:前端发送复杂对象,如用户注册信息、订单详情。
- 批量操作:提交一个对象列表,比如批量新增用户。
- 修改/新增接口:接收前端传来的完整数据对象。
@PathVariable
作用:用于从URL 路径占位符中提取参数,绑定到方法参数。
应用场景:
- RESTful 风格接口:如
GET /users/{id}
获取用户详情。 - 资源定位:常用来标识资源的唯一 ID,比如商品编号、订单号。
- 多层级资源:如
/shops/{shopId}/orders/{orderId}
。
午间演讲示例
@RequestParam用来接收查询参数或者表单字段,比如分页参数、搜索条件;
@RequestBody用来接收请求体里的数据,通常是前端传过来的JSON对象,用在新增或修改这类复杂对象提交;
@PathVariable则是从路径上取值,常见于RESTful接口,比如
/users/{id}
这种资源定位。
聊聊 Mybatis 中常见的动态 SQL 的标签有哪些,这些标签的作用和使用场景是什么¶
1、 <if>
作用:根据条件决定是否拼接一段 SQL。
应用场景:可选查询条件,比如用户搜索时,只有输入了关键字才拼接 AND name LIKE ...
。
2、 <where>
作用:自动去掉多余的 AND/OR
,如果子条件都不满足,就不会加 WHERE
。
应用场景:组合查询时非常常用,比如多条件筛选用户,避免写一堆 WHERE 1=1
。
3、 <set>
作用:主要用于动态 UPDATE
语句,会自动去掉最后多余的逗号。
应用场景:更新时,只修改用户传过来的字段,比如更新用户资料时,只有传了邮箱才更新邮箱。
4、 <foreach>
作用:用来遍历集合,生成 IN
条件或批量插入。
应用场景:批量操作,比如 SELECT * FROM user WHERE id IN (...)
或批量插入多条数据。
午间演讲示例
首先是
<if>
,它的作用是根据条件来决定是否拼接SQL,常见场景就是可选查询条件,比如用户搜索时,如果输入了关键字,就拼接AND name LIKE ...
。接着是
<where>
,它能帮我们自动去掉多余的AND
或OR
,如果条件都没有,也不会生成WHERE
,常用于多条件组合查询,避免写一堆WHERE 1=1
。第三个是
<set>
,主要用在动态更新里,它会自动去掉最后多余的逗号,场景就是用户修改资料时,只更新传过来的字段,比如只传了邮箱就只更新邮箱。最后是
<foreach>
,这个常用来遍历集合,生成IN
条件或批量插入,典型场景就是批量查询用户id
,或者一次性插入多条数据。
什么是 AOP¶
aop是面向切面编程,在spring中用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合,一般像系统的公共日志记录,事务处理,权限的控制等都可以通过AOP来实现。
可能继续追问的问题:
1). 你们项目中有没有使用到AOP?
这个很多地方都用到了,比如我们当时在后台管理系统中,就是使用aop来记录了系统的操作日志、以及权限控制。那就来说一下,记录日志的操作思路吧。
主要思路是这样的,使用aop中的环绕通知 加上 基于注解@annotation
的切点表达式来实现的。
- 首先,自定义了一个注解,比如叫 @Log,然后哪些操作需要记录日志,我们就在哪些方法上加上这个注解。
- 然后再定义一个切面类,通过环绕通知,来获取原始方法在运行的各项信息,比如:类信息、方法信息、注解、请求方式、请求参数、当前操作人、操作时间、返回值等信息,全部记录下来,保存在数据库中。
当时,我们主要记录的是一些核心业务模块的增删改的操作日志,主要便于数据追踪。
2). AOP的底层是如何实现的?
SpringAOP的底层主要是通过动态代理技术实现的,主要是两种代理技术。一种是JDK的动态代理,而JDK的动态代理呢,有限制,只能针对于实现了接口的类做代理,所以,在spring中还有一种是Cglib动态代理,那Cglib动态代理呢,就没有这个限制。
3). JDK动态代理 与 Cglib动态代理有什么区别呢?
- 限制不同。 JDK动态代理,要求被代理对象必须实现了接口才可以。 而Cglib动态代理,无论是否实现接口都可以(只要类不是final修饰即可)。
- 代理对象不同。 JDK动态代理生成的代理对象,与被代理对象其实是实现了相同的接口,可以说是兄弟关系。 而Cglib动态代理生成的代理对象,其实是继承了被代理类,是基于继承体系的,所以是父子关系。 也正是因为此,所以Cglib不能为被final修饰的类做代理。
午间演讲示例
AOP是面向切面编程,在Spring里常用来处理日志、事务、权限这些和业务无关但很常见的逻辑,能降低耦合、提高复用。
在项目里我们就用AOP记录操作日志,做法是定义一个
@Log
注解,配合环绕通知,把方法信息、参数、操作人、时间等收集起来保存到数据库,方便追踪。底层上,Spring AOP是通过动态代理实现的,分为JDK代理和Cglib代理。
JDK只能代理实现了接口的类,生成的代理和目标是兄弟关系;Cglib是通过继承目标类生成子类代理,不要求接口,但不能代理final类。
SpringMVC 的拦截器用过没有¶
追问:你说的这些个功能,过滤器好像也能干,那拦截器 Interceptor 与过滤器 Filter 有什么区别
拦截器在SpringMVC里主要做登录校验、权限控制、日志记录这些和请求相关的功能。它和过滤器的区别可以打个比方:过滤器就像机场安检,在大门口,所有人都要过一遍,不分场合;而拦截器就像公司前台的门禁,只有准备进某个会议室的人才会被拦下来验证身份。所以,Filter更偏底层通用,Interceptor更贴近业务逻辑。
午间演讲示例
我用过拦截器Interceptor,主要用来做登录校验、权限控制、日志记录这类跟请求相关的功能。
- 技术所属:Filter属于Java EE规范,Interceptor属于spring规范
- 拦截资源的范围:Filter拦截部署在Tomcat服务上web项目中所有资源(静态+动态) Interceptor只能拦截spring框架管控的资源(Controller)