SpringBoot开发Web应用集成Thymeleaf(官方推荐)

spring-boot-starter-web

Spring Boot提供了spring-boot-starter-web为Web开发予以支持,spring-boot-starter-web为我们提供了嵌入的Tomcat以及Spring MVC的依赖。

Spring MVC自动配置

Spring Boot为Spring MVC提供适用于多数应用的自动配置功能。在Spring默认基础上,自动配置添加了以下特性:

  1. 引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
  2. 对静态资源的支持,包括对WebJars的支持。
  3. 自动注册Converter,GenericConverter,Formatter beans。
  4. 对HttpMessageConverters的支持。
  5. 自动注册MessageCodeResolver。
  6. 对静态index.html的支持。
  7. 对自定义Favicon的支持。

如果想要自己完全控制WebMVC配置,就需要在@Configuration注解的配置类上增加@EnableWebMvc注解。增加该注解以后WebMvcAutoConfiguration中配置就不会生效,你需要自己来配置需要的每一项。这种情况下的配置还是要多看一下WebMvcAutoConfiguration类(上面7个默认配置就在此处设定)。

@EnableWebMvc
@Configuration
public class TestMvc {
    ···
}

如果想保留Spring Boot MVC的特性(应用默认配置),并只是添加自定义的MVC配置(拦截器,formatters,视图控制器等),你可以自定义一个配置类并继承WebMvcConfigurerAdapter类。在类中通过配置@Bean方法来注册自己想要的bean甚至是自定义的bean。或重写父类某一方法实现自己的处理逻辑

@Configuration
public class CustomizeWebMvcConfiguration extends WebMvcConfigurerAdapter {
        ···
    @Bean
    public BeanNameViewResolver beanNameViewResolver () {
        return  new BeanNameViewResolver(); // 示例代码
    }
  
   /* 一个道理
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
   </bean>
   */
  
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
       registry.addResourceHandler("/webjar/**").addResourceLocations("classpath:/webjar/");
        super.addResourceHandlers(registry);
    }

        ···
}

当你使用@EnableWebMvc来配置spring mvc时,会把WebMvcConfigurationSupport当成配置文件来用,将其中所有标识有@Bean注解的方法配置成bean,这就成了Spring mvc的默认配置

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
        ····
}

各个组件都是可以定制化的,在WebMvcConfigurationSupport是通过模板方法模式来实现的,在各个发布成Bean的方法中(@Bean),都调用了自定义组件的抽象方法,所以可以在其在子类中对这些组件进行覆盖,如:

  • 对HandlerAdapter组件,有addInterceptors(InterceptorRegistry registry)可以添加自己的拦截器;

  • 对conversionService组件,有addFormatters(FormatterRegistry registry)可以添加自己的类型转换器;

    ···

从而实现定制化。

上面提到子类,Spring mvc提供的默认实现是DelegatingWebMvcConfiguration,覆盖父类的方法之前,它会寻找容器中所有的WebMvcConfigurer实现类,将所有WebMvcConfigurer实现类中的配置组合起来,组成一个超级配置,再对WebMvcConfigurationSupport中对应的发布成Bean的方法进行覆盖。这样,WebMvcConfigurationSupport中的bean配置发布时,就会把这所有自定义配置都带上了。

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
        ···
}

总的来说就是,WebMvcConfigurationSupport负责bean的发布。分派自己的子类DelegatingWebMvcConfiguration去寻找用户所有实现了WebMvcConfigurer接口的实现类。并将用户所有发布成Bean的方法组合起来。交还给WebMvcConfigurationSupport统一发布并配置。

参考:Spring mvc注解配置的背后

静态文件

默认情况下,Spring Boot从classpath下一个叫/static(/public,/resources或/META-INF/resources)的文件夹或从ServletContext根目录提供静态内容。(这几个都是静态资源的映射路径,优先级顺序为:META-INF/resources > resources > static > public)

对应的配置文件配置如下:

# 默认映射,默认值为 /**
spring.mvc.static-path-pattern=
# 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
spring.resources.static-locations=这里设置要指向的路径,多个使用英文逗号隔开

