You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring全局Model属性配置与Thymeleaf3.1替代#session等方案咨询

Spring统一填充Model属性及Thymeleaf 3.1移除内置对象后的优化方案

一、Spring中统一为所有Model提供属性的实现方式

最简洁且原生的方案是使用@ControllerAdvice配合@ModelAttribute注解,无需手动编写拦截器即可全局注入属性:

@ControllerAdvice
public class GlobalModelAdvice {

    @ModelAttribute
    public void addGlobalAttributes(Model model, HttpServletRequest request, HttpSession session) {
        // 注入全局通用属性,比如当前用户、系统配置等
        model.addAttribute("currentUser", session.getAttribute("currentUser"));
        model.addAttribute("contextPath", request.getContextPath());
    }
}

这个类会在所有Controller的方法执行前,自动将属性添加到Model中,覆盖所有请求场景,比拦截器实现更轻量,完全依托Spring原生机制。

如果需要在请求前后做额外逻辑(比如权限校验),也可以通过实现HandlerInterceptor接口,在postHandle方法中往ModelAndView里添加属性,但这种方式代码量更大,优先级低于@ControllerAdvice方案。

二、Thymeleaf 3.1移除#session、#httpServletRequest后的优化方案

你当前用拦截器填充属性的思路可行,但可以结合Spring原生特性进一步优化,以下是几种更优方案:

方案1:全局注入Web对象到Model(最小改造量)

借助上面的@ControllerAdvice,直接把HttpServletRequest、HttpSession注入到Model中,模板里用${request}、${session}替代原有的#httpServletRequest、#session:

@ControllerAdvice
public class ThymeleafWebAttributeAdvice {

    @ModelAttribute
    public void addWebObjects(Model model, HttpServletRequest request, HttpSession session) {
        model.addAttribute("request", request);
        model.addAttribute("session", session);
    }
}

模板使用示例:

<!-- 替代 #httpServletRequest.getContextPath() -->
<a href="${request.contextPath}/dashboard">控制台</a>

<!-- 替代 #session.getAttribute('currentUser').username -->
<span>${session.currentUser.username}</span>

这种方式几乎不需要修改原有模板的逻辑,只是把#xxx换成${xxx},适合大规模项目快速迁移。

方案2:自定义Thymeleaf方言(保留原有语法)

如果想完全保留#session、#request的原有语法,可以自定义Thymeleaf方言,注册自己的表达式对象:

@Configuration
public class CustomThymeleafDialect {

    @Bean
    public Dialect webObjectDialect() {
        return new AbstractDialect() {
            @Override
            public String getName() {
                return "customWeb";
            }

            @Override
            public Set<IExpressionObjectFactory> getExpressionObjectFactories() {
                return Collections.singleton(new IExpressionObjectFactory() {
                    @Override
                    public Set<String> getAllExpressionObjectNames() {
                        return Set.of("session", "request");
                    }

                    @Override
                    public Object buildObject(IExpressionContext context, String name) {
                        WebRequest webRequest = (WebRequest) context.getVariable("webRequest");
                        if ("session".equals(name)) {
                            return webRequest.getSession();
                        } else if ("request".equals(name)) {
                            return ((ServletWebRequest) webRequest).getRequest();
                        }
                        return null;
                    }

                    @Override
                    public boolean isCacheable(String name) {
                        return true;
                    }
                });
            }
        };
    }
}

配置完成后,模板可以继续使用${#session.currentUser}的原有语法,完全不需要修改模板代码,适合对代码一致性要求高的大规模项目。

方案3:使用Thymeleaf内置webRequest变量

Thymeleaf 3.1保留了webRequest内置变量(类型为org.springframework.web.context.request.WebRequest),可以直接用它获取request、session属性:

<!-- 获取session属性 -->
${webRequest.getAttribute('currentUser', WebRequest.SCOPE_SESSION)}

<!-- 获取request属性 -->
${webRequest.getAttribute('pageTitle', WebRequest.SCOPE_REQUEST)}

这种方式无需额外编写Java代码,但模板写法稍长,适合小范围调整的场景。

总结

  • 统一填充Model属性优先选择@ControllerAdvice + @ModelAttribute,比拦截器更简洁高效。
  • Thymeleaf 3.1迁移时,方案1实现成本最低,方案2能完全保留原有语法,可根据项目规模和需求选择。

内容的提问来源于stack exchange,提问作者leachim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:25:22