MVC配置原理
修改SpringBoot的默认配置:SpringBoot在自动配置组件时,先看容器中有没有用户自己的配置,如果有就用用户自己配置的,如果没有就用容器的自动配置,有些组件可以存在多个,会将默认配置和用户配置组合使用
自定义配置类
编写一个@Configuration注释的注解类,实现WebMvcConfigurer,还不能标注@EnableWebMvc
//扩展视图解析器
@Configuration//如果想自定义功能,可以通过这个组件,将它交给springboot,springboot会帮我们实现自动装配
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//自己设置跳转路径,以及跳转的页面
registry.addViewController("/aaa").setViewName("test");
}
// @Bean
// public ViewResolver myViewResolver() {
// return new MyViewResolver();
// }
//
// //自定义自己的视图解析器
// public static class MyViewResolver implements ViewResolver {
// @Override
// public View resolveViewName(String s, Locale locale) throws Exception {
// return null;
// }
// }
}
在SpringBoot中,有非常多的xxxConfiguration帮助我们进行扩展,只要看见了这个东西,我们就要注意了
实现简单的功能
首页配置,所有页面的静态资源都要有thymeleaf接管@{}
#手动修改路径
server:
servlet:
context-path: /wjq
页面国际化
th:action="@{/user/login}"
涉及url
th:text="#{login.username}"
页面国际化,涉及配置文件
即根据自己的需要实现中英文的切换
- 配置i18n文件
- 如果需要在项目中按钮自动切换,需要自定义组件
LocaleResolver
- 记得将自己的组件配到SpringBoot中
@Bean
自定义设置请求头的语言
public class MyLocaleResolver implements LocaleResolver {
//可以用来设置请求头的language
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//获取前端的参数
String parameter = httpServletRequest.getParameter("l");
//获取默认时区地址
Locale locale = Locale.getDefault();
if (!StringUtils.isEmpty(parameter)) {
String[] split = parameter.split("_");
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
记得注入到SpringBoot中(此文件用来存放自己的MvcConfig)
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
//手动设置首页跳转
public void addViewControllers(ViewControllerRegistry registry) {
//首页
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
//主页,当我们接收到了main.html时,会去找show,此时boot会背囊我们完成在template下的拼接
registry.addViewController("/main.html").setViewName("show");
}
//将Bean进行注册入springBoot中(作用,中英文切换)
@Bean
public LocaleResolver localeResolver(){//这个名字貌似必须为localeResolver
return new MyLocaleResolver();
}
}
编写i18n配置文件,即国际化语言,可以实现中文和英文
首页编写
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
<!-- 通过thymeleaf引入bootstrap 链接地址@{}-->
<link th:href="@{/css/bootstrap.min.js}">
</head>
<body>
<h1>这是登录首页</h1>
<form th:action="@{/user/login}" method="post">
<!-- 配置文件的参数 #{}-->
<label th:text="#{login.tip}">Please sign in</label><br>
<!--通过th:text表示展示的内容 判断语句,判断msg字符串不为空 可以将!换为not-->
<label th:text="${msg}" style="color: red" th:if="${! #strings.isEmpty(msg)}"></label><br>
<label th:text="#{login.username}">Username</label>
<input type="text" th:placeholder="#{login.username}" name="username"><br>
<label th:text="#{login.password}">Password</label>
<input type="text" th:placeholder="#{login.password}" name="password"><br>
<!-- 像checkbox、submit这些本身就不用写什么值,因此不存在th:text这类属性,我们可以通过行内字符来写[[]]-->
<input type="checkbox">[[#{login.remember}]]<br>
<button type="submit">[[#{login.btn}]]</button>
<br>
<!-- 会有自动拼接-->
<a th:href="@{/index(l='zh_CN')}">中文</a><br>
<a th:href="@{/index(l='en_US')}">English</a>
</form>
</body>
</html>
登录拦截
拦截器三个方法:
preHandler
- 调用controller之前
- 若返回false,则中断执行,不会执行AfterCompletion
- 链式Intercepter情况下,Intercepter按照声明的顺序一个接一个执行
PostHandler
- preHandler返回true
- 在执行完controller之后,因此可以对modelAndView进行操作
- 链式Intercepter情况下,Intercepter按照声明的顺序倒着执行
AfterCompletion
- preHandler返回true
- DispatcherServlet进行渲染之后
- 多用于清理资源
MyMvcConfig
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index","/","/user/login","/css/**");
}
LoginController
@Controller
public class LoginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model, HttpSession session) {
// 空和null都会判断
if (!StringUtils.isEmpty(username) && "123".equals(password)) {//登录成功
session.setAttribute("loginUser", username);
return "redirect:/main.html";
}else {
model.addAttribute("msg", "用户名或密码错误!");
return "index";
}
}
}
LoginHandlerInteceptor
//登录拦截器
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录成功后,将用户存入session中
Object loginUser = request.getSession().getAttribute("loginUser");
if (loginUser == null) {
request.setAttribute("msg", "没有权限,请先登录");
request.getRequestDispatcher("/index").forward(request, response);
return false;
}else {
return true;
}
}
}
抽取组件/循环/判断
th:fragment="sidebar"
th:replace="~{common/commons::sidebar}"
th:insert="~{show::sidebar}"
抽取出来的公共组件
<body>
<!--方法二:我们创建一个commons用来将所有的公共页面进行抽取,然后将抽取的部分用insert/replace进行一个插入-->
<!--div展示-->
<div style="height: 50px; width: 50%; border:1px black solid" th:fragment="sidebar"></div>
</body>
引入组件
<!-- 引入公共组件-->
<div th:replace="~{common/commons::sidebar}"></div>
循环/判断/组件传参
<body>
<!--插入show.html中的sidebar-->
<!--insert和replace实现的功能一样,但是二者的含义不一样-,一个是嵌套,一个是直接替换-->
<!--<div th:insert="~{show::sidebar}"></div>-->
<!--组件传参-->
<div th:replace="~{common/commons::sidebar(active='list.html')}"></div>
<table>
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>department</th>
<th>birth</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- thymeleaf循环-->
<tr th:each="emp:${emps}}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getLastName()}"></td>
<td th:text="${emp.getEmail()}"></td>
<!--判断-->
<td th:text="${emp.getGender()==0?'女':'男'}"></td>
<td th:text="${emp.department.getDepartment()}"></td>
<!-- thymeleaf中对java.util.Date中做的工具类#dates-->
<!--时间格式化-->
<td th:text="${#dates.format(emp.getBirth(),yyyy-MM-dd HH:mm:ss}}"></td>
<td >
<button>编辑</button>
<button>删除</button>
</td>
</tr>
</tbody>
</table>
</body>
组件接收参数
<!--判断组件传的参数,进行高亮的显示-->
<a th:href="@{/emps}" th:class="${active=='list.html'?'nav-link active':'nav-link'}">员工展示</a>
<a th:href="@{/index}">返回登录页</a>
增删查改
add.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>添加员工</title>
</head>
<body>
<form th:action="@{/addEmp}" method="post">
id:<input type="text" name="id"><br>
lastName:<input type="text" name="lastName"><br>
email:<input type="text" name="email"><br>
gender:
<input type="radio" name="gender" value="1">男
<input type="radio" name="gender" value="0">女 <br>
department:
<select name="department.id">
<option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select><br>
birth:
<input type="text" name="birth"><br>
<button type="submit">添加</button>
</form>
</body>
</html>
list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>列表</title>
</head>
<body>
<!--插入show.html中的sidebar-->
<!--insert和replace实现的功能一样,但是二者的含义不一样-,一个是嵌套,一个是直接替换-->
<!--<div th:insert="~{show::sidebar}"></div>-->
<!--组件传参-->
<!--<div th:replace="~{common/commons::sidebar(active='list.html')}"></div>-->
<a th:href="@{/toAdd}">添加员工</a>
<a th:href="@{/logout}">注销</a>
<table>
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>department</th>
<th>birth</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${employees}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getLastName()}"></td>
<td th:text="${emp.getEmail()}"></td>
<td th:text="${emp.getGender()==0?'女':'男'}"></td>
<td th:text="${emp.department.getDepartmentName()}"></td>
<!-- thymeleaf中对java.util.Date中做的工具类#dates-->
<td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
<td >
<!-- 传参-->
<a th:href="@{/update/}+${emp.getId()}">编辑</a>
<a th:href="@{/delete/}+${emp.getId()}">删除</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>
update.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>修改页面</title>
</head>
<body>
<form th:action="@{/realUpdate}" method="post">
<input type="hidden" name="id" th:value="${emp.getId()}"><br>
lastName:<input type="text" name="lastName" th:value="${emp.getLastName()}"><br>
email:<input type="text" name="email" th:value="${emp.getEmail()}"><br>
gender:
<input type="radio" name="gender" value="1" th:checked="${emp.getGender()==1}">男
<input type="radio" name="gender" value="0" th:checked="${emp.getGender()==0}">女 <br>
department:
<select name="department.id">
<option th:each="dept:${depts}" th:selected="${dept.getId()}==${emp.getDepartment().getId()}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select><br>
birth:
<input type="text" name="birth" th:value="${emp.getBirth()}"><br>
<button type="submit">修改</button>
</form>
</body>
</html>
EmployeeController
@Controller
public class EmployeeController {
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
private DepartmentRepository departmentRepository;
@RequestMapping("/emps")
public String getAll(Model model) {
Collection<Employee> employees = employeeRepository.query();
model.addAttribute("employees", employees);
return "/emp/list";
}
@GetMapping("/toAdd")
public String toAdd(Model model) {
//获取所有部门
Collection<Department> departments = departmentRepository.getAllDep();
model.addAttribute("departments", departments);
return "emp/add";
}
@PostMapping("/addEmp")
public String addEmp(Employee employee) {
//添加的操作
employeeRepository.add(employee);
Integer id = employee.getDepartment().getId();
Department dept = departmentRepository.getDepById(id);
employee.getDepartment().setDepartmentName(dept.getDepartmentName());
return "redirect:/emps";
}
// @RequestMapping("/toUpdatePage")
// public String toUpdatePage() {
// return "emp/update";
// }
@RequestMapping("/update/{id}")
public String update(@PathVariable("id") Integer id, Model model) {
Employee emp = employeeRepository.queryById(id);
model.addAttribute("emp", emp);
Collection<Department> depts = departmentRepository.getAllDep();
model.addAttribute("depts", depts);
return "emp/update";
}
@RequestMapping("/realUpdate")
public String realUpdate(Employee employee) {
employeeRepository.add(employee);//修改和增加都可以实现
Integer id = employee.getDepartment().getId();
Department dept = departmentRepository.getDepById(id);
employee.getDepartment().setDepartmentName(dept.getDepartmentName());
return "redirect:/emps";
}
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") Integer id) {
employeeRepository.delete(id);
return "redirect:/emps";
}
@RequestMapping("/logout")
public String logout(HttpSession session) {
session.invalidate();
// return "redirect:/main";//会有没有权限的提示
return "redirect:/index";//直接返回首页
}
}