@ModelAttribute 可实现控制器级或全局级模型数据绑定:控制器内方法作用于本类所有处理器,@ControllerAdvice 配合 @ModelAttribute 则作用于全应用;命名冲突时控制器内同名 key 会覆盖全局的。

在 Spring MVC 中,@ModelAttribute 用于将数据自动绑定到视图模型(Model),而“全局”数据绑定指的是让某些数据对所有请求处理器方法都生效,无需每个方法重复添加。这通常通过 @ModelAttribute 方法实现——它不是加在控制器方法上,而是加在控制器类中任意一个返回值非 void 的方法上,Spring 会自动在每次请求处理前调用它,并把返回值或参数注入 Model。
定义全局 @ModelAttribute 方法
在一个 Controller 类中,声明一个被 @ModelAttribute 注解的方法,该方法不接收请求映射(即没有 @RequestMapping),但会在该 Controller 下所有 handler 方法执行前被调用。
- 方法可以返回任意对象,Spring 会将其以默认名称(类名首字母小写)加入 Model;也可通过注解指定名称:
@ModelAttribute("userInfo") - 方法也可以接受参数(如
Model、HttpServletRequest、@SessionAttribute等),便于动态构建数据 - 注意:该方法只对当前 Controller 有效;若需跨多个 Controller 全局生效,应使用
@ControllerAdvice配合
使用 @ControllerAdvice 实现真正全局绑定
当需要为整个应用的多个 Controller 统一注入公共数据(如导航菜单、当前用户、站点配置等),推荐使用 @ControllerAdvice + @ModelAttribute 组合:
-
@ControllerAdvice是全局拦截器,作用于所有@Controller类 - 在其内部定义
@ModelAttribute方法,即可对所有请求生效 - 可配合条件判断(如检查登录状态、请求路径等)控制是否添加某项数据
示例:
立即学习“Java免费学习笔记(深入)”;
@ControllerAdvice
public class GlobalModelAdvice {
@ModelAttribute("siteTitle")
public String siteTitle() {
return "我的管理系统";
}
@ModelAttribute("currentUser")
public User getCurrentUser(HttpServletRequest request) {
// 从 session 或 token 解析当前用户
return (User) request.getSession().getAttribute("user");
}
}
避免命名冲突与覆盖问题
多个 @ModelAttribute 方法返回同名 key 时,后执行的会覆盖先执行的(按类继承顺序和方法声明顺序)。需要注意:
- 全局
@ControllerAdvice中的方法优先级低于具体 Controller 内的方法(即 Controller 内同名 key 会覆盖全局的) - 可在模板中用
${siteTitle}直接访问,无需在每个 handler 方法里手动model.addAttribute(...) - 如果某次请求不需要某个全局属性,可在 handler 方法中显式调用
model.asMap().remove("key")
结合 @InitBinder 实现全局参数预处理
除了模型数据,有时还需统一处理请求参数(如日期格式、字符串 trim、枚举转换等),这时可搭配 @InitBinder 使用:
-
@InitBinder方法也支持放在@ControllerAdvice中,实现全局参数绑定规则 - 例如注册自定义
PropertyEditor或Converter,让所有 Controller 自动识别yyyy-MM-dd字符串为LocalDate - 注意:它影响的是参数绑定过程,而非 Model 数据本身,但常与
@ModelAttribute协同使用
不复杂但容易忽略细节,关键是区分“Controller 级”和“应用级”作用域,合理选择 @ModelAttribute 的位置和命名策略。


















