SpringBootWeb开发
@Bean为自己配置的组件
1.导入静态资源
- webjars 通过访问localhost:8080/webjars/
- public,static,resource 通过访问localhost:8080/static/
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<img th:src="@{/img/bootstrap-solid.svg}">
2.首页
- 使用RequestMapping需要Thymeleaf的依赖
- 在static文件夹添加favicon.ico会修改浏览器的默认图标
- 首先使用thymeleaf语法替换原来的index.html
3.模板引擎Thymeleaf
变量表达式${}
国际化消息#{}
Link URL @{}
>,<,>=,<= (gt,lt,ge,le)
(if)?(then):(else)
- 模板引擎是将视图与用户数据分离,也就是模板和数据通过模板引擎生成最终的html代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- thymeleaf的模板在template里
- 在ThymeleafProperties里读源码找prefix和suffix找到前缀和后缀
model.addAttribute("msg","<h1>hello,springboot</h1>");
model.addAttribute("users", Arrays.asList("123","456"));
//使用RequestMapping("/test")跳转页面,同时渲染模板
<h1 th:text="${msg}"></h1>
//遍历取出每个元素,然后将元素渲染
<div th:each="user:${users}" th:text="${user}"></div>
///使用了#strings.isEmpty(msg)来判断是否为空
<p style="color:red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
4.装配扩展SpringMVC
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Bean
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
public static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard");
}
if(!StringUtils.isEmpty(username) && password.equals("123456"))
{
return "redirect:/main.html";
}
@Bean
public LocaleResolver localeResolver(){
return new MyLocalResolver();
}
}
5.增删改查
在pojo中增加@Data(getter && setter)
增加@AllArgsConstructor为无参构造,@NoArgsConstructor有参构造
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
<div th:replace="~{commons/common::sidebar(active='main.html')}"></div>
- 列表循环展示,先提取单个变量,然后使用方法获得值
- 注意其中有判断的地方和日期格式化
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getName()}"></td>
<td th:text="${emp.getEmail()}"></td>
<td th:text="${emp.getGender() == 0?'女':'男'}"></td>
<td th:text="${emp.getDepartment().getName()}"></td>
<td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
<td>
<button class="btn btn-sm btn-primary">编辑</button>
<button class="btn btn-sm btn-danger">编辑</button>
</td>
</tr>
- 大体思路是先通过页面的链接标签来对应Controller的方法
<a class="btn btn-sm btn-primary" th:href="@{/emp/{id}(id=${emp.getId()})}">编辑</a>
<a class="btn btn-sm btn-danger" th:href="@{/delemp/{id}(id=${emp.getId()})}">删除</a>
//提交表单对应后端的响应
<form th:action="@{/emp}" method="post">
@GetMapping("/emp")
public String toAddPage(Model model){
Collection<Department> departments = departmentDao.getAllDepartments();
model.addAttribute("departments",departments);
return "emp/add";
}
@PostMapping("/emp")
public String addEmp(Employee employee){
System.out.println(employee);
employeeDao.add(employee);
return "redirect:/emps";
}
@GetMapping("/emp/{id}")
public String toUpdatePage(@PathVariable("id")Integer id, Model model)
{
System.out.println(id);
Employee employee = employeeDao.getEmployee(id);
model.addAttribute("employee",employee);
System.out.println(employee);
Collection<Department> departments = departmentDao.getAllDepartments();
model.addAttribute("departments",departments);
return "emp/update";
}
- model的addAttribute()方法会将设置的object值传给前端
<input type="hidden" name="id" th:value="${employee.getId()}">
<div class="form-group">
<label>department</label>
<select class="form-control" name="department.id">
<option th:each="department:${departments}" th:text="${department.getName()}" th:selected="${department.getId() == employee.getDepartment().getId()}" th:value="${department.getId()}"></option>
</select>
</div>
6.拦截器
- 首先是拦截器的配置,需要实现HandlerInterceptor
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public 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.html").forward(request,response);
return false;
}
else
return true;
}
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login","/css/**","/js/**","/img/**");
}
7.国际化
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
<input type="password" class="form-control" th:placeholder="#{login.password}" required="">
- 配置i18n文件
- 自定义LocaleResolver()
- 组件配置配置到自定义的MVC @Bean
@Bean
public LocaleResolver localeResolver(){
return new MyLocalResolver();
}
public class MyLocalResolver 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("_");
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
- 模板引擎渲染为@{xxx.html"(传入参数)}
<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>