SSM:员工管理系统
SSM_employee
整合 SSM 的核心在配置文件。
需求:
- 员工:ID、姓名、年龄、薪水;
- 业务:增删改查、模糊搜索;
1、环境搭建
1.1、数据库
employee 表
CREATE TABLE `employee`(
`id` VARCHAR(50) NOT NULL COMMENT '员工ID',
`name` VARCHAR(25) NOT NULL COMMENT '员工姓名',
`age` INT NOT NULL COMMENT '员工年龄',
`salary` DECIMAL NOT NULL COMMENT '员工薪水',
PRIMARY KEY (`id`)
)ENGINE=INNODB CHARSET=utf8 COLLATE=utf8_general_ci;
1.2、项目搭建
新建不带模板的 Maven 项目,添加 web 框架支持。(也可以直接创建 webapp 模板的 Maven 项目)
导入依赖
导入依赖,并在项目结构的 Artifacts:WEB-INF 添加 lib 目录。
-
MyBatis
- MyBatis 框架:mybatis
- MyBatis 整合 Spring:mybatis-spring
- 数据库连接:mysql-connector-java
- C3P0 连接池:c3p0
-
Spring
-
Spring 框架:spring-webmvc
-
AOP:aspectjweaver
-
Spring 获取数据源:spring-jdbc
-
-
Servlet、JSP、JSTL
-
JUnit
<dependencies>
<!-- MyBatis框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- MyBatis整合Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 数据库连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<!-- C3P0连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<!-- Spring框架 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<!-- Spring获取数据源-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
<!--Servlet、JSP、JSTL-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
项目包结构
- utils
- pojo / entity / ...
- dao / mapper
- service
- controller
1.3、基础代码
工具类
IdUtils
-
员工 ID 由系统随机生成,而非用户自定义。
-
本方法为员工 ID 生成随机 UUID
public class IdUtils {
/**
* 生成随机UUID,作为员工ID
*/
public static String getRandomId(){
return UUID.randomUUID().toString().replace("-","");
}
}
实体类
Employee
- ORM 原则
- Spring 注入
- 构造器注入
- setter 注入
- 提供 getter,使用 EL 表达式才能获取到属性
- 实现序列化接口,才能使用二级缓存
public class Employee implements Serializable {
/**
* 员工ID
*/
private String id;
/**
* 员工姓名
*/
private String name;
/**
* 员工年龄
*/
private int age;
/**
* 员工薪水
*/
private BigDecimal salary;
/**
* 随机生成员工ID
*/
public Employee() {
id = IdUtils.getRandomId();
}
public Employee(String name, int age, BigDecimal salary) {
this();
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public BigDecimal getSalary() {
return salary;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
}
DAO层
EmployeeMapper
public interface EmployeeMapper {
/**
* 添加员工
*
* @param employee 待添加员工
* @return 受影响行数
*/
int saveEmployee(Employee employee);
/**
* 删除员工:通过ID
*
* @param id 待删除员工ID
* @return 受影响行数
*/
int deleteEmployee(String id);
/**
* 更新员工
*
* @param employee 包含了待更新员工ID和新属性值
* @return 受影响行数
*/
int updateEmployee(Employee employee);
/**
* 查询员工:通过ID
*
* @param id 待查询员工ID
* @return 待查询员工
*/
Employee getEmployeeById(String id);
/**
* 查询员工:所有
*
* @return 所有员工列表
*/
List<Employee> listEmployees();
}
Service层
EmployeeService
public interface EmployeeService {
/**
* 添加员工
* @param employee 待添加员工
* @return 受影响行数
*/
int saveEmployee(Employee employee);
/**
* 删除员工:通过ID
* @param id 待删除员工ID
* @return 受影响行数
*/
int deleteEmployee(String id);
/**
* 更新员工
* @param employee 包含了待更新员工ID和新属性值
* @return 受影响行数
*/
int updateEmployee(Employee employee);
/**
* 查询员工:通过ID
* @param id 待查询员工ID
* @return 待查询员工
*/
Employee getEmployeeById(String id);
/**
* 查询员工:所有
* @return 所有员工列表
*/
List<Employee> listEmployees();
}
EmployeeServiceImpl
- Service 层调用 DAO 层;
- 提供 EmployeeMapper 接口,用于 Spring 依赖注入
- 可以是 setter 注入,也可以是构造器注入
public class EmployeeServiceImpl implements EmployeeService {
/**
* Service层调用DAO层
*/
private final EmployeeMapper employeeMapper;
/**
* 通过构造器注入依赖
*/
public EmployeeServiceImpl(EmployeeMapper employeeMapper) {
this.employeeMapper = employeeMapper;
}
@Override
public int saveEmployee(Employee employee) {
return employeeMapper.saveEmployee(employee);
}
@Override
public int deleteEmployee(String id) {
return employeeMapper.deleteEmployee(id);
}
@Override
public int updateEmployee(Employee employee) {
return employeeMapper.updateEmployee(employee);
}
@Override
public Employee getEmployeeById(String id) {
return employeeMapper.getEmployeeById(id);
}
@Override
public List<Employee> listEmployees() {
return employeeMapper.listEmployees();
}
}
基础结构搭建完成,开始写配置文件。
2、配置文件
- MyBatis
- db.properties
- mybatis-config.xml
- EmployeeMapper.xml
- Spring
- spring-mybatis.xml
- spring-service.xml
- SpringMVC
- web.xml
- spring-mvc.xml
- applicationContext.xml
配置文件 | 作用 | 说明 |
---|---|---|
db.properties | 数据库连接信息 | (非必要)不创建 properties 文件也可 即可以直接将连接信息写入配置文件中 |
mybatis-config.xml | 配置 MyBatis | (非必要)框架整合后 MyBatis 的工作交给 Spring 完成 |
EmployeeMapper.xml | 编写 SQL 语句 | DAO 层的 Mapper 对应的 XML |
spring-mybatis.xml | 完成 MyBatis 的工作 | 数据源、sqlSessionFactory、Mapper 扫描配置器(或SqlSessionTemplate) |
spring-service | 管理 Service 层 | 添加注解支持、注册 Bean、声明式事务、AOP 等 |
web.xml | 注册 DispatcherServlet、过滤乱码 | |
spring-mvc | 管理 Controller 层 | 添加注解支持、过滤静态资源、注解驱动、视图解析器 |
applicationContext.xml | 合并 Spring 配置文件 | spring-mybatis.xml、spring-service.xml、spring-mvc.xml |
2.1、MyBatis
数据库配置文件
db.properties
-
这个文件是非必要的,其中的配置信息可以直接写在配置文件中。
-
必须有
jdbc.
的前缀。
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_employee?useUnicode=true&useSSL=false&characterEncoding=utf8
jdbc.username=root
jdbc.password=529118
MyBatis 配置文件
mybatis-config.xml
这个文件是非必要的,因为 MyBatis 的工作可以交给 Spring 完成。
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 设置 -->
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 别名 -->
<typeAliases>
<package name="indi.jaywee.pojo"/>
</typeAliases>
</configuration>
Mapper.xml
EmployeeMapper.xml
- 对应 DAO 层的 Mapper,用于编写 SQL 语句;
- 建议放在 resources 目录下,防止 Maven 资源过滤【在 resources 目录下建立与 DAO 层同名的包】
注意:select 语句要有 resultType 或 resultMap 结果集映射。
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="indi.jaywee.mapper.EmployeeMapper">
<!-- 开启二级缓存 -->
<cache/>
<insert id="saveEmployee">
insert into ssm_employee.employee(id, name, age, salary)
values (#{id}, #{name}, #{age}, #{salary})
</insert>
<delete id="deleteEmployee">
delete
from ssm_employee.employee
where id = #{id}
</delete>
<update id="updateEmployee">
update ssm_employee.employee
set name=#{name},
age=#{age},
salary=#{salary}
where id = #{id}
</update>
<select id="getEmployeeById" resultType="employee">
select id, name, age, salary
from ssm_employee.employee
where id = #{id}
</select>
<select id="listEmployees" resultType="employee">
select id, name, age, salary
from ssm_employee.employee
</select>
</mapper>
2.2、Spring
Spring:DAO层(MyBatis)
spring-mybatis.xml
用于完成 MyBatis 的工作。
-
数据源
- 引入数据库配置文件:如果没有写 db.properties,可以省去该步骤;
- 数据源:使用连接池,或者用 Spring 自带的数据源;
-
sqlSessionFactory
- 绑定数据源
- 绑定 MyBatis 配置文件
- 注册 Mapper
-
Mapper 扫描配置器
将 Mapper 自动注入容器,省去创建 MapperImpl 的操作。
- 指定要扫描的包;
- 为 Mapper 接口注入 sqlSessionFactory。
【关于MapperImpl ,详见 Spring 整合 MyBatis】
<?xml version="1.0" encoding="UTF-8"?>
<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"
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">
<!-- 数据源 -->
<!-- 导入数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 数据库连接信息 -->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- C3P0连接池的私有属性 -->
<property name="minPoolSize" value="10"/>
<property name="maxPoolSize" value="30"/>
<!-- 关闭连接后不自动提交 -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="loginTimeout" value="10000"/>
<!-- 获取连接重试次数-->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 绑定数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 绑定MyBatis配置文件 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 注册Mapper -->
<property name="mapperLocations" value="classpath:indi/jaywee/mapper/*.xml"/>
</bean>
<!-- Mapper扫描配置器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定要扫描的包 -->
<property name="basePackage" value="indi.jaywee.mapper"/>
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
</beans>
Spring:Service层
spring-service.xml
使用 Spring 管理 Service 层。
-
添加注解支持:扫描指定包下的 Bean ,被扫描的 Bean 中包含的类级别的注解才会生效,Bean 才会被注册到容器中;
-
注册 Bean:注入依赖,如果飘红说明 Mapper 尚未注入;
-
声明式事务;
-
AOP 等等。
<?xml version="1.0" encoding="UTF-8"?>
<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"
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">
<!-- 添加注解支持 -->
<context:component-scan base-package="indi.jaywee.service"/>
<!-- 注册Bean -->
<bean id="employeeService" class="indi.jaywee.service.EmployeeServiceImpl">
<!-- 如果employeeMapper飘红,说明spring-mybatis.xml中没有扫描Mapper所在包 -->
<constructor-arg ref="employeeMapper"/>
</bean>
<!-- 声明式事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
</bean>
</beans>
SpringMVC:Controller层
spring-mvc.xml
- 添加注解支持:扫描指定包下的 Bean ,被扫描的 Bean 中包含的类级别的注解才会生效,Bean 才会被注册到容器中;
- 过滤静态资源:如 CSS、JS、HTML、MP3、MP4...
- 注解驱动:在 Spring 中一般使用 @RequestMapping 注解来处理映射关系,使用该注解需要注册
处理器映射
和处理器适配器
,annotation-driven 自动注入以上两个实例; - 内部资源视图解析器
<?xml version="1.0" encoding="UTF-8"?>
<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="indi.jaywee.controller"/>
<!-- 过滤静态资源 -->
<mvc:default-servlet-handler/>
<!-- 添加注解驱动 -->
<mvc:annotation-driven/>
<!-- 视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
applicationContext.xml
将 Spring 配置文件合并为一个文件。
- spring-mybatis
- spring-service
- spring-mvc
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:spring-dao.xml"/>
<import resource="classpath:spring-service.xml"/>
<import resource="classpath:spring-mvc.xml"/>
</beans>
2.3、web.xml
- 注册 DispatcherServlet
- 绑定配置文件:总配置文件,否则无法正常注册 Bean ;
- 启动优先级;
- 过滤乱码:注意项目结构需要添加 lib 目录,否则 Tomcat 无法运行。
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- DispatcherServlet-->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 绑定Spring总配置文件! -->
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<!-- 启动优先级 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 字符集过滤器 -->
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 初始化参数 -->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
SSM 基础框架搭建完成,对代码进行测试。
3、测试
对 Service 层业务进行测试。
public class EmployeeServiceTest {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeService employeeService = context.getBean("employeeService", EmployeeService.class);
@Test
public void testSaveEmployee() {
Employee employee1 = new Employee("admin", 1, new BigDecimal(10000));
employeeService.saveEmployee(employee1);
}
@Test
public void testDeleteEmployee() {
employeeService.deleteEmployee("1");
}
@Test
public void testUpdateEmployee() {
Employee employee = new Employee("newName", 10, new BigDecimal(100000));
employeeService.updateEmployee(employee);
}
@Test
public void testGetEmployeeById() {
Employee employee = employeeService.getEmployeeById("1");
System.out.println(employee);
}
@Test
public void testListEmployees() {
List<Employee> employees = employeeService.listEmployees();
for (Employee employee : employees) {
System.out.println(employee);
}
}
}
基础后台搭建完成,开始写业务功能。
4、业务功能
使用 bootstrap 简单美化页面,在 JSP 的头部引入以下 CDN:
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
4.1、查询所有员工
Controller
EmployeeController
添加方法
- listEmployees:员工展示
@Controller
@RequestMapping("/employee")
public class EmployeeController {
/**
* Controller层调用Service层
*/
private final EmployeeService employeeService;
/**
* 通过构造器注入依赖
*/
public EmployeeController(EmployeeService employeeService) {
this.employeeService = employeeService;
}
/**
* 员工展示
* @return 员工展示页
*/
@RequestMapping("/listEmployees")
public String listEmployees(Model model) {
List<Employee> employeeList = employeeService.listEmployees();
model.addAttribute("employeeList", employeeList);
return "listEmployees";
}
}
页面
index.jsp
页面添加超链接,跳转到员工展示
页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/employee/listEmployees">查询所有员工</a>
</body>
</html>
listEmployees.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>员工展示</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>员工展示</small>
</h1>
</div>
<table class="table table-hover table-striped">
<thead>
<tr>
<th>员工编号</th>
<th>员工姓名</th>
<th>员工年龄</th>
<th>员工薪水</th>
</tr>
</thead>
<tbody>
<c:forEach items="${employeeList}" var="employee">
<tr>
<td>${employee.id}</td>
<td>${employee.name}</td>
<td>${employee.age}</td>
<td>${employee.salary}</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
4.2、添加员工
Controller
EmployeeController
添加两个方法
- toSaveEmployee:跳转页面;
- saveEmployee:添加员工;
- 处理方法使用实体类接收请求参数,要求前端表单提交的域名称和实体类属性名一致;
- 实体类需要有 setter 方法,Spring 根据域名称通过 setter 注入。
/**
* 跳转页面
*
* @return 添加员工页
*/
@RequestMapping("/toSaveEmployee")
public String toSaveEmployee() {
return "saveEmployee";
}
/**
* 添加员工
* @return 员工展示页
*/
@RequestMapping("/saveEmployee")
public String saveEmployees(Employee employee) {
System.out.println("接收到的:" + employee);
employeeService.saveEmployee(employee);
return "redirect:/employee/listEmployees";
}
页面
listEmployees.jsp
页面添加超链接,跳转到添加员工
页
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
...
<div class="row">
<div class="col-md-4 column">
<a href="${pageContext.request.contextPath}/employee/toSaveEmployee" class="btn btn-primary">添加员工</a>
</div>
</div>
...
</div>
</div>
</div>
saveEmployee.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>添加员工</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-10 column">
<div class="page-header">
<h1>
<small>添加员工</small>
</h1>
</div>
<div>
<form action="${pageContext.request.contextPath}/employee/saveEmployee" method="post">
<div class="form-group">
<label> 姓名:<input type="text" name="name" required> </label><br>
<label> 年龄:<input type="text" name="age" required> </label><br>
<label> 薪水:<input type="text" name="salary" required> </label><br>
<input type="submit">
<input type="reset">
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
4.3、更新、删除员工
Controller
EmployeeController
添加三个方法
- toUpdateEmployee:跳转页面,页面需要向后台传递 ID,用于展示待更新员工的信息;
- updateEmployee:更新书籍,页面需要向后台传递 ID,用于执行 SQL 语句;
- deleteEmployeek:删除书籍,,页面需要向后台传递 ID,用于执行 SQL 语句。
/**
* 跳转页面:需要获取待更新员工ID,封装到模型对象中
*
* @return 更新员工页
*/
@RequestMapping("/toUpdateEmployee")
public String toUpdateEmployee(String id, Model model) {
Employee employee = employeeService.getEmployeeById(id);
model.addAttribute("employee", employee);
return "updateEmployee";
}
/**
* 更新员工:需要获取待更新员工ID,用于执行SQL语句
*
* @return 员工展示页
*/
@RequestMapping("/updateEmployee")
public String updateEmployee(Employee employee) {
employeeService.updateEmployee(employee);
return "redirect:/employee/listEmployees";
}
/**
* 删除员工
*
* @return 员工展示页
*/
@RequestMapping("/deleteEmployee")
public String deleteEmployee(String id) {
employeeService.deleteEmployee(id);
return "redirect:/employee/listEmployees";
}
页面
listBooks.jsp
- 添加超链接,
更新
和删除
; - 需要向后台传递员工 ID,通过 URL 携带参数
<tbody>
<c:forEach items="${employeeList}" var="employee">
<tr>
...
<td>
<a href="${pageContext.request.contextPath}/employee/toUpdateEmployee?id=${employee.id}">更新</a>
<a href="${pageContext.request.contextPath}/employee/deleteEmployee?id=${employee.id}">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
updateEmployee.jsp
需要向后台传递员工 ID,通过隐藏域
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>添加员工</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-10 column">
<div class="page-header">
<h1>
<small>更新员工</small>
</h1>
</div>
<div>
<form action="${pageContext.request.contextPath}/employee/updateEmployee" method="post">
<%-- 要传ID,才能执行update的SQL语句 --%>
<input type="hidden" name="id" value="${employee.id}">
<div class="form-group">
<label> 姓名:<input type="text" name="name" placeholder="${employee.name}" required> </label><br>
<label> 年龄:<input type="text" name="age" placeholder="${employee.age}" required> </label><br>
<label> 薪水:<input type="text" name="salary" placeholder="${employee.salary}" required> </label><br>
<input type="submit">
<input type="reset">
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
4.4、搜索
添加一个模糊搜索功能。
DAO
EmployeeMapper
/**
* 查询员工:根据员工名模糊查询
* @param nameStr 员工名
* @return 模糊查询列表
*/
List<Employee> listEmployeesLike(String nameStr);
EmployeeMapper.xml
如果没有接收到 nameStr,SQL 语句为select * from employee
,会查询所有员工。
<select id="listEmployeesLike" resultType="employee">
select id, name, age, salary
from ssm_employee.employee
where name like concat('%', #{nameStr}, '%')
</select>
Service
EmployeeService
/**
* 查询员工:根据员工名模糊查询
*
* @param nameStr 员工名
* @return 模糊查询列表
*/
List<Employee> listEmployeesLike(String nameStr);
EmployeeServiceImpl
@Override
public List<Employee> listEmployeesLike(String nameStr) {
return employeeMapper.listEmployeesLike(nameStr);
}
Test
@Test
public void testListEmployeesLike() {
List<Employee> employees = employeeService.listEmployeesLike("j");
for (Employee employee : employees) {
System.out.println(employee);
}
}
Controller
添加一个方法:listEmployeesLike
- 页面需要向后台传递员工名字段;
- 返回员工展示页,封装的对象名 employeeList 要与 listEmployees() 方法中封装的对象同名,才能在页面中获取。
/**
* 查询员工:根据员工名模糊查询
*
* @return 员工展示页
*/
@RequestMapping("/listEmployeesLike")
public String listEmployeesLike(String nameStr, Model model) {
List<Employee> employeeList = employeeService.listEmployeesLike(nameStr);
model.addAttribute("employeeList", employeeList);
return "listEmployees";
}
页面
listEmployees.jsp
添加表单,作为搜索栏
<form action="${pageContext.request.contextPath}/employee/listEmployeesLike">
<input type="text" name="nameStr" placeholder="请输入员工名">
<input type="submit" class="btn btn-primary">
</form>
到此,一个简单的 SSM 项目完成。
5、注意事项
5.1、环境搭建
- 数据库
- 字符集:utf8
- 字符集校对:utf8_general_ci
- 引擎:InnoDB
- 导入依赖
- 如果没有自动下载,刷新 Maven;
- 需要检查项目结构的 Artifacts 中的 WEB-INF 中是否有生成 lib 目录,否则会导致 Tomcat 无法运行等问题;
- 基础代码
- 实体类
- ORM 原则
- Spring 注入
- 提供 getter,使用 EL 表达式才能获取到属性
- 实现序列化接口,才能使用二级缓存
- Service
- Service 层调用 DAO 层;
- 提供 Mapper 接口,用于 Spring 依赖注入。
- 实体类
5.2、配置文件
引入其他文件时,必须在文件名开头写classpath:
,否则会找不到文件。
- MyBatis
- 数据库配置文件,属性名必须有
jdbc.
前缀; - Mapper.xml
- 放在 resources 目录下,防止 Maven 资源过滤;
- select 语句需要有 resultType 或 resultMap 结果映射;
- 开启二级缓存;
- 数据库配置文件,属性名必须有
- Spring
- 整合 DAO 层:注意 Mapper 扫描配置器的使用;
- 整合 Service 层;
- 整合 Controller 层;
- 总配置文件:applicationContext.xml
- web.xml
- DispatcherServlet:绑定总配置文件,否则会导致 Bean 无法正常创建。
5.3、业务功能
自底向上开发:DAO - Service - Controller - 页面。
- Controller
- Controller 层调用 Service 层,提供 Service 接口,用于 Spring 依赖注入。
- @RequestMapping:映射请求路径;
- Model:封装模型对象,通常用于展示数据;
- 方法参数:由前端传递
- 基本数据类型:域名称与参数名一致,可以直接接收;如果不一致,使用 @PathVariable 注解;
- 引用数据类型:要求域名称与实体类的属性名一致才能接收到,并且实体类要有 setter。
- return:返回的视图名;
- 页面
- 在页面添加超链接或表单,用于发送请求;
- 页面发送请求到 Controller,如果处理方法需要参数,则页面需要发送请求参数;
- 超链接发送:URL 携带参数;
- 表单发送:隐藏域;