Article

【springmvc thymeleaf】springmvc整合thymeleaf

【springmvc thymeleaf】springmvc整合thymeleaf

概述

Thymeleaf 提供了一组 Spring 集成,使您可以将其用作 Spring MVC 应用程序中 JSP 的全功能替代品。

这些集成将使您能够:

  • @Controller 像使用 JSP 一样,将 Spring MVC 对象中的映射方法转发到 Thymeleaf 管理的模板。
  • 在模板中使用 Spring 表达式语言(Spring EL)代替 OGNL。
  • 在与表单支持 Bean 和结果绑定完全集成的模板中创建表单,包括使用属性编辑器,转换服务和验证错误处理。
  • 显示 Spring 管理的消息文件中的国际化消息(通过常规 MessageSource 对象)。
  • 使用 Spring 自己的资源解析机制解析您的模板。

thymeleaf 自己也做了 spring 的集成,所以我们并不需要做太多的配置,就可以达到我们想要的结果。thymeleaf 提供了两种集成方法:①、注解配置,也就是 java 代码,②、xml 文件配配置,本文主要介绍第二种 xml 配置。

你能 get 到的知识点:

1、springmvc 整合 thymeleaf 2、spring 提供的三种 model 的使用 3、解决 html 前端 thymeleaf 不生效问题(见问题 1) 4、解决 html 前端显示乱码问题(见问题 2)

springmvc 整合 thymeleaf

一:加入依赖

在 springmvc 里面,除了要加入thymeleaf的主依赖之外,还需要thymeleaf-spring4,否则会报org.thymeleaf.spring4.view.ThymeleafViewResolver,找不到 thymeleaf 解析器,所以thymeleaf-spring4也是必不可少的。

Thymeleaf 具有针对 Spring Framework 3.x 和 4.x 的集成,由两个独立的库分别称为 thymeleaf-spring3 和提供 thymeleaf-spring4。这些库打包在单独的.jar 文件(thymeleaf-spring3-{version}.jar 和 thymeleaf-spring4-{version}.jar)中,需要添加到类路径中,以便在应用程序中使用 Thymeleaf 的 Spring 集成

        <!--        thymeleaf-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring4</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>

二:设置 thymeleaf 解析器

在 springmvc 配置文件中配置 thymeleaf 解析器,官方文档中 Thymeleaf 提供了上述两个接口的实现:

org.thymeleaf.spring4.view.ThymeleafView
org.thymeleaf.spring4.view.ThymeleafViewResolver

不过现在都已经被org.thymeleaf.spring4.view.ThymeleafViewResolver所代替,至于以上配置是否还能够生效,就要靠你来试试了。

 <!-- thymeleaf 模板解析器 -->
    <bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
        <property name="prefix" value="/" />
        <property name="suffix" value=".html" />
        <property name="templateMode" value="HTML" />
        <property name="cacheable" value="false" />
        <property name="characterEncoding" value="UTF-8"/>
    </bean>

    <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
        <property name="templateResolver" ref="templateResolver" />
    </bean>

    <!--    视图解析器-->
    <bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
        <property name="templateEngine" ref="templateEngine" />
        <property name="characterEncoding" value="UTF-8"/>
    </bean>

ViewResolvers 是负责获取特定操作和语言环境的 View 对象的对象。通常,控制器要求 ViewResolvers 转发到具有特定名称的视图(由 controller 方法返回的 String),然后应用程序中的所有视图解析器将按有序链执行,直到其中一个能够解析该视图为止。如果返回了 View 对象,并且将控件传递给该对象以呈现 HTML。

注:值得注意的是,如果自己设置了 spring 的视图解析器,需要将其注释掉,否则 thymeleaf 解析器可能不会生效,我就是因为这个调试了好久,最后才发现这个问题。

    <!--    配置视图解析器 prefix:前缀, suffix:后缀   使用thymeleaf需要将其注释掉-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".html"/>
    </bean>

三:编写控制器

需要从控制层传数据到视图时,我们就会使用 model,常用的三种 model 就是:Model、ModelMap、ModelAndView。使用这三种 model 时,spring 框架自动创建实例并作为 controller 的入参,用户无需自己创建

1、使用 Model

    /**
     * 在Model里存入一个用户信息
     * @return hello页面
     */
    @GetMapping("returnModelAndView")
    public String returnModelAndView(Model model){
        model.addAttribute("userInfo",new UserInfo("lomtom","123",new Address("湖南","邵阳")));
        return "hello";
    }

Model 是一个接口, Model 源码:

public interface Model {
    Model addAttribute(String var1, Object var2);

    Model addAttribute(Object var1);

