开发的时候使用模板引擎,修改页面内容不生效?
1.禁用模板缓存
#禁用缓存
spring.thymeleaf.cache=false
2.修改完后刷新
修改完页面内容后 ctrl+f9 重新编译
登录错误消息显示
@PostMapping(value ="/user/login")
// @RequestMapping(value ="/user/login",method =RequestMethod.POST)
public String login(@RequestParam("username") String username ,@RequestParam("password") String password,
Map<String,String> map){
//测试使用 用户名不为空 密码是123456 就认为成功
if(!StringUtils.isEmpty(username) && "123456".equals(password)){
//登录成功
return "dashboard";
}else{
map.put("msgmsg","用户名密码错误");
return "login";
}
}
<p style="color:red" th:text="${msgmsg}" th:if="${not #strings.isEmpty(msgmsg)}" >p>
防止表单重复提交 需要重定向
1)
@Bean
public WebMvcConfigurer addViewControllers2() {
return new WebMvcConfigurer() {
//
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("index.html").setViewName("login");
//重定向使用
registry.addViewController("main.html").setViewName("dashboard");
}
};
}
拦截器进行登录检查
1)登陆成功后需要把登录信息放入session(或者用其他存储方法)
@PostMapping(value ="/user/login")
// @RequestMapping(value ="/user/login",method =RequestMethod.POST)
public String login(@RequestParam("username") String username , @RequestParam("password") String password,
Map<String,String> map, HttpSession session){
if(!StringUtils.isEmpty(username) && "123456".equals(password)){
//放入session 为了后边验证是否登录!!!
session.setAttribute("loginUser",username);
//登录成功 防止表单重复提交 使用重定向 /main.html 重定向到当前项目下的main.html
return "redirect:/main.html";
}else{
map.put("msgmsg","用户名密码错误");
return "login";
}
}
2)编写拦截器
public class LoginHandllerInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("loginUser");
if(user == null){
//未登录 返回登录页面 登录页面显示错误信息
request.setAttribute("msgmsg","没有权限 请先登录");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else{
//已登录 放行请求
return true;
}
}
}
3)注册拦截器
@Bean
public WebMvcConfigurer addViewControllers2() {
return new WebMvcConfigurer() {
//添加映射
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("index.html").setViewName("login");
registry.addViewController("main.html").setViewName("dashboard");
}
//注册拦截器注册拦截器!!
@Override
public void addInterceptors(InterceptorRegistry registry) {
//以前需要考虑静态资源拦截问题( *.css *.js 等) SpringBoot就不需要考虑了 它已经做好了静态资源映射
registry.addInterceptor(new LoginHandllerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login");
}
};
}
直接访问main.html会提示没有权限
把dashboard.html页面的js css引用都改为th引用 webjars方式
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>jqueryartifactId>
<version>3.0.0version>
dependency>
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>bootstrapartifactId>
<version>4.2.1version>
dependency>
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>popper.jsartifactId>
<version>1.14.4version>
dependency>
<dependency>
<groupId>org.webjars.npmgroupId>
<artifactId>feather-iconsartifactId>
<version>4.10.0version>
dependency>
<dependency>
<groupId>org.webjars.bowergroupId>
<artifactId>chart.jsartifactId>
<version>2.7.3version>
dependency>
<script type="text/javascript" src="asserts/js/jquery-3.2.1.slim.min.js" th:src="@{/webjars/jquery/3.0.0/jquery.js}">script>
<script type="text/javascript" src="asserts/js/popper.min.js" th:src="@{/webjars/popper.js/1.14.4/umd/popper.js}">script>
<script type="text/javascript" src="asserts/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/4.2.1/js/bootstrap.js}">script>
<script type="text/javascript" src="asserts/js/feather.min.js" th:src="@{/webjars/feather-icons/4.10.0/dist/feather.js}">script>
<script type="text/javascript" src="asserts/js/Chart.min.js" th:src="@{/webjars/chart.js/2.7.3/dist/Chart.js}">script>
普通CRUD | RestfaulCRUD | |
---|---|---|
查询 | getEmp | emp—GET |
添加 | addEmp | emp—POST |
修改 | updateEmp | emp—PUT |
删除 | deleteEmp | emp—DELETE |
就是用一样的请求资源名 /emp 用不一样的请求方式 GET POST PUT DELETE 来做CRUD
请求URI | 请求方式 | |
---|---|---|
查询所有员工 | emps | GET |
查询某个员工 | emp/{id} | GET |
到添加页面 | emp | GET |
添加员工 | emp | POST |
到修改页面 | emp/{id} | GET |
修改 | emp | PUT |
删除 | emp/{id} | DELETE |
thymeleaf公共页面元素抽取
1.抽取
<div th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
div>
2.引用
//模板名::选择器 模板名::片段名
<div th:insert="~{footer :: copy}">div>
或者是
<div th:insert="footer :: copy">div>
3.默认效果
insert的片段 就在div中
如果使用th:insert等属性引入 可以不写~{}
行内写法可以加上:[[~{}]] [(~{})]
三种引入th片段的属性:
th:insert: 将公共片段插入声明引入的元素中
th:replace : 将声明引入的元素 替换为公共片段
th:include : 将被引入的片段的内容 包含进引入标签中
<footer th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
footer>
引入方式:
<div th:insert="footer :: copy">div>
<div th:replace="footer :: copy">div>
<div th:include="footer :: copy">div>
效果:
<div>
<footer>
© 2011 The Good Thymes Virtual Grocery
footer>
div>
<footer>
© 2011 The Good Thymes Virtual Grocery
footer>
<div>
© 2011 The Good Thymes Virtual Grocery
div>
引入片段时传入参数:
引入的时候传入参数:
<div th:replace="commons/bar::#sidebar(activeUri='emps')">div>
片段定义的地方使用参数:
//根据参数判断 给不同的class
th:class="${activeUri=='emps'?'nav-link active':'nav-link'}"
1. 查询员工:
@GetMapping("/emps")
public String list(Model model){
//查询所有员工
Collection<Employee> emps = employeeDao.getAll();
//放在请求域中共享
model.addAttribute("emps",emps);
//classpath:/tmplates/xxx .html
return "emp/list";
}
<h2><a class="btn btn-sm btn-success" th:href="@{/emp}">员工添加a>h2>
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>#th>
<th>lastNameth>
<th>emailth>
<th>genderth>
<th>departmentth>
<th>birthth>
<th>操作th>
tr>
thead>
<tbody>
<tr th:each="emp:${emps}" >
<td th:text="${emp.id}">td>
<td>[[${emp.lastName}]]td>
<td th:text="${emp.email}">td>
<td th:text="${emp.gender}==0?'女':'男'">td>
<td th:text="${emp.department.departmentName}">td>
<td th:text="${#dates.format(emp.birth,'yyyy-mm-dd HH:ss')}">td>
<td >
<button class="btn btn-sm btn-primary">编辑button>
<button class="btn btn-sm btn-danger">删除button>
td>
tr>
tbody>
table>
div>
<a class="btn btn-sm btn-success" th:href="@{/emp}">员工添加a>
@GetMapping("/emp")
public String toAddPage(Model model){
//查出所有部门
Collection<Department> depts = departmentDao.getDepartments();
model.addAttribute("depts",depts);
return "emp/add";
}
//添加员工
//SpringMCV 自动将参数和入参对象的属性进行一一绑定 ; 请求参数名字 要与javabean入参的属性名一样
@PostMapping("/emp")
public String addEmp(Employee employee){
employeeDao.save(employee);
//到员工列表页面
//redirect表示重定向到一个地址 /代表当前项目路径
//forward方法 表示转发到一个地址
return "redirect:/emps";
}
<div th:replace="commons/bar::#sidebar(activeUri='emps')">div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<form th:action="@{/emp}" method="post">
<input type="hidden" name="_method" value="put" th:if="${emp!=null}"/>
<input type="hidden" name="id" th:if="${emp!=null}" th:value="${emp.id}">
<div class="form-group">
<label>名称label>
<input name="lastName" type="text" class="form-control" placeholder="zhangsan" th:value="${emp!=null}?${emp.lastName}">
div>
<div class="form-group">
<label>邮件label>
<input name="email" type="email" class="form-control" placeholder="[email protected]" th:value="${emp!=null}?${emp.email}">
div>
<div class="form-group">
<label>性别label><br/>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="1" th:checked="${emp!=null}?${emp.gender==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" th:checked="${emp!=null}?${emp.gender==0}">
<label class="form-check-label">女label>
div>
div>
<div class="form-group">
<label>部门label>
<select class="form-control" name="department.id">
<option th:selected="${emp!=null}?${dept.id == emp.department.id}"
th:value="${dept.id}"
th:each="dept:${depts}"
th:text="${dept.departmentName}">option>
select>
div>
<div class="form-group">
<label>生日label>
<input name="birth" type="text" class="form-control" placeholder="zhangsan" th:value="${emp!=null}?${#dates.format(emp.birth, 'yyyy-MM-dd HH:mm')}">
div>
<button type="submit" class="btn btn-primary" th:text="${emp!=null}?'修改':'添加'">添加button>
form>
main>
div>
容易出问题:日期转换
2018-08-08 2018/08/08 2018.08.08
默认用的是dd/MM/yyyy
可以直接在配置文件修改:
#日期
spring.mvc.date-format=yyyy-MM-dd
页面模板中日期格式化
<td th:text="${#dates.format(emp.birth,'yyyy-MM-dd HH:ss')}">td>
<a class="btn btn-sm btn-primary" th:href="@{emp/}+${emp.id}">编辑a>
@GetMapping("/emp/{id}")
public String toEditPage(@PathVariable("id") String id, Model model){
Employee e = employeeDao.get(id);
model.addAttribute("emp",e);
//查出所有部门
Collection<Department> depts = departmentDao.getDepartments();
model.addAttribute("depts",depts);
return "emp/add";
}
用新增页面 加 三元判断与修改页面公用!
//通过判断emp是否为空 来控制页面是否回显
th:value="${emp!=null}?${emp.lastName}"
//通过判断emp是否为空 来控制按钮内容
th:text="${emp!=null}?'修改':'添加'"
//隐藏id
<input type="hidden" name="id" th:if="${emp!=null}" th:value="${emp.id}">
//员工修改
@PutMapping("/emp")
public String updateEmp(Employee employee){
employeeDao.save(employee);
return "redirect:/emps";
}
修改页面提交的HTTP方式:
<input type="hidden" name="_method" value="put" th:if="${emp!=null}"/>
SpringBoot已经配置好了
//WebMvcAutoConfiguration类中
//转换post的提交方式
@Bean
@ConditionalOnMissingBean({HiddenHttpMethodFilter.class})
@ConditionalOnProperty(
prefix = "spring.mvc.hiddenmethod.filter",
name = {"enabled"},
matchIfMissing = true
)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
<form th:action="@{/emp}+${emp.id}" method="post">
<input type="hidden" name="_method" value="delete"/>
<button class="btn btn-sm btn-danger" type="submit"> 删除button>
form>
1.
<button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger deleteBtn" type="submit"> 删除button>
2.
<form id="deleteEmpForm" method="post">
<input type="hidden" name="_method" value="delete"/>
form>
3.
<script>
$(function(){alert();
$(".deleteBtn").on("click",function(){
$("#deleteEmpForm").attr("action",$(this).attr("del_uri")).submit();
return false;
})
});
script>
后台都一样:
@DeleteMapping("/emp/{id}")
public String deleteEmp(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/emps";
}