1.默认首页
访问项目时如何去访问Templates中的index.html文件?
默认的是去静态资源文件夹下,加载index.html页面,那么需要在创建一个方法借助Thymeleaf去跳转到我们Templates文件夹下的index.html页面。
@RequestMapping({"/","/index.html"})
public String findIndex() {
return "index";
}
这样我们在访问项目时:http://localhost:8080时;会跳转到templates文件夹下的index.html。但是SpringBoot不推荐这么做,而且每一个controller都需这么写,非常麻烦。以前我们在配置SpringMVC的xml文件,内容如下:
<!--使用注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:resources location="/statics/" mapping="/statics/**" />
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--上传文件的最大大小,单位为字节 -->
<property name="maxUploadSize" value="17367648787"></property>
<!-- 上传文件的编码 -->
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--重定向时,是否加上上下文路径-->
<property name="redirectContextRelative" value="true"/>
<!--配置解析前后缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--扫描所有handler(控制器)-->
SpringBoot推荐使用配置类的形式去配置:
WebMvcConfigurerAdapter在Spring5.0已经废弃,所以不推荐使用。取代的方法有两种:implements WebMvcConfigurer(SpringBoot官方推荐使用);extends WebMvcConfigurationSupport
第一种方法我们去实现WebMvcConfigurer,可以任意实现其中的方法,不会影响到我们SpringBoot自身的自动配置(@EnableAutoConfiguration),而使用第二种方法相当于覆盖了SpringBoot自动配置里面的所有的方法,每个方法我们去重新定义。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyAppconfig implements WebMvcConfigurer{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 路径为../wjz,访问index.html页面
registry.addViewController("/wjz").setViewName("index");
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
2.修改login页面
动态取获取连接的href和src
login页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Signin Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="asserts/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.5.0/css/bootstrap.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html" th:action="@{/user/login}" method="post">
<img class="mb-4" th:src="@{/asserts/img/bootstrap-solid.svg}" src="asserts/img/bootstrap-solid.svg" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<p style="color:red" th:text="${message}" th:if="${not #strings.isEmpty(message)}"></p>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" name="username" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" name="password" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me">[[#{login.remember}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<a class="btn btn-sm" th:href="@{/index.html(l=zh_CN)}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l=en_US)}">English</a>
</form>
</body>
</html>
引入bootstrap的css和普通css样式和图片 ,可在login里面找到
@{/webjars/bootstrap/4.5.0/css/bootstrap.css}
@{/asserts/css/signin.css}
@{/asserts/img/bootstrap-solid.svg}
3.国际化配置
在classpath下创建i18n文件夹;在i18n下创建三个配置国际化的文件(login_zh_CN.properties、login_en_US.properties、login.properties)
在文件中分别写入对应的属性,代码如下:点击中英文切换
#login.properties
login.tip=qdl
login.username=yhm
login.password=mm
login.remember=jzw
login.btn=dl
#login_zh_CN.properties
login.tip=请登录
login.username=用户名
login.password=密码
login.remember=记住我
login.btn=登陆
#login_en_US.properties
login.tip=Please Sign In
login.username=UserName
login.password=Password
login.remember=Remember Me
login.btn=Sign In
在application.properties文件中通知SpringBoot的路径基础名:
spring.messages.basename=i18n.login
修改页面,通过国际化取值,并进行动态赋值,longin页面,最下方中文和English
<form class="form-signin" action="dashboard.html">
<img class="mb-4" src="asserts/img/bootstrap-solid.svg" th:src="@{/asserts/img/bootstrap-solid.svg}" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<label class="sr-only" th:text="#{login.username}">Username</label>
<input type="text" class="form-control" placeholder="Username" th:placeholder="#{login.username}" required="" autofocus="">
<label class="sr-only" th:text="#{login.password}">Password</label>
<input type="password" class="form-control" placeholder="Password" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> [[#{login.remember}]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<a class="btn btn-sm" th:href="@{/index.html(l=zh_CN)}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l=en_US)}">English</a>
</form>
4.手动切换国际化
提交请求并提交参数,把l=zh_CN和l=en_US提交给后台
<a class="btn btn-sm" th:href="@{/index.html(l=zh_CN)}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l=en_US)}">English</a>
自定义一个MyLocaleResolver去实现LocaleResolver接口,实现resolverLocale()方法,实现路径切换
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.LocaleResolver;
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
// 从请求中拿到数据
// 从request取值th:href="@{/index.html(l=en_US)},这里为l,因为l=en_US
String l = request.getParameter("l");
String[] split = null;
Locale locale = Locale.getDefault();
if (l != null) {
split = l.split("_");// zh_CN,{zh,CN}或l=en_US,{en,US}
locale = new Locale(split[0], split[1]);
}
// 返回通过配置文件的配置找到il8n下的配置文件
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
注册一个LocaleResolver,并且注入到IOC容器中,让Spring解析上方重写的方法,实现切换
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.school.demo.coponent.MyLocaleResolver;
@Configuration
public class MyAppconfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 路径为../wjz,访问index.html页面
registry.addViewController("/wjz").setViewName("index");
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
}
// 返回MyLocaleResolver重写的方法
@Bean
public LocaleResolver localeResolver() {
return new MyLocaleResolver();
}
}
5.登录
实现登录功能:现在虚拟登录,不做真实的数据交互,用户名任意,密码为123456
controller
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class LoginController {
@PostMapping("/user/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password) {
if (username != null && password.equals("123456")) {
return "dashboard";
}
return "login";
}
}
dashboard.html页面
<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="asserts/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="asserts/css/dashboard.css" rel="stylesheet">
<style type="text/css">
/* Chart.js */
@-webkit-keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
@keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
.chartjs-render-monitor {
-webkit-animation: chartjs-render-animation 0.001s;
animation: chartjs-render-animation 0.001s;
}
</style>
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">欢迎[[${session.loginName}]]先生/女士</a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
</li>
</ul>
</nav>
<div class="container-fluid">
<div class="row">
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
Dashboard <span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
<polyline points="13 2 13 9 20 9"></polyline>
</svg>
Orders
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
</svg>
Products
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" th:href="@{/list.html}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
Employees
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bar-chart-2">
<line x1="18" y1="20" x2="18" y2="10"></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg>
Reports
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg>
Integrations
</a>
</li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Saved reports</span>
<a class="d-flex align-items-center text-muted" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
</a>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Current month
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Last quarter
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Social engagement
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Year-end sale
</a>
</li>
</ul>
</div>
</nav>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<div class="chartjs-size-monitor" style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;">
<div class="chartjs-size-monitor-expand" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
<div style="position:absolute;width:1000000px;height:1000000px;left:0;top:0"></div>
</div>
<div class="chartjs-size-monitor-shrink" style="position:absolute;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1;">
<div style="position:absolute;width:200%;height:200%;left:0; top:0"></div>
</div>
</div>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<button class="btn btn-sm btn-outline-secondary">Share</button>
<button class="btn btn-sm btn-outline-secondary">Export</button>
</div>
<button class="btn btn-sm btn-outline-secondary dropdown-toggle">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-calendar"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>
This week
</button>
</div>
</div>
<canvas class="my-4 chartjs-render-monitor" id="myChart" width="1076" height="454" style="display: block; width: 1076px; height: 454px;"></canvas>
</main>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="asserts/js/jquery-3.2.1.slim.min.js" ></script>
<script type="text/javascript" src="asserts/js/popper.min.js" ></script>
<script type="text/javascript" src="asserts/js/bootstrap.min.js" ></script>
<!-- Icons -->
<script type="text/javascript" src="asserts/js/feather.min.js" ></script>
<script>
feather.replace()
</script>
<!-- Graphs -->
<script type="text/javascript" src="asserts/js/Chart.min.js" ></script>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: false,
}
}
});
</script>
</body>
</html>
5.1.加入表单提交请求
5.2.后台实现登录请求
5.3.登录错误提示
开发期间模板引擎页面修改以后,需要实时生效:需要导入开发工具依赖
<!-- Eclipse 热部署开发工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
配置热部署的属性
#开启热部署
spring.devtools.restart.enabled=true
#classpath目录下的WEB-INF文件夹内容修改不重启
spring.devtools.restart.exclude=WEB-INF/**
校验用户名和密码是否正确,错误返回错误提示
@Controller
public class LoginController {
@PostMapping(value="/user/login")
public String login(@RequestParam("username")String username,
@RequestParam("password")String password,
Map<String,String> map) {
if(username != null && password.equals("123456")) {
return "dashboard";
}
//返回错误信息
map.put("message","用户名密码错误!");
return "login";
}
}
页面进行错误信息展示,login页面,在引入图片下方
<p style="color:red" th:text="${message}" th:if="${not #strings.isEmpty(message)}"></p>
5.4.防止表单重复提交使用重定向:
第一步:首先需要加入映射;
registry.addViewController("/main.html").setViewName("dashboard");
第二步:需要重定向后,向浏览器提交请求
if (username != null && password.equals("123456")) {
// 重定向:防止表单重复提交
return "redirect:/main.html";
}
5.5.添加拦截器,防止别人恶意访问:
1、登陆成功以后,session中绑定用户名和密码
@PostMapping("/user/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password,
Map<String, String> map, HttpSession session) {
if (username != null && password.equals("123456")) {
// username与loginName绑定到session中
session.setAttribute("loginName", username);
session.setAttribute("password", password);
// 重定向:防止表单重复提交
return "redirect:/main.html";
}
map.put("message", "用户名密码错误");
return "login";
}
2、在com.wjz.demo.component下创建拦截器LoginHandlerInterceptor,并且实现HandlerInterceptor,实现preHandle(目标方法执行之前,执行该方法)
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
//拦截器
public class LoginHandleinterceptor implements HandlerInterceptor {
/**
* 目标方法执行前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
Object loginName = request.getSession().getAttribute("loginName");
if (loginName == null) {
request.setAttribute("message", "没有权限,请先登录");
request.getRequestDispatcher("/index.html").forward(request, response);
return false;
} else {
return true;
}
}
/**
* 目标方法执行中
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* 目标方法执行后
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
3、在MyAppConfig类中添加拦截器方法,并且拦截所有访问,放行登录和静态资源路径,需要注意SpringBoot2.x以上版本会对静态资源进行拦截,而2.0以下不会拦截原因是Spring5.0的升级
@Configuration
public class MyAppconfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 路径为../wjz,访问index.html页面
//registry.addViewController("/wjz").setViewName("index");
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard");
}
/**
* SpringBoot2.0对静态资源访问进行拦截
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 将我们重写的拦截器交给IOC
registry.addInterceptor(new LoginHandleinterceptor())
// 拦截所有路径
.addPathPatterns("/**")
// 排除登录页、登录、所有静态资源和样式
.excludePathPatterns("/","index.html","/user/login","/webjars/**","/asserts/**");
}
// 返回MyLocaleResolver重写的方法
@Bean
public LocaleResolver localeResolver() {
return new MyLocaleResolver();
}
}
5.6.主页显示Company name,改为显示登陆者姓名
nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">欢迎[[${session.loginName}]]先生/女士</a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
6.Restful-CRUD
什么是Restful?
RestfulCRUD:CRUD满足Rest风格;
URI: /资源名称/资源标识 HTTP请求方式区分对资源CRUD操作
普通CRUD(uri来区分操作) | RestfulCRUD | |
---|---|---|
查询 | getEmp | emp---GET |
添加 | addEmp?xxx | emp---POST |
修改 | updateEmp?id=xxx&xxx=xx | emp/{id}---PUT |
删除 | deleteEmp?id=1 | emp/{id}---DELETE |
实验的请求架构;
实验功能 | 请求URI | 请求方式 |
---|---|---|
查询所有员工 | emps | GET |
查询某个员工(来到修改页面) | emp/id | GET |
来到添加页面 | emp | GET |
添加员工 | emp | POST |
来到修改页面(查出员工进行信息回显) | emp/id | GET |
修改员工 | emp | PUT |
删除员工 | emp/id | DELETE |
员工列表:thymeleaf公共页面元素抽取
1.抽取公共片段:© 2011 The Good Thymes Virtual Grocery
2.引入公共片段:~{templatename::selector}:模板名::选择器
~{templatename::fragmentname}:模板名::片段名
3.默认效果: insert的公共片段在div标签中
如果使用th:insert等属性进行引入,可以不用写~{}: 行内写法可以加上:[[~{}]];[(~{})]
三种引入公共片段的th属性:
th:insert:将公共片段整个插入到声明引入的元素中
th:replace:将声明引入的元素替换为公共片段
th:include:将被引入的片段的内容包含进这个标签中
6.1.列表
<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link href="asserts/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="asserts/css/dashboard.css" rel="stylesheet">
<style type="text/css">
/* Chart.js */
@-webkit-keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
@keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
.chartjs-render-monitor {
-webkit-animation: chartjs-render-animation 0.001s;
animation: chartjs-render-animation 0.001s;
}
</style>
</head>
<body>
<!-- 引入topbar
th:replace="资源路径 :: 片段名称"
-->
<div th:replace="dashboard :: topbar"></div>
<div class="container-fluid">
<div class="row">
<!-- 引入sidebar -->
<div th:replace="dashboard :: sidebar"></div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<h2>Section title</h2>
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>#</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>1,001</td>
<td>Lorem</td>
<td>ipsum</td>
<td>dolor</td>
<td>sit</td>
</tr>
<tr>
<td>1,002</td>
<td>amet</td>
<td>consectetur</td>
<td>adipiscing</td>
<td>elit</td>
</tr>
<tr>
<td>1,003</td>
<td>Integer</td>
<td>nec</td>
<td>odio</td>
<td>Praesent</td>
</tr>
<tr>
<td>1,003</td>
<td>libero</td>
<td>Sed</td>
<td>cursus</td>
<td>ante</td>
</tr>
<tr>
<td>1,004</td>
<td>dapibus</td>
<td>diam</td>
<td>Sed</td>
<td>nisi</td>
</tr>
<tr>
<td>1,005</td>
<td>Nulla</td>
<td>quis</td>
<td>sem</td>
<td>at</td>
</tr>
<tr>
<td>1,006</td>
<td>nibh</td>
<td>elementum</td>
<td>imperdiet</td>
<td>Duis</td>
</tr>
<tr>
<td>1,007</td>
<td>sagittis</td>
<td>ipsum</td>
<td>Praesent</td>
<td>mauris</td>
</tr>
<tr>
<td>1,008</td>
<td>Fusce</td>
<td>nec</td>
<td>tellus</td>
<td>sed</td>
</tr>
<tr>
<td>1,009</td>
<td>augue</td>
<td>semper</td>
<td>porta</td>
<td>Mauris</td>
</tr>
<tr>
<td>1,010</td>
<td>massa</td>
<td>Vestibulum</td>
<td>lacinia</td>
<td>arcu</td>
</tr>
<tr>
<td>1,011</td>
<td>eget</td>
<td>nulla</td>
<td>Class</td>
<td>aptent</td>
</tr>
<tr>
<td>1,012</td>
<td>taciti</td>
<td>sociosqu</td>
<td>ad</td>
<td>litora</td>
</tr>
<tr>
<td>1,013</td>
<td>torquent</td>
<td>per</td>
<td>conubia</td>
<td>nostra</td>
</tr>
<tr>
<td>1,014</td>
<td>per</td>
<td>inceptos</td>
<td>himenaeos</td>
<td>Curabitur</td>
</tr>
<tr>
<td>1,015</td>
<td>sodales</td>
<td>ligula</td>
<td>in</td>
<td>libero</td>
</tr>
</tbody>
</table>
</div>
</main>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript" src="asserts/js/jquery-3.2.1.slim.min.js"></script>
<script type="text/javascript" src="asserts/js/popper.min.js"></script>
<script type="text/javascript" src="asserts/js/bootstrap.min.js"></script>
<!-- Icons -->
<script type="text/javascript" src="asserts/js/feather.min.js"></script>
<script>
feather.replace()
</script>
<!-- Graphs -->
<script type="text/javascript" src="asserts/js/Chart.min.js"></script>
<script>
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
datasets: [{
data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
lineTension: 0,
backgroundColor: 'transparent',
borderColor: '#007bff',
borderWidth: 4,
pointBackgroundColor: '#007bff'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
}
}]
},
legend: {
display: false,
}
}
});
</script>
</body>
</html>
将dashboard的一个模块改为自己的路径
<li class="nav-item">
<!-- 修改路径和跳转 -->
<a class="nav-link" href="#" th:href="@{/list.html}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-users">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
<!-- 修改模块名 -->
Employees
</a>
</li>
添加映射
registry.addViewController("/list.html").setViewName("list");
6.2.抽取公共样式
声明topbar片段
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">欢迎[[${session.loginName}]]先生/女士</a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
</li>
</ul>
</nav>
映射修改
registry.addViewController("/list.html").setViewName("emp/list");
list引入topbar样式
<!-- 引入topbar
th:replace="资源路径 :: 片段名称"
-->
<div th:replace="dashboard :: topbar"></div>
列表引入自己的样式
//dashboard模块
<div class="container-fluid">
<div class="row">
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
Dashboard <span class="sr-only">(current)</span>
</a>
</li>
// list模块
<!-- 引入topbar
th:replace="资源路径 :: 片段名称"
-->
<div th:replace="dashboard :: topbar"></div>
<div class="container-fluid">
<div class="row">
<!-- 引入sidebar -->
<div th:replace="dashboard :: sidebar"></div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<h2>Section title</h2>
返回首页,改链接地址main.html
<li class="nav-item">
<a class="nav-link active" href="#" th:href="@{/main.html}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
Dashboard <span class="sr-only">(current)</span>
</a>
</li>
把topbar和sidebar抽取出来到bar.html,在引入
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0"
th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">欢迎[[${session.loginName}]]先生/女士</a>
<input class="form-control form-control-dark w-100" type="text"
placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign
out</a></li>
</ul>
</nav>
<nav class="col-md-2 d-none d-md-block bg-light sidebar"
th:fragment="sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link active" href="#"
th:href="@{/main.html}"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg> Dashboard <span class="sr-only">(current)</span>
</a></li>
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-file">
<path
d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
<polyline points="13 2 13 9 20 9"></polyline>
</svg> Orders
</a></li>
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-shopping-cart">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path
d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
</svg> Products
</a></li>
<li class="nav-item"><a class="nav-link" href="#"
th:href="@{/list.html}"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-users">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg> Employees
</a></li>
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-bar-chart-2">
<line x1="18" y1="20" x2="18" y2="10"></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg> Reports
</a></li>
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-layers">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg> Integrations
</a></li>
</ul>
<h6
class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Saved reports</span> <a
class="d-flex align-items-center text-muted"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-plus-circle">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="8" x2="12" y2="16"></line>
<line x1="8" y1="12" x2="16" y2="12"></line></svg>
</a>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-file-text">
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg> Current month
</a></li>
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-file-text">
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg> Last quarter
</a></li>
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-file-text">
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg> Social engagement
</a></li>
<li class="nav-item"><a class="nav-link"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#"> <svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-file-text">
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg> Year-end sale
</a></li>
</ul>
</div>
</nav>
</body>
</html>
引入
<body>
<!-- 引入topbar -->
<div th:replace="commons/bar :: topbar"></div>
<div class="container-fluid">
<div class="row">
<!-- 引入sidebar -->
<div th:replace="commons/bar :: sidebar"></div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<div class="chartjs-size-monitor"
style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;">
<div class="chartjs-size-monitor-expand"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;">
<div
style="position: absolute; width: 1000000px; height: 1000000px; left: 0; top: 0"></div>
</div>
<div class="chartjs-size-monitor-shrink"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: hidden; pointer-events: none; visibility: hidden; z-index: -1;">
<div
style="position: absolute; width: 200%; height: 200%; left: 0; top: 0"></div>
</div>
</div>
<div
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<button class="btn btn-sm btn-outline-secondary">Share</button>
<button class="btn btn-sm btn-outline-secondary">Export</button>
</div>
修改list的引入
<!-- 引入topbar
th:replace="资源路径 :: 片段名称"
-->
<div th:replace="commons/bar :: topbar"></div>
<div class="container-fluid">
<div class="row">
<!-- 引入sidebar -->
<div th:replace="commons/bar :: sidebar"></div>
6.3.高亮显示选中图标
修改bar.html文件,用三元表达式,选中就高亮显示,没选中就不高亮,Dashboard模块
<li class="nav-item"><a class="nav-link active" href="#"
th:href="@{/main.html}"
th:class="${activeUri=='main.html'?'nav-link active':'nav-link'}">
Employees模块
<a class="nav-link active"
href="#" th:class="${activeUri=='list.html'?'nav-link active':'nav-link'}"
th:href="@{/list.html}">
dashborad.html修改
<!-- 引入topbar -->
<div th:replace="commons/bar :: topbar"></div>
<div class="container-fluid">
<div class="row">
<!-- 引入sidebar -->
<div th:replace="commons/bar :: sidebar(activeUri='main.html')"></div>
list.html修改
<!-- 引入topbar
th:replace="资源路径 :: 片段名称"
-->
<div th:replace="commons/bar :: topbar"></div>
<div class="container-fluid">
<div class="row">
<!-- 引入sidebar -->
<div th:replace="commons/bar :: sidebar((activeUri='list.html'))"></div>