    Model addAllAttributes(Collection<?> var1);

    Model addAllAttributes(Map<String, ?> var1);

    Model mergeAttributes(Map<String, ?> var1);

    boolean containsAttribute(String var1);

    Map<String, Object> asMap();
}

2、使用 ModelMap

ModelMap 继承 LinkedHashMap ModelMap 源码:

public class ModelMap extends LinkedHashMap<String, Object> {
    public ModelMap() {
    }

    public ModelMap(String attributeName, Object attributeValue) {
        this.addAttribute(attributeName, attributeValue);
    }

    public ModelMap(Object attributeValue) {
        this.addAttribute(attributeValue);
    }

    public ModelMap addAttribute(String attributeName, Object attributeValue) {
        Assert.notNull(attributeName, "Model attribute name must not be null");
        this.put(attributeName, attributeValue);
        return this;
    }

    public ModelMap addAttribute(Object attributeValue) {
        Assert.notNull(attributeValue, "Model object must not be null");
        return attributeValue instanceof Collection && ((Collection)attributeValue).isEmpty() ? this : this.addAttribute(Conventions.getVariableName(attributeValue), attributeValue);
    }

    public ModelMap addAllAttributes(Collection<?> attributeValues) {
        if (attributeValues != null) {
            Iterator var2 = attributeValues.iterator();

            while(var2.hasNext()) {
                Object attributeValue = var2.next();
                this.addAttribute(attributeValue);
            }
        }

        return this;
    }

    public ModelMap addAllAttributes(Map<String, ?> attributes) {
        if (attributes != null) {
            this.putAll(attributes);
        }

        return this;
    }

    public ModelMap mergeAttributes(Map<String, ?> attributes) {
        if (attributes != null) {
            Iterator var2 = attributes.entrySet().iterator();

            while(var2.hasNext()) {
                Entry<String, ?> entry = (Entry)var2.next();
                String key = (String)entry.getKey();
                if (!this.containsKey(key)) {
                    this.put(key, entry.getValue());
                }
            }
        }

        return this;
    }

    public boolean containsAttribute(String attributeName) {
        return this.containsKey(attributeName);
    }
}

3、使用 ModelAndView

    /**
     * 在ModelAndView里存入一个用户信息
     * @return ModelAndView
     */
    @GetMapping("returnModelAndView")
    public ModelAndView returnModelAndView(ModelAndView modelAndView){
        modelAndView.setViewName("hello");
        modelAndView.addObject("userInfo",new UserInfo("lomtom","123",new Address("湖南","邵阳")));
        return modelAndView;
    }

ModelAndView 顾名思义就是模型和试图的结合。 ModelAndView 源码:

public class ModelAndView {
    private Object view;
    private ModelMap model;
    private HttpStatus status;
    private boolean cleared = false;

	......
}

四:编写 html

首先,写一个链接,请求returnModelAndView请求。

<a href="returnModelAndView">ModelAndView</a>

然后,写 hello.html 页面用于验证

<h2>你好啊,你成功了</h2>
<p
  th:text="${userInfo.userName}+'来自'+${userInfo.address.province}+${userInfo.address.city}"
></p>

五:结果

六:记录我遇到的问题

问题 1:配置好一切后,thymeleaf 无法解析,所有关于 thymeleaf 的显示都无法生效。 解决:由于我配置了 spring 的视图解析,所以导致 thymeleaf 的试图解析无法生效,所以去掉 spring 的视图解析。

thmelaf 介绍 Springmvc 的视图解析: 快速浏览其属性足以了解其配置方式:

  • viewClass 建立 View 实例的类。对于 JSP 解析器,这是必需的,但是当我们与 Thymeleaf 合作时,根本不需要。
  • prefix 与 suffixThymeleaf 的 TemplateResolver 对象中相同名称的属性的工作方式相似。
  • order 确定在链中查询 ViewResolver 的顺序。
  • viewNames 允许使用此 ViewResolver 解析视图名称(带通配符)。

问题 2:前端显示乱码,具体表现为后台传入的不乱码,但是 html 中原本存在的乱码。 解决:在试图解析器和模板解析器中加入参数:<property name="characterEncoding" value="UTF-8"/>

作者有话

我写的可能并不怎么详细,详细配置请查看 thymeleaf 官方介绍:传送门 🔗,到最后,看都看完了,如果对你有帮助,请点个赞吧。

Copyright

本文为原创内容,欢迎分享与引用,请保留作者与原文链接。

文章标题

【springmvc thymeleaf】springmvc整合thymeleaf

作者

lomtom

发布方式

原创发布

原文链接 https://lomtom.cn/springmvc-thymeleafspringmvc整合thymeleaf