springboot学习10

一、模板引擎Thymeleaf

1)资源定位(模板来源 ):
	通用资源抽象
		文件资源: File
		ClassPath资源: ClassLoader 
		统一资源: URL
		Web资源: ServletContext
	Spring 资源抽象:
		Spring 资源: Resource
2)渲染上下文(变量来源 ) 
	不同的实现
		Context :Thyemeaf 渲染上下文 
		Model :Spring Web MVC 模型
		Attribute :Servlet 上下文
3)模板引擎(模板渲染) 
	ITemplateEngine 实现
		TemplateEngine :Thymeleaf 原生实现 
		SpringTemplateEngine :Spring 实现 
		SpringWebFluxTemplateEngine :Spring WebFlux 实现

二、Thymeleaf 与 Spring 资源整合
这里以多模块构建工程。springboot-view。
pom.xml 继承 父 pom.xml。
父 pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>springboot-view</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springbootlearn</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springbootlearn</name>
    <description>Demo project for Spring Boot</description>

 <repositories>
        <repository>
            <id>central</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        </repository>
    </repositories>
 
    <pluginRepositories>
        <pluginRepository>
            <id>central</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        </pluginRepository>
    </pluginRepositories>

    <properties>
        <java.version>1.8</java.version>
        <docker.image.prefix>springboot</docker.image.prefix>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
         </dependencies>
    <build>
    </build>

</project>

springboot-view的pom.xml引入thymeleaf相关依赖:

<!-- thymeleaf-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<packaging>war</packaging>

新建一个 Thymeleaf 引导类:

package com.example.web.template.engine;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Thymeleaf 引导类
 */
public class ThymeleafTemplateEngineBootstrap {
    
    

    public static void main(String[] args) throws IOException {
    
    
        // 构建引擎
        SpringTemplateEngine templateEngine = new SpringTemplateEngine(); // 创建渲染上下文
        Context context = new Context();
        context.setVariable("demomessage", "hello,Thymeleaf");
        // 模板的内容,可通过文件方式或者读取
        // 读取内容从 templates/thymeleaf/hellothymeleaf.html
        // ResourceLoader
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        // classpath:/templates/thymeleaf/hellothymeleaf.html   Resource
        Resource resource = resourceLoader.getResource("classpath:/templates/thymeleaf/hellothymeleaf.html");
        File templateFile = resource.getFile();
        // 文件流
        FileInputStream fileInputStream = new FileInputStream(templateFile);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        //copy
        IOUtils.copy(fileInputStream, byteArrayOutputStream);

        fileInputStream.close();
        // 模板的内容,可通过文件方式或者读取
//        String content = "<p th:text=\"${demomessage}\">!!!</p>";
        String content = byteArrayOutputStream.toString("UTF-8");
        // 渲染(处理)结果
        String result = templateEngine.process(content, context);
        // 输出渲染(处理)结果
        System.out.println(result);
    }
}

运行即可。

三、视图处理
1、SpringWebMVC 视图组件

ViewResolver :视图解析器
View : 视图组件 
DispatcherServlet :总控

2、Thymeleaf 整合 Spring Web MVC

ViewResolver : ThymeleafViewResolver 
View : ThymeleafView
ITemplateEngine : SpringTemplateEngine

交互流程:

DispatcherServlet->ViewResolver(如果多个,优先级处理)->View->DispatcherServlet->视图内容(html、xml等)

多视图处理器并存
1) ThymeleafViewResolver 视图处理器:
新建一个HelloThymeleafController:

package com.example.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;

/**
 * {@link Controller}
 */
@Controller
public class HelloThymeleafController {
    
    

    @GetMapping("/hellothymeleaf")
    public String helloThymeleaf() {
    
    
        return "hellothymeleaf";
    }

    @ModelAttribute("demomessage")
    public String message() {
    
    
        return "demomessage,thymeleaf.......";
    }
}

新建一个SpringBootViewBootstrap:

package com.example.web.bootstrap;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * springboot 视图引导类
 */
@SpringBootApplication(scanBasePackages = "com.example.web")
public class SpringBootViewBootstrap {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(SpringBootViewBootstrap.class, args);
    }
}

新建一个application.properties:
Thymeleaf相关属性可以查看

package org.springframework.boot.autoconfigure.thymeleaf;

