补:在Spring Boot 当中使用 Thymeleaf 视图解析器

news2024/11/15 20:06:50

补:在Spring Boot 当中使用 Thymeleaf 视图解析器

想要在 Spring Boot 当中使用 Thymeleaf 视图,就需要导入相关的 jar 依赖。在 pom.xml 文件中配置

在这里插入图片描述

<!--        引入 thymeleaf-start ,项目会自动完成配置,-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

在 Spring Boot当中的 Thymeleaf 相关的类是 :ThymeleafProperties.java 类。

在这里插入图片描述

注意:路径不可以随便改,要按照要求来,或者通过 application.yaml 进行修改。

在这里插入图片描述

spring:
  thymeleaf:
    prefix: "classpath:/填写自己想要的路径目录"
    # classpath:/ 类路径起手

对应 HTML页面上想要使用上 Thymeleaf 语法的需要加上如下的一行内容,才行。

在这里插入图片描述

<html lang="en" xmlns:th="http://www.thymeleaf.org">

案例举例:

在 pom.xml 文件当中,导入相关的 jar 包文件。

在这里插入图片描述

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>springboot_usersys</artifactId>
    <version>1.0-SNAPSHOT</version>


    <!--    导入SpringBoot 父工程-规定写法-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <!--    导入web项目场景启动器:会自动导入和web开发相关的jar包所有依赖【库/jar】-->
    <!--    后面还会在说明spring-boot-starter-web 到底引入哪些相关依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--        引入 thymeleaf-start ,项目会自动完成配置,-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--  引入 lombok 插件      -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

编写相关项目的启动场景。

在这里插入图片描述

package com.rainbowsea.springboot;


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

@SpringBootApplication // 项目启动标志
public class Application {

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

对应的 Bean 类

在这里插入图片描述

package com.rainbowsea.springboot.bean;


import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor  // 无参数
public class Admin {
    private String name;
    private String password;

}

package com.rainbowsea.springboot.bean;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor // 无参数
@AllArgsConstructor  // 全参数
public class User {
    private Integer id;
    private String name;
    private String password;
    private Integer age;
    private String email;

}

编写相关 thymeleaf 视图,HTML文件。

在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>管理后台</title>
</head>
<body>
<a href="#">返回管理界面</a> <a href="#">安全推出</a>


<hr>
<div style="text-align: center">
    <h1>管理员</h1>
    <table border="1px" cellspacing="0" bordercolor="green" style="text-align: center">
        <tr bgcolor="pink">
            <td>id</td>
            <td>name</td>
            <td>pwd</td>
            <td>email</td>
            <td>age</td>
        </tr>
        <tr bgcolor="#7fffd4" style="text-align: center" th:each="user:${users}">
            <td th:text="${user.id}"></td>
            <td th:text="${user.name}"></td>
            <td th:text="${user.password}"></td>
            <td th:text="${user.email}"></td>
            <td th:text="${user.age}"></td>
        </tr>
    </table>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<div style="text-align: center">
    <h1>用户登录</h1>
    <form action="#" th:action="@{/login}" method="post">
        <label style="color: red" th:text="${msg}"></label><br>
        用户名: <input type="text" style="width: 150px" name="name"><br>
        密码: <input type="password" style="width: 150px" name="password"><br>
        <input type="submit" value="登录"><br>
        <input type="reset" value="重新填写"><br>
    </form>
</div>

</body>
</html>

相关的 controller 控制器,处理请求内容。

在这里插入图片描述

package com.rainbowsea.springboot.controller;


import com.rainbowsea.springboot.bean.Admin;
import com.rainbowsea.springboot.bean.User;
import com.sun.org.apache.xpath.internal.operations.Mod;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.jws.WebParam;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;

@Controller
public class AdminController {


