准备工作
第一步: 创建Maven工程然后手动添加web模块
第二步: 在pom.xml
文件中指定Maven工程的打包方式war
第三步: 引入依赖,由于Maven的传递性,我们不必将所有需要的包全部配置依赖,只需要配置最顶端的依赖,其他依赖靠传递性导入
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.atguigugroupId>
<artifactId>spring_mvc_restartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.3.1version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.3version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring5artifactId>
<version>3.0.12.RELEASEversion>
dependency>
dependencies>
project>
第四步: 在web.xml文件中配置SpringMVC的前端控制器DispatcherServlet,配置编码过滤器,配置HiddenHttpMethodFilter
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceResponseEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<filter>
<filter-name>HiddenHttpMethodFilterfilter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<servlet>
<servlet-name>DispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springMVC.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>DispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
第五步: 创建springMVC的配置文件,扫描所有组件,配置Thymeleaf视图解析器,配置视图控制器(开启MVC注解驱动),配置静态资源映射
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.atguigu.rest">context:component-scan>
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
bean>
property>
bean>
property>
bean>
<mvc:view-controller path="/" view-name="index">mvc:view-controller>
<mvc:view-controller path="/toAdd" view-name="employee_add">mvc:view-controller>
<mvc:default-servlet-handler />
<mvc:annotation-driven />
beans>
数据准备
第一步: 准备实体类封装查询到的数据
public class Employee {
private Integer id;
private String lastName;
private String email;
//1 male, 0 female
private Integer gender;
//getter和setter方法
public Employee(Integer id, String lastName, String email, Integer gender) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
public Employee() {
}
}
第二步: 准备dao接口及其实现类模拟连接数据库做增删改查操作
@Repository
public class EmployeeDao {
private static Map<Integer, Employee> employees = null;
static{
employees = new HashMap<Integer, Employee>();
employees.put(1001, new Employee(1001, "E-AA", "[email protected]", 1));
employees.put(1002, new Employee(1002, "E-BB", "[email protected]", 1));
employees.put(1003, new Employee(1003, "E-CC", "[email protected]", 0));
employees.put(1004, new Employee(1004, "E-DD", "[email protected]", 0));
employees.put(1005, new Employee(1005, "E-EE", "[email protected]", 1));
}
// 设置添加员工时Id的初始化值
private static Integer initId = 1006;
// 添加和修改员工信息
public void save(Employee employee){
// 判断员工信息中是否包含Id,如果有表示需要修改员工信息,没有表示需要添加员工
if(employee.getId() == null){
employee.setId(initId++);
}
// 对于修改员工信息,如果Map集合中的key重复时value会覆盖
employees.put(employee.getId(), employee);
}
// 查询所有员工信息
public Collection<Employee> getAll(){
return employees.values();
}
// 根据id查询某个员工信息
public Employee get(Integer id){
return employees.get(id);
}
// 根据id删除某个员工信息
public void delete(Integer id){
employees.remove(id);
}
}
编写控制器方法
创建处理员工业务相关的请求控制器类EmployeeController
@Controller
public class EmployeeController {
// 自动注入Dao层组件
@Autowired
private EmployeeDao employeeDao;
//编写控制器方法
}
功能 | URL 地址 | 请求方式 |
---|---|---|
访问首页 | / | GET |
查询所有员工信息 | /employee | GET |
根据Id删除员工 | /employee/2 | DELETE |
跳转到添加员工信息的页面 | /toAdd | GET |
新增员工 | /employee | POST |
跳转到修改员工信息的页面,修改前需要先把员工原本的信息查询出来 | /employee/2 | GET |
修改员工信息 | /employee | PUT |
访问首页功能
第一步: 创建首页面index.html
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" >
<title>Titletitle>
head>
<body>
<h1>首页h1>
<a th:href="@{/employee}">查询所有员工的信息a>
body>
html>
第二步: 在SpringMVC配置文件中使用view-controller标签
配置视图控制器跳转到首页
<mvc:view-controller path="/" view-name="index"/>
<mvc:annotation-driven />
查询所有员工并展示
第一步: 在首页点击查询查询员工所有信息的链接
<a th:href="@{/employee}">查询所有员工的信息a>
第二步: 编写控制器方法负责查询所有的员工信息并跳转到员工列表页面展示查询到的数据
//@RequestMapping(value = "/employee", method = RequestMethod.GET)
@GetMapping("/employee")
public String getEmployeeList(Model model){
// 获取所有的员工信息
Collection<Employee> employeeList = employeeDao.getAll();
// 使用model的方式将获取的员工信息添加到请求域共享
model.addAttribute("employeeList", employeeList);
// 返回视图名称,跳转到员工列表页面
return "employee_list";
}
第二步: 创建employee_list.html
,将请求域中查询到的所有员工信息动态展示出来,并提供对每个员工修改和删除的超链接
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Employee Infotitle>
<link rel="stylesheet" th:href="@{/static/css/index_work.css}">
<script type="text/javascript" th:src="@{/static/js/vue.js}">script>
head>
<body>
<table border="1" cellpadding="0" cellspacing="0" style="text-align: center;" id="dataTable">
<tr>
<th colspan="5">Employee Infoth>
tr>
<tr>
<th>idth>
<th>lastNameth>
<th>emailth>
<th>genderth>
<th>options(<a th:href="@{/toAdd}">adda>)th>
tr>
<tr th:each="employee : ${employeeList}">
<td th:text="${employee.id}">td>
<td th:text="${employee.lastName}">td>
<td th:text="${employee.email}">td>
<td th:text="${employee.gender}">td>
<td>
"@{'/employee/'+${employee.id}}"或"@{/employee/}+${employee.id}}"
<a class="deleteA" @click="deleteEmployee" th:href="@{'/employee/'+${employee.id}}">deletea>
<a th:href="@{'/employee/'+${employee.id}}">updatea>
td>
tr>
table>
body>
html>
添加员工
第一步: 用户点击employee_list.html页面中的add超链接
会发起GET请求,然后跳转到添加员工信息的页面employee_add.html
<tr>
<th>idth>
<th>lastNameth>
<th>emailth>
<th>genderth>
<th>options(<a th:href="@{/toAdd}">adda>)th>
tr>
第二步: 在SpringMVC配置文件中使用view-controller
标签配置视图控制器跳转到employee_add.html页面
<mvc:view-controller path="/toAdd" view-name="employee_add">mvc:view-controller>
<mvc:annotation-driven />
第三步: 创建employee_add.html页面保存要添加员工的信息且不含有员工Id,最后发起POST请求提交员工信息
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Add Employeetitle>
<link rel="stylesheet" th:href="@{/static/css/index_work.css}">
head>
<body>
<form th:action="@{/employee}" method="post">
lastName:<input type="text" name="lastName"><br>
email:<input type="text" name="email"><br>
gender:<input type="radio" name="gender" value="1">male
<input type="radio" name="gender" value="0">female<br>
<input type="submit" value="add"><br>
form>
body>
html>
第四步: 用户点击employee_add.html页面上的add表单提交按钮
,执行添加员工的控制器方法
//@RequestMapping(value = "/employee", method = RequestMethod.POST)
@PostMapping("/employee")
public String addEmployee(Employee employee){
employeeDao.save(employee);
// 添加完员工后需要重定向到查询所有员工功能的请求,因为员工数据有变化需要重新查询并渲染
// 重定向的目的就是为了刷新地址栏,防止用户一直刷新添加员工的请求
return "redirect:/employee";
}
修改员工信息
第一步: 用户点击employee_list.html页面中的update超链接
会发起GET请求
<td>
<a th:href="@{'/employee/'+${employee.id}}">updatea>
td>
第二步: 编写控制器方法负责根据员工Id查询员工信息并跳转到修改员工信息的页面展示查询到的数据
//@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
@GetMapping("/employee/{id}")
public String getEmployeeById(@PathVariable("id") Integer id, Model model){
// 查询要修改的员工信息并存放到请求域中
Employee employee = employeeDao.get(id);
model.addAttribute("employee", employee);
// 跳转到修改员工信息的页面employee_update.html
return "employee_update";
}
第三步: 创建employee_update.html页面,将请求域中查询到的要修改的员工信息展示出来并且员工Id会隐藏起来不显示
@{}和${}
,那么对应的属性就需要使用th
命名空间修饰,这样Thymeleaf视图解析器才会知道对哪个标签解析DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Update Employeetitle>
<link rel="stylesheet" th:href="@{/static/css/index_work.css}">
head>
<body>
<form th:action="@{/employee}" method="post">
<input type="hidden" name="_method" value="put">
<input type="hidden" name="id" th:value="${employee.id}">
lastName:<input type="text" name="lastName" th:value="${employee.lastName}"><br>
email:<input type="text" name="email" th:value="${employee.email}"><br>
gender:<input type="radio" name="gender" value="1" th:field="${employee.gender}">male
<input type="radio" name="gender" value="0" th:field="${employee.gender}">female<br>
<input type="submit" value="update"><br>
form>
body>
html>
第三步: 用户点击employee_update.html页面中update表单的提交按钮
后,执行修改员工信息的控制器方法
//@RequestMapping(value = "/employee", method = RequestMethod.PUT)
@PutMapping("/employee")
public String updateEmployee(Employee employee){
// 保存修改后的员工信息(包含员工Id)
employeeDao.save(employee);
// 修改完员工信息后需要重定向到查询所有员工功能的请求,因为员工数据有变化需要重新查询并渲染
// 重定向的目的就是为了刷新地址栏,防止用户一直刷新添加员工的请求
return "redirect:/employee";
}
根据Id删除员工
第一步: 因为用户点击delete按钮
是个超链接只能发起GET请求,所以我们需要通过点击超链接执行点击事件deleteEmployee
控制表单的提交
<div id="app">
<a @click="deleteEmployee" th:href="@{'/employee/'+${employee.id}}">deletea>
<form id="deleteForm" method="post">
<input type="hidden" name="_method" value="delete">
form>
div>
<script type="text/javascript" th:src="@{/static/js/vue.js}">script>
<script type="text/javascript">
var vue = new Vue({
el:"#app",
methods:{
deleteEmployee:function (event) {// event表示当前事件
// 通过标签的id获取表单标签
var delete_form = document.getElementById("deleteForm");
// 将触发点击事件元素即超链接的href属性赋值给form表单的action属性
delete_form.action = event.target.href;
// 提交表单
delete_form.submit();
// 阻止超链接默认的跳转行为
event.preventDefault();
}
}
});
script>
第二步: 编写控制器方法根据Id删除对应的员工
//@RequestMapping(value = "/employee/{id}", method = RequestMethod.DELETE)
@DeleteMapping("/employee/{id}")
public String deleteEmployee(@PathVariable("id") Integer id){
// 根据Id删除对于的员工
employeeDao.delete(id);
// 删除完员工后需要重定向到查询所有员工功能的请求,因为员工数据有变化需要重新查询并渲染
// 重定向的目的就是为了刷新地址栏,防止用户一直刷新添加员工的请求
return "redirect:/employee";
}