下的ThymeleafProperties.java文件。
在application.properties中修改属性值。
如:

#thymeleaf
spring.thymeleaf.prefix=classpath:/templates/thymeleaf/
spring.thymeleaf.suffix=.html
# 取消缓存
spring.thymeleaf.cache=false

新建一个hellothymeleaf.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
    <p th:text="${demomessage}">~~~~</p>
</body>
</html>

2)InternalResourceViewResolver视图处理器:

WebMvcConfig:

package com.example.web.config;

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;

/**
 * Spring web mvc 配置类
 */

@Configuration
//@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
    
    

    @Bean
    public ViewResolver myViewResolver() {
    
    
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        // 因为ThymeleafViewResolver ORDER Ordered.LOWEST_PRECEDENCE - 5
        // 所以若要在Thymeleaf之前,order比它小即可。
        viewResolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
        return viewResolver;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    
         registry.addInterceptor(new HandlerInterceptor() {
    
    
             @Override
             public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
                 System.out.println("拦截中。。。");
                 return true;
             }
         });
    }
	
	// 修复 Maven 多模块 JSP 定位问题。
	// Maven多模块,jsp无法读取。无法找到模块下的。src/main/webapp。
	// 因为会读到的路径是/Users/xxx/develop/springbootlearn/src/main/webapp
	// 而不是期望的 /Users/xxx/develop/springbootlearn/springboot-view/src/main/webapp
	// 加上这个方法以解决。
    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> customizer() {
    
    
        return (factory) -> {
    
    
            factory.addContextCustomizers((context) -> {
    
    
                        String relativePath = "springboot-view/src/main/webapp";
                        // 相对于 user.dir = /Users/xxx/develop/springbootlearn
                        File docBaseFile = new File(relativePath);
                        if(docBaseFile.exists()) {
    
     // 路径是否存在
                            // 解决 Maven 多模块 JSP 无法读取的问题
                            context.setDocBase(docBaseFile.getAbsolutePath());
                        }
                    }
            );
        };
    }
}

HelloThymeleafController:

package com.example.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * {@link Controller}
 */
@Controller
public class HelloThymeleafController {
    
    

    @RequestMapping("")
    public String index(@RequestParam(required = false,defaultValue = "0") int value, Model model) {
    
    
        return "index";
    }

    @GetMapping("/hellothymeleaf")
    public String helloThymeleaf() {
    
    
        return "hellothymeleaf";
    }

    @ModelAttribute("demomessage")
    public String message() {
    
    
        return "demomessage,thymeleaf.......";
    }
}

HelloThymeleafControllerAdvice:

package com.example.web.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@ControllerAdvice(assignableTypes = HelloThymeleafController.class)
public class HelloThymeleafControllerAdvice {
    
    

    @ModelAttribute("acceptLanguage")
    public String acceptLanguage(@RequestHeader("Accept-Language") String acceptLanguage){
    
    
        return acceptLanguage;
    }

    @ModelAttribute("jsessionId")
    public String jsessionId(@CookieValue(value = "JSESSIONID",required = false) String jsessionId){
    
    
        return jsessionId;
    }

    @ModelAttribute("hellomessage")
    public String message(){
    
    
        return "一段hellomessage。。。";
    }

    @ExceptionHandler(Throwable.class)
    public ResponseEntity<String> onException(Throwable throwable) {
    
    
        return ResponseEntity.ok(throwable.getMessage());
    }

}


```在src目录下,新建webapp目录。
```bash
└── src
    ├── main
    ├── resources
    └── webapp
        └── WEB-INF
            └── jsp
            	└── index.jsp

index.jsp:

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
    <body>
    <hellomessage>${hellomessage}</hellomessage>
    <language>${acceptLanguage}</language>
    <jsessionId>${jsessionId}</jsessionId>
    </body>
</jsp:root>

如果不在上面WebMvcConfig文件中加上处理方法:

	@Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> customizer() {
    
    
    // ...省略
    }

而通过maven插件打包,访问war包也可以。
在springboot-view的pom.xml加入:

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

运行:

mvn -Dmaven.test.skip -U clean package
java -jar target/springboot-view-0.0.1-SNAPSHOT.war

在浏览器输入localhost:8080即可。

猜你喜欢

转载自blog.csdn.net/tongwudi5093/article/details/113755153