1、首页实现
1.1、访问index
由于template包下的静态文件不能直接访问,所以需要间接访问到;需要进行视图跳转;
- 在主程序统计目录下新建config包用来存放自己的配置类
- 在其中建立自己的配置类MyMvcConfig用来增加自己的视图跳转
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
要先要导入thymeleaf依赖后,启动才有效!
启动主程序后访问测试,访问localhost:8080/或localhost:8080/index.html
显然,此时前端html代码有问题,一些静态资源没有成功引入。
1.2、给index.html引入thymeleaf
上述测试可以看到页面有图片没有加载出来,且没有css和js的样式,这就是因为我们html
页面中静态资源引入的语法出了问题,在SpringBoot中,推荐使用Thymeleaf
作为模板引擎,我们将其中的语法改为Thymeleaf
,所有页面的静态资源都需要使用其接管
- 注意所有html都需要引入
Thymeleaf
命名空间
xmlns:th="http://www.thymeleaf.org"
- 然后修改所有的页面静态资源的引入,使用@{…}链接表达式
在此访问,正确显示页面:
2、页面国际化
2.1、统一properties编码
在IDEA中统一设置properties的编码为UTF-8
2.2、编写i18n国际化资源文件
-
在resources目录下新建一个i18n包,其中放置国际化相关的配置
-
其中新建三个配置文件,用来配置语言:
-
login.properties: 无语言配置时生效;
-
login_en_US.properties:英文生效;
-
login_zh_CN.properties:中文生效;
命名方式是下划线的组合:
文件名_语言_国家.properties
-
以此命名方式,IDEA会帮助我们识别这是个国际化配置,自动绑定在一起转换如下的模式:
绑定在一起后,我们想要添加更多的语言配置,只需要在大的资源包右键添加到该绑定文件即可
此时只需要输入区域名即可创建成功,比如:en_US,就会自动识别为美国:
然后打开英文或是中文语言的properties文件,点击Resources Bundle进入可视化编辑页面
进入到可视化编辑页面后
- 点击+
- 添加属性:首先创建一个login.tip代表首页中的提示(自定义起名login.XXX)
- 然后对提示分别做三种情况的语言配置,三个对应的输入框输入即可
类似配置tip提示,我们在配置更多的信息
然后打开三个配置文件查看其中的文本内容,可以看到已经做好了全部的配置
login.properties(默认)
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
login_en_US.properties(英文)
login.btn=login
login.password=password
login.remember=remember me
login.tip=Please sign in
login.username=username
login_zh_CN.properties(中文)
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
2.3、配置国际化资源文件名称
在Spring程序中,国际化主要是通过ResourceBundleMessageSource这个类来实现的
Springboot通过MessageSourceAutoConfiguration为我们自动配置好管理国际化资源文件的组件
先来看看这个类
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {
private static final Resource[] NO_RESOURCES = {};
@Bean
@ConfigurationProperties(prefix = "spring.messages")
public MessageSourceProperties messageSourceProperties() {
return new MessageSourceProperties();
}
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
...
}
}
主要了解一下messageSource()这个方法
可以看到,此方法的参数为messageSourceProperties对象,来分析一下这个类:
public class MessageSourceProperties {
/*逗号分隔的基名列表(本质上是完全限定的类路径)
每个都遵循ResourcesBundle约定,并轻松支持基于斜杠的位置
如果不包含全限定符(如:org.mypackage),他将从类路径根目录中解析*/
private String basename = "messages";
/**
* Message bundles encoding.
*/
private Charset encoding = StandardCharsets.UTF_8;
意思是:
- 如果你不在springboot配置文件中指定以.分隔开的国际化资源文件名称的话
- 他默认会去类路径下找messages.propertiese作为国际化资源文件
因为我们自定义了国际化资源文件,因此我们需要在springboot配置文件application.propreties中加入以下配置指定我们配置文件的名称
spring.message
2.4、首页获取显示国际化
利用#{…}消息表达式,去首页index.html获取国际化的值
重启项目,访问首页,已经自动识别为中文
2.5、配置国际化组件实现中英文切换
2.5.1、添加中英文切换标签链接
index.html中底部可以看到两个标签
<a class="btn btn-sm">中文</a>
<a class="btn btn-sm">English</a>
要通过这两个标签实现中英文切换,首先要在这两个标签上加跳转链接并带上响应参数
<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中,需要处理这个带参数的链接请求
2.5.2、自定义地区解析器组件
LocaleResolver:地区解析器
在WebMvcAutoConfiguration中,找到**localeResolver()**方法
该方法作用是:获取LocaleResolver地区对象解析器:
- 如果用户配置了则使用用户配置的地区解析器
- 如用户没有配置,就用默认的
@Override
@Bean
@ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME)
public LocaleResolver localeResolver() {
if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.webProperties.getLocale());
}
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.webProperties.getLocale());
return localeResolver;
}
因此我们要实现自定义的国际化资源生效,需要自己编写一个地区解析器,来继承LocleResolver接口,重写其方法即可。
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
//获取请求中的国际化参数
String language = request.getParameter("l");
//默认的地址
Locale locale = Locale.getDefault();
//如果请求的链接参数不为空,携带了国际化参数
if(!StringUtils.isEmpty(language)){
String[] split = language.split("_");//zh_CN(语言_地区)
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
为了我们的区域化信息能够生效,我们需要配置一下这个组件!在我们的MyMvcConfig配置类下添加bean
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
...
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
我们重启项目,来访问一下,发现点击按钮可以实现切换!
4、登录功能实现
当我们点击登录按钮时,会进入一个界面(dashboard页面)
1、首先在index.html的表单中更改提交地址/user/login, 并给名称和密码输入框添加name属性为了后面传参
2、编写控制层的controller
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("passwrod") String password,
Model model){
if("admin".equals(username) && "123123".equals(password)){
return "dashboard";
}else{
model.addAttribute("msg", "用户名或密码错误");
return "index";
}
}
}
3、在index.html首页中,添加一个标签来显示从controller返回的登录错误信息
<p style="color: red" th:text="${msg}"></p>
重启,进行测试:
【注意: url泄露信息】
此时登录功能实现完毕,但是现在有一个大问题,浏览器的url暴露了用户的用户名和密码,泄露了用户信息,此时我们需要编写一个映射!
- 我们在MyMvcConfig中加一句代码
registry.addViewController("/main.html").setViewName("dashboard");
也就是访问main.html页面就跳转到dashboard页面
- 然后修改LoginController,当登录成功后重定向到main.html页面,也就跳转到了dashboard页面
...
if("admin".equals(username) && "123123".equals(password)){
return "redirect:/main.html";
}else{
...
因为:
==原来是请求转发:==到dashboard,还是原来的请求,转发到dashboard页面
重定向后:是去请求mian.html,请求变了!
再次重新测试,输入正确的用户名和密码登录成功后,浏览器不在携带泄露信息。
【注意:拦截无权限访问】
出现了新的问题,不论登不登陆,我们访问localhost:8080/main.html都会跳转到dashhoard页面,此时就需要拦截器了。
5、登录拦截器
为了解决上述问题,我们需要自定义一个拦截器
在config目录下,新建一个登录拦截器类:LoginHandlerInterceptor
登录成功后,后台会得到我们的用户信息;如果没有登录,则不会有任何用户信息。我们通过这一点来用拦截器进行拦截:
- 将用户登录后的用户名信息放到session中,访问页面时首先判断session中有没有用户信息
- 如果没有,拦截器进行拦截
- 如果有,拦截器放行
1、存session信息
要先在LoginController中设计:用户登录成功后,存入用户信息到session中
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model,
HttpSession session){
if("admin".equals(username) && "123123".equals(password)){
session.setAttribute("LoginUser", username);
return "redirect:/main.html";
}else{
model.addAttribute("msg", "用户名或密码错误");
return "index";
}
}
2、自定义HandlerInterceptor接口的preHandle方法
2、再在config目录中新建一个自定义的LoginHanderInterceptor 类(继承HandlerInterceptor接口)
public class LoginHanderInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
Object loginUser = session.getAttribute("LoginUser");
//session中有LoginUser信息,放行
if(loginUser != null){
return true;
}else{
//session中没有LoginUser信息,就拒绝放行,并在请求上下文中放入msg信息,index的p标签提取
,请求转发到index.html页面
request.setAttribute("msg", "权限不够,请先登录!");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}
}
}
3、在配置类中注入bean
重写WebMvcConfigurer接口的addInterceptors方法
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHanderInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index.html", "/", "/user/login", "/css/**", "/js/**", "/img/**");
}
与增加视觉控制器一样,通过addInterceptors方法添加你自定义的拦截器
- 拦截器起作用路径:
/**
- 作用排除:
"/index.html", "/", "/user/login", "/css/**", "/js/**", "/img/**"
6、展示员工信息
1、实现Customers视图跳转
需要在dashboard.html页面中的侧边栏,点击Customers链接跳转到用户信息列表页面
1、在templates目录下新建一个包:emp,用来放有关员工信息的页面,我们将list.html页面移入其中
2、编写controller,处理/emps请求,在controller包下,建立一个EmployeeController类
/***
* 所有员工信息
* @param model 视图解析器
* @return 返回到 list 页面(list页面:显示所有员工信息)
*/
@RequestMapping("/emps")
public String list(Model model){
Collection<Employee> allEmployee = employeeDao.getAllEmployee();
model.addAttribute(allEmployee);
return "emp/list";
}
3、修改list.html 和 dashboard.html中Customers链接请求路径
<a class="nav-link" th:href="@{/emps}">
重启主程序,登录到大神board页面中,再点击Customer,成功跳转到/emps
【问题】
- 点击Customer后,此处链接应该成高亮状态,但是这里点击后还是普通的样式,高亮点还在dashboard上
- list.html和dashboard.html页面的侧边栏和顶部栏是相同的,可以抽出来,共用!
2、提取页面公共部分
1、在templates目录下,新建common包(用来存放提取出来的公共部分)
2、dashboard.html和list.html中有公共部分代码(顶部栏、侧边栏部分)
-
所以将其公共代码取出,放入common目录下的新建html文件:common.html中
-
取出的标签中写上 :
th:fragment="topbar" 、 th:fragment="sidepbar"
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!--顶部导航栏,利用th:fragment提取出来,名为topbar-->
<nav th:fragment="topbar" class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
......
</nav>
<!--侧边栏,利用th:fragment提取出来,名为sidebar-->
<nav th:fragment="sidebar" class="col-md-2 d-none d-md-block bg-light sidebar">
......
</nav>
</html>
3、原代码中将提取部分删除掉,在原来你的地方插入common.html的代码
<body>
<div th:insert="common/common::topbar"></div>
<div class="container-fluid">
<div class="row">
<div th:insert="~{common/common::sidebar}"></div>
</div>
....
</body>
- 带不带~{}都可
- th:insert 或 th:replace
- 注意插入的文件与common.html的相对目录层级
3、点击高亮处理
在common.html中对链接进行判断
<a th:class="${active == 'dashboard.html'? 'nav-link active' : 'nav-link'}" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
如果active是dashboard.html,class就等于nav-link active(高亮),否则定于nav-link
active的值从何而来?
在每次进入某个html页面后,插入的公共部分代码标签上传递对应的值,例如:
<!--侧边栏-->
<div th:replace="~{common/common::sidebar(active='list.html')}"></div>
进入list页面后,list.html的侧边栏代码在引入公共代码时向其传入参数,公共代码部分识别此参数,做出判断后,显示高亮或不高亮。
4、显示员工信息
1、EmployeeController中将查找出来的所有员工信息,放入model中
Collection<Employee> allEmployee = employeeDao.getAllEmployee();
model.addAttribute("emps", allEmployee);
2、前段将emps取出,在table中each遍历取出
<table class="table table-striped table-sm">
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>department</th>
<th>date</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}">
<td th:text="${emp.getLastName()}">
<td th:text="${emp.getEmail()}">
<td th:text="${emp.getGender() == 1 ? '男' : '女'}">
<td th:text="${emp.getDepartment().getDepartmentName()}">
<td th:text="${#dates.format(emp.getDate(),'yyyy-MM-dd HH:mm:ss')}">
</td>
</tr>
</tbody>
</table>
【注意】
日期格式转换:thymeleaf语法专门的转换格式#dates.format(emp.getDate(),'yyyy-MM-dd HH:mm:ss')
3、在员工列表每行中再加上两个按钮操作:编辑 、 删除
在此重启主程序测试,成功:
7、增加员工
【整体流程图】
1、list页面增加 添加员工 按钮
1、首先在list.html页面中,添加一个 增加员工的按钮,点击按钮后发起一个请求: /add
<a class="btn btn-sm badge-success" th:href="@{/emp}">添加员工</a>
2、编写/emp对应的controller,在EmployeeController中添加一个toAdd方法用来处理list页面中的按钮提交动作,返回到add.html页面
/***
* 获取所有departments信息
* @param model 视图解析器
* @return 跳转到add.html页面
*/
@GetMapping("/emp")
public String toAdd(Model model){
Collection<Department> allDepartments = departmentDao.getAllDepartments();
model.addAttribute("departments", allDepartments);
return "emp/add";
}
【注意】
add.html中,有一个部分选项:需要前端获取到所有的departments信息,所以在toAdd方法中有两个作用:
- 将departments信息放入model中;
- 跳转到add.html界面
2、创建添加员工页面add
1、在templates/emp目录下新建add.html
2、我们复制list.html中的内容,修改掉中心内容信息,更改为我们的表格
<form th:action="@{/emp}" method="post">
<div class="form-group">
<label>LastName</label>
<input type="text" name="lastName" class="form-control" placeholder="lastname:zsr">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" placeholder="email:xxxxx@qq.com">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<!--注意这里的name是department.id,因为传入的参数为id-->
<select class="form-control" name="department.id">
<option th:each="department:${departments}" th:text="${department.getDepartmentName()}" th:value="${department.getId()}"></option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<!--springboot默认的日期格式为yy/MM/dd-->
<input type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">
</div>
<button type="submit" class="btn btn-primary">添加</button>
</form>
重启后看看
点击添加员工—>成功跳转到add.html页面
【注意】
department下拉框应该是所有的部分,是我们前端获取到departments后遍历显示得到
- 注意后台接收的是employee对象,其中department属性是对象,所以前端不能name是department但是值是department.id,后端参数解析器会配置错误!
- 直接让前端传入的是department.id,后端后自行实例化对象,只不过departmentName属性可能是NULL
<!--注意这里的name是department.id,因为传入的参数为id-->
<select class="form-control" name="department.id">
<option th:each="department:${departments}" th:text="${department.getDepartmentName()}" th:value="${department.getId()}"></option>
</select>
3、add页面添加员工请求
在add.html页面,我们填写完信息,点击添加按钮后,应该完成添加返回到list页面,展示新的员工信息;
因此在add.html点击按钮的一瞬间,我们同样发起post请求/emp(restF风格)
<form th:action="@{/emp}" method="post">
然后编写对应的controller: EmployeeController下的add方法
/****
* 增加新用户
* @param employee 前端传入的用户信息,用employee接收
* @return 跳转到list.html页面
*/
@PostMapping("/emp")
public String add(Employee employee){
employeeDao.insert(employee);
return "redirect:/emps";
}
注意增加后,重定向至emps,获取数据库中所用员工信息,后到list.html页面展示.
重启后测试:
点击添加按钮,成功实现添加员工
8、修改员工信息
1、list页面编辑按钮,添加请求
点击编辑后,应该跳转到edit.html进行编辑
- 首先就是要将list.html的标签添加href属性,实现点击请求/edit/id号 (restFul风格)
<a th:href="@{/edit/${emp.getId()}}" style="color: white ; border-radius: 50px" class="btn btn-sm btn-primary">编辑</a>
- 然后编写对应的controller,在EmployeeController类下添加新的方法叫edit来处理list页面点击编辑后的操作,返回到edit.html编辑员工页面
/***
* restful风格接收参数
* @param id list编辑按键的请求中带有的参数
* @param model 视图解析器
* @return 跳转到编辑界面
*/
@RequestMapping("/edit/{id}")
public String edit(@PathVariable("id") Integer id, Model model){
//查询指定id的员工,添加到employee中,用于前端接收
Employee employee = employeeDao.getEmployeeByID(id);
model.addAttribute("employee", employee);
//查出所有部分的信息,添加到departments中,用于前端接收(和add一样)
Collection<Department> allDepartments = departmentDao.getAllDepartments();
model.addAttribute("departments", allDepartments);
return "/emp/edit";
}
2、创建编辑员工页面edit
edit.html
修改处:
- th:value="${employee.getLastName()}"提前放值,不同类型的标签,属性不同!
- th:checked="${employee.getGender() == 1}"
- th:selected="${department.getId() == employee.getDepartment().getId()}"
<form th:action="@{/edit}" method="post">
<div class="form-group">
<label>LastName</label>
<input th:value="${employee.getLastName()}" type="text" name="lastName" class="form-control" placeholder="lastname:zsr">
</div>
<div class="form-group">
<label>Email</label>
<input th:value="${employee.getEmail()}" type="email" name="email" class="form-control" placeholder="email:xxxxx@qq.com">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input th:checked="${employee.getGender() == 1}" value="1" class="form-check-input" type="radio" name="gender" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input th:checked="${employee.getGender()==0}" value="0" class="form-check-input" type="radio" name="gender" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<!--注意这里的name是department.id,因为传入的参数为id-->
<select class="form-control" name="department.id">
<option th:each="department:${departments}"
th:selected="${department.getId() == employee.getDepartment().getId()}"
th:text="${department.getDepartmentName()}"
th:value="${department.getId()}">
</option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<!--springboot默认的日期格式为yy/MM/dd-->
<input th:value="${employee.getDate()}" type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">
</div>
<button type="submit" class="btn btn-primary">修改</button>
</form>
启动主程序测试:
【注意】
要将日期格式提前修改
<input th:value="${#dates.format(employee.getDate(), 'yyyy-MM-dd')}" type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">
【注意:修改employee的date属性格式】
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date date;
使其能够兼容得到前端传回的时间格式参数。
3、edit页面编辑完成提交请求
在edit.html点击修改按钮后,我们需要返回到list页面,更新员工信息,因此我们需要添加href属性,实现点击按钮后的请求:/editEmp
<form th:action="@{/editEmp}" method="post">
编写对应的controller,处理修改按钮的请求, editEmp方法
/***
* 处理edit按键的请求
* @param employee 前端传递来的参数
* @return 重定向到/emps,刷新列表
*/
@RequestMapping("/editEmp")
public String editEmp(Employee employee){
employeeDao.insert(employee);
return "redirect:/emps";
}
【注意:修改时隐藏提交id】
如果按照add.html样式提交修改后的信息,向后端传入的参数中id=null,后端接收到的employee对象因此没有id值,就会触发自增id条件,生成了新的用户。
所以,需要在edit.html的from表单中添加隐藏提交值
<input type="hidden" name="id" th:value="${employee.getId()}">
然后点击修改后,正常完成修改,并返回到list.html页面。
4、删除员工信息
给list中的删除标签写请求(注意写法)
<a th:href="@{/delete/{id}(id=${emp.getId()})}" style="color: white; border-radius: 50px" class="btn btn-sm btn-danger">删除</a>
【注意:restFul风格的thymeleaf请求风格】
{id}(id=${…})—参数给值
然后编写controller,处理删除标签的请求,删除指定id的员工
/***
* 处理delete请求
* @param id 指定员工id
* @return 重定向到emps,刷新列表
*/
@RequestMapping("/delete/{id}")
public String deleteEmp(@PathVariable("id") Integer id){
employeeDao.deleteEmployeeByID(id);
return "redirect:/emps";
}
重新启动后测试,成功删除,刷新页面。
9、 404页面定制
只需要在templates目录下新建一个error包,然后将404.html放入其中,报错Springboot就会自动找到这个页面
测试:随便访问一个不存在的页面
出现的404页面即是我们自己的404.html
10、注销操作
在common页面中,修改顶部导航栏标签的href属性,实现点击发起请求/logout
<li class="nav-item text-nowrap">
<a class="nav-link" th:href="@{/logout}">Sign out</a>
</li>
然后编写对应的controller,处理点击注销的请求,在LoginController中编写方法,清除session,重定向到首页
/***
* 注销用户session
* @param session HttpSession
* @return 重定向到:index.html
*/
@RequestMapping("/logout")
public String signout(HttpSession session){
session.invalidate();
return "redirect:index.html";
}
重新测试,登录成功后,点击sign out退出首页。
员工id
* @return 重定向到emps,刷新列表
*/
@RequestMapping("/delete/{id}")
public String deleteEmp(@PathVariable(“id”) Integer id){
employeeDao.deleteEmployeeByID(id);
return "redirect:/emps";
}
重新启动后测试,成功删除,刷新页面。
# 9、 404页面定制
只需要在templates目录下新建一个error包,然后将404.html放入其中,报错Springboot就会自动找到这个页面
测试:随便访问一个不存在的页面
[外链图片转存中...(img-VdUALG20-1642820791754)]
出现的404页面即是我们自己的404.html
# 10、注销操作
在common页面中,修改顶部导航栏标签的href属性,实现点击发起请求/logout
```html
<li class="nav-item text-nowrap">
<a class="nav-link" th:href="@{/logout}">Sign out</a>
</li>
然后编写对应的controller,处理点击注销的请求,在LoginController中编写方法,清除session,重定向到首页
/***
* 注销用户session
* @param session HttpSession
* @return 重定向到:index.html
*/
@RequestMapping("/logout")
public String signout(HttpSession session){
session.invalidate();
return "redirect:index.html";
}
重新测试,登录成功后,点击sign out退出首页。