    @PostMapping("/login")
    public String login(Admin admin, HttpSession session, Model model) {




        // 验证用户是否合法
        if(StringUtils.hasText(admin.getName()) && "666".equals(admin.getPassword())) {
            // 将登录用户保险到 session会话域当中
            session.setAttribute("loginAdmin",admin);

            // 合法,重定向到manage.html
            // 请小伙伴回忆,Java web ,不使用请求转发是防止刷新页面会重复提交
            // 这里老师为什么写的是 manage.html,因为这样可以更加明确的表示到哪个页面
            // manage.html 表示要去找方法的映射路径为: manage.html
            return "redirect:/manage.html";
        } else {
            // 不合法,就重新登录,请求转发
            model.addAttribute("msg","账号/用户错误");
            return "adminLogin";  // 视图解析
        }

    }

    // 处理用户的请求到 manage.html
    // 是重定向——>get
    @GetMapping("/manage.html")
    public String mainPage(Model model,HttpSession session){

        // 可以这里集合~模板数据,放入到request域中,并显示
        ArrayList<User> users = new ArrayList<>();
        users.add(new User(1,"关羽","666",28,"gy@ohu.com"));
        users.add(new User(2,"关羽","666",28,"gy@ohu.com"));
        users.add(new User(3,"关羽","666",28,"gy@ohu.com"));
        users.add(new User(4,"关羽","666",28,"gy@ohu.com"));
        users.add(new User(5,"关羽","666",28,"gy@ohu.com"));
        model.addAttribute("users",users);  // 放入到请求域当中
        return "manage";  // 视图解析器

        // 拦截器处理
        // 获取到 session会话域当中的信息,判断用户是否登录过,进行一个过滤
        /*Object loginAdmin = session.getAttribute("loginAdmin");
        if(null != loginAdmin) {  // 说明成功登录过
            // 可以这里集合~模板数据,放入到request域中,并显示
            ArrayList<User> users = new ArrayList<>();
            users.add(new User(1,"关羽","666",28,"gy@ohu.com"));
            users.add(new User(2,"关羽","666",28,"gy@ohu.com"));
            users.add(new User(3,"关羽","666",28,"gy@ohu.com"));
            users.add(new User(4,"关羽","666",28,"gy@ohu.com"));
            users.add(new User(5,"关羽","666",28,"gy@ohu.com"));
            model.addAttribute("users",users);  // 放入到请求域当中

            return "manage";  // 视图解析器
        } else {
            // 说明没有登录过,
            // 这里就返回登录页,并给出提示
            model.addAttribute("msg","你没有登录/请登录");  // 请求域
            return "adminLogin"; // 请求转发到 adminLogin.html视图解析
        }*/


    }
}

package com.rainbowsea.springboot.controller;


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

@Controller
public class IndexController {

    // 编写方法,转发到登录页面
    /*
    解释:
    1.因为我们引入了 starter-thymeleaf
    2.这里就会直接使用视图解析到thymeleaf下的模板文件admin
     */
    @GetMapping(value = {"/","/login"})
    public String login(){
        return "adminLogin";
    }
}

配置的相关拦截器:

在这里插入图片描述

package com.rainbowsea.springboot.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 为了让大家看到访问的URI
        String requestURI = request.getRequestURI();
        String requestURL = request.getRequestURL().toString();
        log.info("preHandle 拦截到的请求URI={}", requestURI);
        log.info("preHandle 拦截到的请求URL={}", requestURL);

        // 进行登录的校验
        HttpSession session = request.getSession();
        Object loginAdmin = session.getAttribute("loginAdmin");
        if (null != loginAdmin) { // 说明该用户已经成功登录
            // 返回 true 就是放行
            return true;
        } else {
            // 拦截,重新返回到登录页面
            request.setAttribute("msg", "你没有登录/请登录~~~");
            // 注意:因为这里我们只有一个内容被拦截了,而且该内容的 uri路径就是我们要跳转进入的路径
            request.getRequestDispatcher("/").forward(request, response);  // 重定向
            return false; // 拦截了,不放行

        }


    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle执行了...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion执行了...");

    }
}
// HandlerInterceptor

在这里插入图片描述

package com.rainbowsea.springboot.config;


