注意
- 如果靜態資源放到了靜態資源文件夾下卻無法訪問,請檢查一下是不是在自定義的配置類上加了@EnableWebMvc注解
- templete文件夾不是靜態資源的文件夾,默認是無法訪問的,所以要添加視圖映射
package cn.xxxxxx.hellospringbootweb.config;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 MyMvcConfig implements WebMvcConfigurer {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("login");registry.addViewController("/index").setViewName("login");registry.addViewController("/index.html").setViewName("login");}
}
?i18n國際化
-
編寫國際化配置文件,抽取頁面需要顯示的國際化消息
創建i18n文件夾存放配置文件,文件名格式為
基礎名(login)
+語言代碼(zh)
+國家代碼(CN)
-
在配置文件中添加國際化文件的位置和基礎名,如果配置文件中沒有配置基礎名,就在類路徑下找基礎名為
message
的配置文件spring.messages.basename=i18n.login
- 點擊切換語言? ? 修改頁面,點擊連接攜帶語言參數
<a class="btn btn-sm" href="?l=zh_CN">中文</a> <a class="btn btn-sm" href="?l=en_US">English</a>
實現登陸功能
1,提供登陸的Controller
@Controller
public class UserController {@PostMapping("/user/login")public String login(@RequestParam String username, @RequestParam String password, HttpSession session, Model model) {if (!StringUtils.isEmpty(username) && "123456".equals(password)) {//登錄成功,把用戶信息方法哦session中,防止表單重復提交,重定向到后臺頁面session.setAttribute("loginUser", username);return "redirect:/main.html";}//登錄失敗,返回到登錄頁面model.addAttribute("msg", "用戶名或密碼錯誤!");return "login";}
}
2,修改表單的提交地址,輸入框添加name值與參數名稱相對應
<form class="form-signin" action="dashboard.html" th:action="@{/user/login}" method="post"><img class="mb-4" 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">Username</label><input type="text" name="username" class="form-control" th:placeholder="#{login.username}" placeholder="Username" autofocus=""><label class="sr-only">Password</label><input type="password" name="password" class="form-control" th:placeholder="#{login.password}" placeholder="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" href="?l=zh_CN">中文</a><a class="btn btn-sm" href="?l=en_US">English</a></form>
3,由于登陸失敗是轉發,所以得修改靜態資源的請求路徑,在其中添加模版引擎
<link href="asserts/css/bootstrap.min.css" th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
4,添加登陸頁面的顯示,將msg傳回主頁面
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<!--msg存在才顯示該p標簽-->
<p th:text="${msg}" th:if="${not #strings.isEmpty(msg)}" style="color: red"></p>
修改頁面使其立即生效
在配置文件里面添加如下的命令,在頁面修改完成之后,按快捷鍵ctrl+f9,重新編譯
# 禁用緩存
spring.thymeleaf.cache=false
攔截器進行登陸檢查
1,實現攔截器
package cn.xxxxxx.hellospringbootweb.interceptor;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class LoginHandlerInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object loginUser = request.getSession().getAttribute("loginUser");if (loginUser == null) {//未登錄,攔截,并轉發到登錄頁面request.setAttribute("msg", "您還沒有登錄,請先登錄!");request.getRequestDispatcher("/index").forward(request, response);return false;}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
2,注冊攔截器
package cn.clboy.hellospringbootweb.config;import cn.clboy.hellospringbootweb.interceptor.LoginHandlerInterceptor;
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.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MyMvcConfig implements WebMvcConfigurer {//定義不攔截路徑private static final String[] excludePaths = {"/", "/index", "/index.html", "/user/login", "/asserts/**"};@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("login");registry.addViewController("/index").setViewName("login");registry.addViewController("/index.html").setViewName("login");registry.addViewController("/main.html").setViewName("dashboard");}@Beanpublic LocaleResolver localeResolver() {return new MyLocaleResolver();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {//添加不攔截的路徑,SpringBoot已經做好了靜態資源映射,所以我們不用管registry.addInterceptor(new LoginHandlerInterceptor()).excludePathPatterns(excludePaths);}
}
注意:在spring2.0+的版本中,只要用戶自定義了攔截器,則靜態資源會被攔截。但是在spring1.0+的版本中,是不會攔截靜態資源的。因此我們需要將靜態資源排除到攔截器的攔截路徑之外
案例,實現員工的增刪改查
實驗功能 | 請求URI | 請求方式 |
---|---|---|
查詢所有員工 | emps | GET |
查詢某個員工(來到修改頁面) | emp/1 | GET |
來到添加頁面 | emp | GET |
添加員工 | emp | POST |
來到修改頁面(查出員工進行信息回顯) | emp/1 | GET |
修改員工 | emp | PUT |
刪除員工 | emp/1 | DELETE |
-
為了頁面結構清晰,在template文件夾下新建emp文件夾,將list.html移動到emp文件夾下
-
將dao層和實體層java代碼復制到項目中
dao
,entities
-
添加員工controller,實現查詢員工列表的方法
@Controller public class EmpController {@Autowiredprivate EmployeeDao employeeDao;@GetMapping("/emps")public String emps(Model model) {Collection<Employee> empList = employeeDao.getAll();model.addAttribute("emps", empList);return "emp/list";}}
- 修改后臺頁面,更改左側的側邊欄,并修改請求路徑
<li class="nav-item"><a class="nav-link" th:href="@{/emps}"><svg .....>......</svg>員工列表</a> </li>
thymeleaf公共頁面元素抽取(參考官方文檔)
- ~{templatename::selector}:模板名::選擇器
- ~{templatename::fragmentname}:模板名::片段名
/*公共代碼片段*/
<footer th:fragment="copy">© 2011 The Good Thymes Virtual Grocery
</footer>/*引用代碼片段*/
<div th:insert="~{footer :: copy}"></di/*(?{...}包圍是完全可選的,所以上?的代碼 將等價于:*/
<div th:insert="footer :: copy"></di
三種引入公共片段的th屬性:
th:insert
:將公共片段整個插入到聲明引入的元素中th:replace
:將聲明引入的元素替換為公共片段th:include
:將被引入的片段的內容包含進這個標簽中
后臺頁面的抽取
1,將后臺主頁中的頂部導航欄作為片段,在list中引入
<nav th:fragment="topbar" class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0"><a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Company name</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>
2,list.html
<body><div th:replace="dashboard::topbar"></div>......
3,使用選擇器的方式抽取左側邊欄的代碼,就是我們將不同html文件的公共部分抽取出來,作為一個模版,其余需要的html文件只需要引入即可使用。比如現在我們將名稱為sidebar的模版放在dashboard.html里面,而在list.html里面進行復用。
<!--dashboard.html-->
<div class="container-fluid"><div class="row"><nav id="sidebar" class="col-md-2 d-none d-md-block bg-light sidebar" ......
<!--list.html-->
<div class="container-fluid"><div class="row"><div th:replace="dashboard::#sidebar"></div>......
4,顯示員工數據,添加增刪改按鈕
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><h2><button class="btn btn-sm btn-success">添加員工</button></h2><div class="table-responsive"><table class="table table-striped table-sm"><thead><tr><th>員工號</th><th>姓名</th><th>郵箱</th><th>性別</th><th>部門</th><th>生日</th><th>操作</th></tr></thead><tbody><tr th:each="emp:${emps}"><td th:text="${emp.id}"></td><td th:text="${emp.lastName}"></td><td th:text="${emp.email}"></td><td th:text="${emp.gender}==1?'男':'女'"></td><td th:text="${emp.department.departmentName}"></td><td th:text="${#dates.format(emp.birth,'yyyy-MM-dd')}"></td><td><button class="btn btn-sm btn-primary">修改</button><button class="btn btn-sm btn-danger">刪除</button></td></tr></tbody></table></div></main>
5,員工添加頁面 add.html
......
<body>
<div th:replace="commons/topbar::topbar"></div><div class="container-fluid"><div class="row"><div th:replace="commons/sidebar::#sidebar(currentURI='emps')"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><form><div class="form-group"><label>LastName</label><input name="lastName" type="text" class="form-control" placeholder="zhangsan"></div><div class="form-group"><label>Email</label><input name="email" type="email" class="form-control" placeholder="zhangsan@atguigu.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><select name="department.id" class="form-control"><option th:each="dept:${departments}" th:text="${dept.departmentName}" th:value="${dept.id}"></option></select></div><div class="form-group"><label>Birth</label><input name="birth" type="text" class="form-control" placeholder="zhangsan"></div><button type="submit" class="btn btn-primary">添加</button></form></main></div>
</div>
......
6,點擊鏈接,跳轉到添加頁面
<a href="/emp" th:href="@{/emp}" class="btn btn-sm btn-success">添加員工</a>
7,EmpController添加映射方法
@Autowiredprivate DepartmentDao departmentDao;@GetMapping("/emp")public String toAddPage(Model model) {//準備部門下拉框數據Collection<Department> departments = departmentDao.getDepartments();model.addAttribute("departments",departments);return "emp/add";}
8, 修改頁面遍歷添加下拉選項
<select class="form-control"><option th:each="dept:${departments}" th:text="${dept.departmentName}"></option>
</select>
9,表單提交,添加員工
<form th:action="@{/emp}" method="post">
@PostMapping("/emp")public String add(Employee employee) {System.out.println(employee);//模擬添加到數據庫employeeDao.save(employee);//添加成功重定向到列表頁面return "redirect:/emps";}
10,日期格式的修改
表單提交的格式必須是yyyy/MM/dd的格式,可以在配置文件中修改格式
spring.mvc.date-format=yyyy-MM-dd
員工修改
- 點擊按鈕跳轉到編輯頁面
<a th:href="@{/emp/}+${emp.id}" class="btn btn-sm btn-primary">修改</a>
- 添加編輯頁面,將表單的提交方式設置為post方式,提供_method參數
<body> <div th:replace="commons/topbar::topbar"></div><div class="container-fluid"><div class="row"><div th:replace="commons/sidebar::#sidebar(currentURI='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"><!--員工id--><input type="hidden" name="id" th:value="${emp.id}"><!--http請求方式--><input type="hidden" name="_method" value="put"><div class="form-group"><label>LastName</label><input name="lastName" th:value="${emp.lastName}" type="text" class="form-control" placeholder="zhangsan"></div><div class="form-group"><label>Email</label><input name="email" th:value="${emp.email}" type="email" class="form-control" placeholder="zhangsan@atguigu.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" th:checked="${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.gender==0}"><label class="form-check-label">女</label></div></div><div class="form-group"><label>department</label><select name="department.id" class="form-control"><option th:each="dept:${departments}" th:value="${dept.id}" th:selected="${dept.id}==${emp.department.id}" th:text="${dept.departmentName}"></option></select></div><div class="form-group"><label>Birth</label><input name="birth" type="text" class="form-control" placeholder="zhangsan" th:value="${#dates.format(emp.birth,'yyyy-MM-dd')}"></div><button type="submit" class="btn btn-primary">添加</button></form></main></div> </div>......
- controller轉發到編輯頁面,回顯員工信息
@GetMapping("/emp/{id}")public String toEditPage(@PathVariable Integer id, Model model) {Employee employee = employeeDao.get(id);//準備部門下拉框數據Collection<Department> departments = departmentDao.getDepartments();model.addAttribute("emp", employee).addAttribute("departments", departments);return "emp/edit";}
- 提交表單修改員工的信息
@PutMapping("/emp")public String update(Employee employee) {employeeDao.save(employee);return "redirect:/emps";}
員工刪除
- 點擊刪除提交發出delete請求
@DeleteMapping("/emp/{id}")public String delete(@PathVariable String id){employeeDao.delete(id);return "redirect:/emps";}
- 如果提示不支持POST請求,在確保代碼無誤的情況下查看是否配置啟動
HiddenHttpMethodFilter
-
這個好像是2.0版本以后修改的 spring.mvc.hiddenmethod.filter.enabled=true
-
如果刪除不掉,請修改
EmployeeDao
,把String轉為Integer類型public void delete(String id) {employees.remove(Integer.parseInt(id));}
?