SpringBoot Web 开发
- 导入静态资源
- 首页
- jsp,模板引擎 Thymeleaf
- 装配扩展SpringMVC
- 增删改查
- 拦截器
- 国际化
静态资源
新建一个项目后 首先测试Controoller 是否可用
总结:
- 在springboot,我们可以使用以下方式处理静态资源
- webjars
localhost:8080/webjars/
- public, static, resources,/**
localhost:8080/
- 优先级: resources>static (默认) >public
定制首页
观察源码可知,首页为 index.html
这三个文件夹均可放 index.html
不过一般放在 static
通过controller跳转至首页
- 配置Thymeleaf
<!-- themeleaf,基于3.x开发-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
- html文件存放
- 编写Controller代码
thymeleaf语法
- html 端语法
在html页面加上 xmlns:th=“http://www.thymeleaf.org”
- thymeleaf 转义与否
- 遍历数组里的值
扩展spring MC
package com.kuang.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
//如果,你想diy一些定制化的功能,只要写这个组件,
// 然后将它交给springboot,springboot就会帮我们自动装配!
//扩展springmvc dispatcherservlet
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//ViewResolver 实现了视图解析器接口的类,我们就可以把它看做视图解析器
@Bean
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
//自己定义了一个视图解析器 MyViewResolver
public static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String s, Locale locale) throws Exception {
return null;
}
}
}
视图跳转操作
package com.kuang.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//如果我们要扩展 MVC ,官方建议我们这样做
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//视图跳转 输入 kuang 跳转至 test 界面
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/kuang").setViewName("test");
}
}
员工管理系统
- 去搜索 bootstrap 模板 下载前端模板
html文件放在templates下面,css等文件放在static下面 - 新建 pojo 包,在pom.xml 添加 lombok依赖
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
- 在pojo新建实体类 Department、Employee
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data //get、 set、 toString
@AllArgsConstructor //有参构造
@NoArgsConstructor //无参构造
public class Department {
private Integer id;
private String departmentName;
}
package com.kuang.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
//员工表
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender; //0为女,1为男
private Department department;
private Date birth; //是util包下的,其他包会报错
}
- 新建对实体类的操作 Dao层,DepartmentDao,EmployeeDao
package com.kuang.dao;
import com.kuang.pojo.Department;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
//部门dao
@Repository
public class DepartmentDao {
//模拟数据库中的数据
//新建一个Map键值对 departments,键为 integer 值为 department
private static Map<Integer, Department> departments = null;
//静态 最先执行 优先加载
static{
departments = new HashMap<Integer, Department>(); //创建一个部门表
departments.put(101,new Department(101,"教学部"));
departments.put(102,new Department(102,"市场部"));
departments.put(103,new Department(103,"教研部"));
departments.put(104,new Department(104,"运营部"));
departments.put(105,new Department(105,"后勤部"));
}
//模拟数据库的操作
//获得所有部门信息
public Collection<Department> getDepartments(){
return departments.values();
}
//通过id得到部门
public Department getDepartmentById(Integer id){
return departments.get(id);
}
}
package com.kuang.dao;
import com.kuang.pojo.Department;
import com.kuang.pojo.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
//员工操作 Dao
@Repository
public class EmployeeDao {
//模拟数据
//新建一个Map键值对 departments,键为 integer 值为 department
private static Map<Integer, Employee> employees = null;
//员工有所属的部门 外表
@Autowired
private DepartmentDao departmentDao;
static{ //static 优先加载
employees = new HashMap<Integer, Employee>(); //创建一个部门表
employees.put(1001,new Employee(1001,"AA","1803291168@qq.com",1,new Department(101,"教学部")));
employees.put(1002,new Employee(1002,"AA","1803291168@qq.com",1,new Department(102,"市场部")));
employees.put(1003,new Employee(1003,"AA","1803291168@qq.com",1,new Department(103,"教研部")));
employees.put(1004,new Employee(1004,"AA","1803291168@qq.com",1,new Department(104,"运营部")));
employees.put(1005,new Employee(1005,"AA","1803291168@qq.com",1,new Department(105,"后勤部")));
}
//主键自增!
private static Integer initId = 1006;
//增加一个员工
public void save(Employee employee){
if(employee.getId()==null){
employee.setId(initId++);
}
//外键关联
employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
employees.put(employee.getId(),employee);
}
//查询全部员工信息
public Collection<Employee> getAll(){
return employees.values();
}
//通过ID查询员工
public Employee getEmployeeById(Integer id){
return employees.get(id);
}
//删除员工
public void deleteEmployeeById(Integer id){
employees.remove(id);
}
}
- 跳转页面的两种配法
- 在controller层配置
package com.kuang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping({"/","/index.html"})
public String index(){
return "index";
}
}
- 在config层配置,重载视图管理方法
package com.kuang.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 {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//重载 视图控制层
// 用户输入 ‘/’ 则自动跳转去 ‘index’
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
}
}
html 支持thymeleaf
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{/css/signin.css}" rel="stylesheet">
静态资源 href 等,要写成 thymeleaf 的格式,方便被thymeleaf托管; th: + @{ }
==注意:==在线链接不能改,只需改本地链接,链接图片、CSS等
国际化
- IDEA变成utf-8
- 配置i18n文件
新建文件夹 i18n ,然后新建文件 login.properties、login_en_US.properties、login_zh_CN.properties 三个文件
然后写变量名和值
在 yaml中配置
- 在html文件里 替换文本
一般用 方式1 th: + #{} 的形式,若不行就用 方式2
- 需要自定义一个组件
LocaleResover
- 前端加上链接消息
- 接管配置
代码为
package com.kuang.config;
import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//获取前端页面请求中的语言参数,变量为 l
String language = httpServletRequest.getParameter("l");
Locale locale = Locale.getDefault(); //如果前端链接没有传值就使用默认的
//如果请求的链接携带了国际化参数
if(!StringUtils.isEmpty(language)){
//zh_CN
String[] split = language.split("_");
//Locale的参数为 语言代码 ,国家地区
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
- 记得将自己写的组件配置到spring容器@Bean
全部代码为
package com.kuang.config;
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.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//重载 视图控制层
// 用户输入 ‘/’ 则自动跳转去 ‘index’
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
//自定义的国际化组件就生效了
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
员工登录
- 前端页面添加 th:action
发送请求 /user/login
- 新增 LoginController ,添加注解
@RequestMapping("/user/login")
获取前端的 请求th:action="@{/user/login}"
;
在前端页面的 input框中 添加name属性,用户输入的内容就和前端的 username 绑定;
在后端 用注解 @RequestParam("username") String username
,将前端的 username 和 后端的变量 username 绑定;
- 登录判断成功则跳转至相应页面,
在这里,登录成功就重定向到 main.html
需要在 MyMvcConfig里面配置映射,因为我们没有 main.html 这个文件,所以将其映射到 dashboard
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JH0qQDlP-1629031010627)(C:\Users\Administrator\Desktop\Spring Boot\SpringBootWeb开发.assets\image-20210814110734699.png)]
下面的文件才是我们有的
整个MyMvcConfig代码
package com.kuang.config;
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.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//重载 视图控制层
// 用户输入 ‘/’ 则自动跳转去 ‘index’
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
registry.addViewController("/main.html").setViewName("dashboard");
}
//自定义的国际化组件就生效了
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
- 登录失败,绑定一个msg消息,用于回显提示
在前端添加代码,显示这个msg信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FSzdzn38-1629031010631)(C:\Users\Administrator\Desktop\Spring Boot\SpringBootWeb开发.assets\image-20210814111312413.png)]
<!-- 如果msg值不为空,则显示 msg,if用 $ ,表达式用 #-->
<p style="color: red" th:text="${msg}" th:if="${! #strings.isEmpty(msg)}"></p>
- 整个LoginController 代码
package com.kuang.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.thymeleaf.util.StringUtils;
//登录控制
@Controller
public class LoginController {
@RequestMapping("/user/login") //接收index.html传过来的 ‘/user/login’ 请求
//@ResponseBody //生成一个页面,内容为 return的字符串 ,不会跳转到视图
public String login(@RequestParam("username") String username , //@RequestParam 注解的参数来自前端中的 name属性
@RequestParam("password") String password ,
Model model) {
//具体的业务
//用户名不为空 且 密码为123456则登录成功
if (!StringUtils.isEmpty(username) && password.equals("123456")) { //登录成功
return "redirect:/main.html"; //重定向到 main.html 需要在 MyMvcConfig 里设置映射
//return "dashboard"; //直接跳转去 dashboard 页面
} else { //登录失败
model.addAttribute("msg", "用户名或密码错误"); //model 用于前端消息回显
return "index";
}
}
}
登录拦截器
- 新建一个 登录拦截器
LoginHandlerInterceptor
,其继承HandlerInterceptor
。
对应的java代码
package com.kuang.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginHandlerInterceptor implements HandlerInterceptor {
//该拦截器需要重载1个方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//登录成功后,应该有用户的session
Object loginUser = request.getSession().getAttribute("loginUser");
if(loginUser == null){ //没有登录
//设置 msg 用于前端消息回显
request.setAttribute("msg","请先登录");
//重定向到 index.html 界面;该写法 就是传统的 JSP 写法
request.getRequestDispatcher("/index.html").forward(request,response);
//不放行
return false;
}else { //登录
return true;
}
}
}
- 在MyMvcConfig里添加拦截器
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns("/**") //拦截所有静态资源
.excludePathPatterns("/index.html","/","/user/login","/css/**","/js/**","/img/**"); //除了这几个不拦截
}
员工列表展示
提取公共页面
- 新建 commons文件夹 及 commons.html 文件
- 将其他页面,比如 list.html 和 dashboard.html 中公共的代码抽取出来,放到 commons.html 中,要在第一个标签里加上
th:fragment="topBar"
然后在需要 引入的页面中添加 th:replace="~{commons/commons::topBar}"
代码,这样就能引入 公共页面的代码,完成代码复用
完整的 commons.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!--头部导航栏-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topBar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" th:text="${session.loginUser}">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/#">注销</a>
</li>
</ul>
</nav>
<!--侧边栏-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sideBar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a th:class="${active=='main.html'?'nav-link active':'nav-link'}" th:href="@{/index.html}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
首页 <span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
<polyline points="13 2 13 9 20 9"></polyline>
</svg>
Orders
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shopping-cart">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
</svg>
Products
</a>
</li>
<li class="nav-item">
<a th:class="${active=='list.html'?'nav-link active':'nav-link'}" th:href="@{/emps}">
<circle cx="9" cy="7" r="4"></circle>
</svg>
员工管理
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-bar-chart-2">
<line x1="18" y1="20" x2="18" y2="10"></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg>
Reports
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layers">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg>
Integrations
</a>
</li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Saved reports</span>
<a class="d-flex align-items-center text-muted" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
</a>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Current month
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Last quarter
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Social engagement
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Year-end sale
</a>
</li>
</ul>
</div>
</nav>
</html>
标签高亮
- 在commons.html中,添加下述代码
注:${}
是用来写java表达式的
然后在 list.html 中添加参数
在 main.html 中,也添加参数
可实现选中高亮
员工列表显示
- 后端:
新增一个 EmployeeController
完整代码:
package com.kuang.controller;
import com.kuang.dao.EmployeeDao;
import com.kuang.pojo.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Collection;
@Controller
public class EmployeeController {
//引入另外的java类 都得写该注释
@Autowired
EmployeeDao employeeDao;
//获取前端的 /emps 请求
@RequestMapping("/emps")
public String list(Model model){
Collection<Employee> employees = employeeDao.getAll();
//将 employees 数据绑定至 emps 用于前端显示
model.addAttribute("emps",employees);
//前端请求响应到 emp/list.html 中
return "emp/list";
}
}
- 前端:在 emp/list.html 中引入数据
前端表格代码
<table class="table table-striped table-sm">
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>departmentId</th>
<th>departmentName</th>
<th>birth</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<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()==1?'男':'女'}"></td>
<td th:text="${emp.getDepartment().getId()}"></td>
<td th:text="${emp.getDepartment().getDepartmentName()}"></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>
</tbody>
</table>
添加员工
- 新建add.html 将公共部分的导航栏和侧边栏写进去
在前端写一个form表单
<form th:action="@{/emp}" method="post">
<div class="form-group">
<label>LastName</label>
<!-- 注意 此处的 name="lastName" 必须与后台pojo保持一致 -->
<input type="text" name="lastName" class="form-control" placeholder="chenhao">
</div>
<div class="form-group">
<label>Email</label>
<!-- 注意 此处的 name="email" 必须与后台pojo保持一致 -->
<input type="email" name="email" class="form-control" placeholder="1803291168@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>
<select class="form-control" name="department.id">
<!-- 下面的下拉框中,th:text 是显示的文本,th:value 才是提交的值-->
<option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<input type="text" name="birth" class="form-control" placeholder="chenhaostudy">
</div>
<button type="submit" class="btn btn-primary">添加</button>
</form>
- 在EmployeeController 里面添加 post请求
//post 请求 与前端 emp 对应
@PostMapping("/emp")
public String addEmp(Employee employee){
//添加的操作
System.out.println("save=>"+employee);
//调用dao层方法 保存员工信息
employeeDao.save(employee);
//重定向到 emps
return "redirect:/emps";
}