import com.rainbowsea.springboot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration  // 配置拦截器
public class WebConfig
/*        implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截器LoginInterceptor
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")  // 拦截所有的请求
                .excludePathPatterns("/","/login","/images/**"); // 还要放行视图的内容,因为上面是
        // 拦截所有,注意不要: templates ,因为sprinboot的默认配置,就是以templates为根路径往下找的
        // 所以添加就错了,就成了 /templates/templates/images/**了。

    }*/
{

    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                System.out.println("addInterceptors~~~");
                // 注册拦截器
                registry.addInterceptor(new LoginInterceptor())
                        .addPathPatterns("/**")
                        .excludePathPatterns("/","/login","/images/**");
            }
        };
    }
}

启动程序,打开浏览器运行测试

在这里插入图片描述


最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2130425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MPU6050移植DMP读出三轴角度

先决条件 MPU6050移植完成&#xff0c;能够正确读出加速度和陀螺仪原始数据 DMP移植 官方包代码复制 解压demo&#xff0c;打开motion_driver_6.12\arm\STM32F4_MD6\Projects\eMD6\core\driver&#xff0c;复制路径下的eMPL到自己工程 代码移植 需要修改的有三个文件&am…

GD32/STM32启动过程

GD32/STM32启动过程 文章目录 GD32/STM32启动过程前言一、系统架构二、自举配置三、启动文件四、启动流程总结 前言 本文以STM32F407为例简单介绍其启动过程。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、系统架构 STM32F407的系统架构如图所…

libyuv之linux编译

文章目录 一、下载源码二、编译源码三、注意事项1、银河麒麟系统&#xff08;aarch64&#xff09;&#xff08;1&#xff09;解决 armv8-adotprodi8mm 指令集支持问题&#xff08;2&#xff09;解决 armv9-asve2 指令集支持问题 一、下载源码 到GitHub网站下载https://github.…

【JAVA】Undertow的使用及性能优化,以及Undertow与Tomcat的对比

文章目录 Undertow优势Undertow使用Undertow性能优化线程池配置缓冲区和内存使用连接和请求超时禁用无关的设置编程式配置启用HTTP/2 Undertow与Tomcat的对比 更多相关内容可查看 当你进行Tomcat调优发现在怎么调都无法满足需求的时候&#xff0c;Undertow容器在性能和内存上都…

盘点2024年大家都在用的短视频剪辑工具

你现在休息的时间是不是都靠短视频来消遣&#xff1f;看着看着你就会发现短视频制作好像我也可以了吧&#xff1f;这次我就介绍一些简单好操作的短视频剪辑工具。 1.FOXIT视频剪辑 连接直达>>https://www.pdf365.cn/foxitclip/ 短视频剪辑其实也不难&#xff0c;只需…

MySql-表的内外连接

文章目录 前言一、内连接二、外连接1.左外连接2.右外连接 前言 表的内外连接跟我们上节课讲的笛卡尔积很相似。 一、内连接 格式&#xff1a;select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件&#xff1b; 例如&#xff1a;显示SMITH的名字和部门名称 二、外…

RB-SQL:利用检索LLM框架处理大型数据库和复杂多表查询的NL2SQL

NL2SQL的任务是将自然语言问题转换为SQL查询&#xff0c;以便从数据库中获取答案。现有LLM来指导SQL生成的方法在处理大型数据库和复杂多表查询时存在挑战&#xff0c;尤其是在处理冗余信息和提高提示工程效率方面。 (a) 利用大型语言模型&#xff08;LLM&#xff09;解决文本…

ctfshow-web入门-sql注入(web249-web253)nosql 注入

目录 1、web249 2、web250 3、web251 4、wen252 5、web253 1、web249 开始nosql,flag在flag中 $user $memcache->get($id); 使用 Memcache 类的 get 方法从缓存中获取数据&#xff0c;$id 是传入的键&#xff0c;用于从缓存中获取与该键对应的值&#xff0c;结果存储…

明基相机sd卡格式化还能恢复数据吗?可以这样操作