可以通过修改spring.mvc.static-path-pattern来修改默认的映射,例如改成/thymeleaf/**,那运行的时候访问 http://lcoalhost:8080/thymeleaf/index.html 才对应到index.html页面。

这使用了Spring MVC的ResourceHttpRequestHandler,所以你可以通过添加自己的WebMvcConfigurerAdapter并覆写addResourceHandlers方法来改变这个行为(加载静态文件)。

在一个单独的web应用中,容器默认的servlet是开启的,如果Spring决定不处理某些请求,默认的servlet作为一个回退(降级)将从ServletContext根目录加载内容。大多数时候,这不会发生(除非你修改默认的MVC配置),因为Spring总能够通过DispatcherServlet处理请求。

此外,上述标准的静态资源位置有个例外情况是Webjars内容。任何在/webjars/**路径下的资源都将从jar文件中提供,只要它们以Webjars的格式打包。

:如果你的应用将被打包成jar,那就不要使用src/main/webapp文件夹。尽管该文件夹是一个共同的标准,但它仅在打包成war的情况下起作用,并且如果产生一个jar,多数构建工具都会静悄悄的忽略它

默认实现类:

class WebMvcConfigurerComposite implements WebMvcConfigurer {
                ···
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        for (WebMvcConfigurer delegate : this.delegates) {
            delegate.addResourceHandlers(registry);
    }
                ···
}
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
            ···
    @Bean
    public HandlerMapping resourceHandlerMapping() {
        ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext,
                this.servletContext, mvcContentNegotiationManager());
         // 关键代码
        addResourceHandlers(registry); 
      
        AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
        if (handlerMapping != null) {
            handlerMapping.setPathMatcher(mvcPathMatcher());
            handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
            handlerMapping.setInterceptors(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
            handlerMapping.setCorsConfigurations(getCorsConfigurations());
        }
        else {
            handlerMapping = new EmptyHandlerMapping();
        }
        return handlerMapping;
    }
                ···
}

扩展类:

public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
                ···
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    }
                ···
}

模板引擎

Spring Boot支持多种模版引擎包括:

  • FreeMarker
  • Groovy
  • Thymeleaf(官方推荐)

JSP技术Spring Boot官方是不推荐的:

  1. Tomcat 只支持war的打包方式,不支持可执行的jar。
  2. Jetty 嵌套的容器不支持jsp
  3. Undertow
  4. 创建自定义error.jsp页面不会覆盖错误处理的默认视图,而应该使用自定义错误页面

当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates

Thymeleaf模板引擎

Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。与其它模板引擎相比,Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用。它的功能特性如下:


引入依赖

<!--thymeleaf模板引擎 -->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

需要注意的是:

spring-boot-starter-thymeleaf会自动包含spring-boot-starter-web,所以我们就不需要单独引入web依赖了。

Model

@Data
@AllArgsConstructor
public class User {
    private String username;
    private String password;
}

Controller

@Controller
@RequestMapping(value = "/thymeleaf")
public class ThymeleafController {

    @RequestMapping(path = "/", method = RequestMethod.GET)
    public ModelAndView index() {
        List<User> userList = new ArrayList<User>();
        User user = new User("jyg", "jyg");
        userList.add(user);
        user = new User("lyn", "lyn");
        userList.add(user);
        ModelAndView modelAndView = new ModelAndView("index.html");
        modelAndView.addObject("userList", userList);
        return modelAndView;
    }
}

Html

  1. 首先通过xmlns:th=”http://www.thymeleaf.org“ 命名 thymeleaf 空间,将静态页面转换为动态的视图,需要进行动态处理的元素将使用“th:”前缀。
xmlns:th="http://www.thymeleaf.org"
  1. 代码:

    <body>
    <h1>Thymeleaf</h1>
    <hr/>
        <table class="table table-striped table-bordered table-hover">
            <tr class="info">
                <td>用户名</td>
                <td>密码</td>
            </tr>
            <!--/*@thymesVar id="userList" type=""*/-->
            <tr th:each="user : ${userList}" class="success">
                <td th:text="${user.username}">冀永光</td>
                <td th:text="${user.password}">jiyongguang.</td>
            </tr>
        </table>
    </body>
    

Thymeleaf 做到了什么

直接访问 index.html :

访问 http://localhost:8080/thymeleaf/

Thymeleaf 做到了不破坏 Html 自身内容的数据逻辑分离。

Thymeleaf的默认参数配置

# THYMELEAF (ThymeleafAutoConfiguration)
#开启模板缓存(默认值:true)
spring.thymeleaf.cache=true 
#Check that the template exists before rendering it.
spring.thymeleaf.check-template=true 
#检查模板位置是否正确(默认值:true)
spring.thymeleaf.check-template-location=true
#Content-Type的值(默认值:text/html)
spring.thymeleaf.content-type=text/html
#开启MVC Thymeleaf视图解析(默认值:true)
spring.thymeleaf.enabled=true
#模板编码
spring.thymeleaf.encoding=UTF-8
#要被排除在解析之外的视图名称列表,用逗号分隔
spring.thymeleaf.excluded-view-names=
#要运用于模板之上的模板模式。另见StandardTemplate-ModeHandlers(默认值:HTML5)
spring.thymeleaf.mode=HTML5
#在构建URL时添加到视图名称前的前缀(默认值:classpath:/templates/)
spring.thymeleaf.prefix=classpath:/templates/
#在构建URL时添加到视图名称后的后缀(默认值:.html)
spring.thymeleaf.suffix=.html
#Thymeleaf模板解析器在解析器链中的顺序。默认情况下,它排第一位。顺序从1开始,只有在定义了额外的TemplateResolver Bean时才需要设置这个属性。
spring.thymeleaf.template-resolver-order=
#可解析的视图名称列表,用逗号分隔
spring.thymeleaf.view-names=
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容