随着数字摄影的普及&#xff0c;相机SD卡已成为我们记录生活点滴的重要载体。然而&#xff0c;不小心将SD卡格式化&#xff0c;导致珍贵照片和视频瞬间消失&#xff0c;无疑是摄影爱好者的一大噩梦。面对这样的突发情况&#xff0c;许多朋友可能会感到无助与绝望。但实际上&…

【计算机组成原理】概述+数制与编码

目录 计算机组成原理概述计算机基本组成计算机系统的层次结构计算机性能指标 数制与编码进位计数制及其相互转换数据的编码与表示校验码 计算机组成原理概述 计算机基本组成 运算器、控制器、存储器、输入输出设备 运算器&#xff1a;完成数据的暂存、变换、算术运算和逻辑…

OpenCV结构分析与形状描述符(23)确定一个点是否位于多边形内的函数pointPolygonTest()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 进行点在轮廓内的测试。 该函数确定点是在轮廓内、轮廓外&#xff0c;还是位于一条边上&#xff08;或与顶点重合&#xff09;。它返回正值&…

【可变参模板】基类参数包的展开

一、基类参数包的展开 1.1基类参数包的展开 C C C是一个支持多继承的语言&#xff0c;因此继承的类也可以是一个基类的参数包 注意继承的语法是 p u b l i c : c l a s s . . . public: class ... public:class...&#xff0c;需要补充 . . . ... ...作为基类参数包的标志。…

Linux 驱动编写框架 并编译导入开发板

向内核新加文件&#xff1a;例如 demo1.c 1. 创建并编辑新的文件 #include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/kdev_t.h> #include …

Qt控制开发板的LED

Qt控制开发板的LED 使用开发板的IO接口进行控制是嵌入式中非常重要的一点&#xff0c;就像冯诺依曼原理说的一样&#xff0c;一个计算机最起码要有输入输出吧&#xff0c;我们有了信息的接收和处理&#xff0c;那我们就要有输出。 我们在开发板上一般都是使用开发板的GPIO接口…

vue3使用provide和inject传递异步请求数据子组件接收不到

前言 一般接口返回的格式是数组或对象&#xff0c;使用reactive定义共享变量 父组件传递 const data reactive([])// 使用settimout模拟接口返回 setTimeout(() > {// 将接口返回的数据赋值给变量Object.assign(data, [{ id: 10000 }]) }, 3000);provide(shareData, dat…

02请求响应(简单参数)

一、操作目的 前端通过post/get请求&#xff0c;传递给后端简单的数据&#xff0c;后端接收后在控制台打印出来&#xff0c;并将结果返回给前端页面展示出来。&#xff08;这里我们用postman来模拟前端页面&#xff0c;而非真实的通过编写前端代码&#xff0c;通过浏览器来展示…

Docker数据挂载本地目录

docker内的数据映射可以不通过数据卷&#xff0c;直接映射到本地的目录。下面将以mysql容器示例&#xff0c;完成容器的数据映射。 注意&#xff1a;每一个不同的镜像&#xff0c;将来创建容器后内部有哪些目录可以挂载&#xff0c;可以参考DockerHubDocker Hub Container Ima…

求树上任意两个点的距离lca

前言&#xff1a;一开始看到这个题目的时候&#xff0c;感觉就和lca有关&#xff0c;但是没有想到具体的公式 d d e p [ x ] d e p [ y ] − 2 ∗ d e p [ l c a ( x , y ) ] d dep[x] dep[y] - 2*dep[lca(x,y)] ddep[x]dep[y]−2∗dep[lca(x,y)] 并且我们这个题目还是一个…

[数据集][目标检测]烟叶病害检测数据集VOC+YOLO格式612张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;612 标注数量(xml文件个数)&#xff1a;612 标注数量(txt文件个数)&#xff1a;612 标注类别…

【重学 MySQL】二十六、内连接和外连接

【重学 MySQL】二十六、内连接和外连接 内连接&#xff08;INNER JOIN&#xff09;外连接&#xff08;OUTER JOIN&#xff09;总结 在MySQL中&#xff0c;内连接和外连接是两种常见的表连接方式&#xff0c;它们在处理多个表之间的关系时发挥着重要作用。 内连接&#xff08;I…