环境
springboot2.4.3 + freemarker2.3.31 + bootstrap3 + druid1.2.6+ mysql8 + mybatis2.1.4
需求
使用springboot完成员工的crud
操作步骤
步骤1:创建项目:springboot-crud
步骤2:创建数据库,创建表
CREATE TABLE `employee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`admin` bit(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
导入数据:
INSERT INTO `employee` VALUES ('1', 'admin', '1', 'admin@126.com', '19', '');
INSERT INTO `employee` VALUES ('2', '刘备', '1', 'lb@126.com', '43', '\0');
INSERT INTO `employee` VALUES ('3', '诸葛亮', '1', 'zgl@126.com', '28', '\0');
INSERT INTO `employee` VALUES ('4', '马谡', '1', 'ms@126.com', '21', '\0');
INSERT INTO `employee` VALUES ('5', '关羽', '1', 'gy@126.com', '43', '\0');
INSERT INTO `employee` VALUES ('6', '张飞', '1', 'zf@126.om', '39', '\0');
INSERT INTO `employee` VALUES ('7', '赵云', '1', 'zy@126.com', '43', '\0');
INSERT INTO `employee` VALUES ('8', '马超', '1', 'mc@126.com', '33', '\0');
INSERT INTO `employee` VALUES ('9', '黄忠', '1', 'hz@126.com', '60', '\0');
步骤3:导入相关依赖
依赖分别有:springboot环境,web环境, mysql ,druid, mybatis, freemarker, pagehelper等
<!--springboot-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
<dependencies>
<!--web环境-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql相关-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<!--mybatis相关-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!--freemarker相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!--分页相关-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--mybatis逆袭工程相关-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>false</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
步骤4:在/项目/resources/application.properties配置相关环境
环境有:druid数据源, freemarker,pageHelper
#数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/crud?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=admin
#mybatis日志
logging.level.com.langfeiyes.crud.mapper=trace
#freemarker
#一般我们会做3个配置,其余默认即可
#暴露session对象的属性
spring.freemarker.expose-session-attributes=true
#配置为传统模式,空值自动处理
spring.freemarker.settings.classic_compatible=true
#重新指定模板文件后缀 springboot 2.2.x 后 默认后缀为 .ftlh
spring.freemarker.suffix=.ftl
#pagehelper
#合理化分页
pagehelper.reasonable=true
步骤4:在/项目/resourcess/static 文件中导入静态配置文件与模板
步骤5:编写案例代码
最终代码结构:
实体类:Employee
package com.langfeiyes.crud.domain;
public class Employee {
private Long id;
private String name;
private String password;
private String email;
private Integer age;
private boolean admin;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
}
持久层mapper映射类:EmployeeMapper
package com.langfeiyes.crud.mapper;
import com.github.pagehelper.PageInfo;
import com.langfeiyes.crud.domain.Employee;
import com.langfeiyes.crud.query.EmployeeQuery;
import java.util.List;
public interface EmployeeMapper {
int deleteByPrimaryKey(Long id);
int insert(Employee record);
Employee selectByPrimaryKey(Long id);
List<Employee> selectAll();
int updateByPrimaryKey(Employee record);
//分页查询
List<Employee> selectForList(EmployeeQuery qo);
}
条件查询封装类:QueryObject EmployeeQuery
package com.langfeiyes.crud.query;
//封装页面传入的分页数据
public class QueryObject {
private int currentPage = 1; //当前页
private int pageSize = 5; //每页显示条数
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
package com.langfeiyes.crud.query;
import org.springframework.util.StringUtils;
//用户相关查询参数封装类
public class EmployeeQuery extends QueryObject {
private String keyword; //关键字查询
public String getKeyword(){
return StringUtils.hasText(keyword)?keyword:null;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
}
服务层接口与实现类: IEmployeeService EmployeeServiceImpl
package com.langfeiyes.crud.service;
import com.github.pagehelper.PageInfo;
import com.langfeiyes.crud.domain.Employee;
import com.langfeiyes.crud.query.EmployeeQuery;
import java.util.List;
/**
* 用户服务层接口
*/
public interface IEmployeeService {
/**
* 添加
* @param entity
*/
void save(Employee entity);
/**
* 更新
* @param entity
*/
void update(Employee entity);
/**
* 删除
* @param id
*/
void delete(Long id);
/**
* 查单个
* @param id
* @return
*/
Employee get(Long id);
/**
* 查多个
* @return
*/
List<Employee> list();
/**
* 分页
* @param qo
* @return
*/
PageInfo<Employee> query(EmployeeQuery qo);
}
package com.langfeiyes.crud.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.langfeiyes.crud.domain.Employee;
import com.langfeiyes.crud.mapper.EmployeeMapper;
import com.langfeiyes.crud.query.EmployeeQuery;
import com.langfeiyes.crud.service.IEmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmployeeServiceImpl implements IEmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
public void save(Employee entity) {
employeeMapper.insert(entity);
}
@Override
public void update(Employee entity) {
employeeMapper.updateByPrimaryKey(entity);
}
@Override
public void delete(Long id) {
employeeMapper.deleteByPrimaryKey(id);
}
@Override
public Employee get(Long id) {
return employeeMapper.selectByPrimaryKey(id);
}
@Override
public List<Employee> list() {
return employeeMapper.selectAll();
}
@Override
public PageInfo<Employee> query(EmployeeQuery qo) {
PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
return new PageInfo<Employee>(employeeMapper.selectForList(qo));
}
}
表现层处理请求的类:EmployeeController
package com.langfeiyes.crud.web.controller;
import com.langfeiyes.crud.domain.Employee;
import com.langfeiyes.crud.query.EmployeeQuery;
import com.langfeiyes.crud.service.IEmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("employee")
public class EmployeeController {
@Autowired
private IEmployeeService employeeService;
@RequestMapping("list")
public String list(Model model, @ModelAttribute("qo") EmployeeQuery qo) {
model.addAttribute("pageInfo", employeeService.query(qo));
return "employee/list";
}
@RequestMapping("input")
public String input(Long id, Model model) throws Exception{
if(id != null){
model.addAttribute("entity", employeeService.get(id));
}
return "employee/input";
}
@RequestMapping("saveOrUpdate")
public String saveOrUpdate(Employee entity) throws Exception{
if(entity.getId() != null){
employeeService.update(entity);
}else{
employeeService.save(entity);
}
return "redirect:/employee/list";
}
@RequestMapping("delete")
public String input(Long id) throws Exception{
if(id != null){
employeeService.delete(id);
}
return "redirect:/employee/list";
}
}
sql映射配置文件:EmployeeMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.langfeiyes.crud.mapper.EmployeeMapper">
<resultMap id="BaseResultMap" type="com.langfeiyes.crud.domain.Employee">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="password" property="password" />
<result column="email" property="email" />
<result column="age" property="age" />
<result column="admin" property="admin" />
</resultMap>
<delete id="deleteByPrimaryKey">
delete from employee
where id = #{id}
</delete>
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
insert into employee (name, password, email, age, admin)
values (#{name}, #{password}, #{email}, #{age}, #{admin})
</insert>
<update id="updateByPrimaryKey">
update employee
set name = #{name},
email = #{email},
age = #{age},
admin = #{admin}
where id = #{id}
</update>
<select id="selectByPrimaryKey" resultMap="BaseResultMap">
select id, name, password, email, age, admin from employee e
where id = #{id}
</select>
<select id="selectAll" resultMap="BaseResultMap">
select id, name, password, email, age, admin from employee
</select>
<!--where 条件-->
<sql id="base_where">
<where>
<if test="keyword != null">
and (name like concat("%",#{keyword} ,"%") or email like concat("%",#{keyword} ,"%"))
</if>
</where>
</sql>
<!--查数据-->
<select id="selectForList" resultMap="BaseResultMap">
select id, name, password, email, age, admin from employee
<include refid="base_where"/>
</select>
</mapper>
springboot项目启动类:App
package com.langfeiyes.crud;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = "com.langfeiyes.crud.mapper")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
核心页面模板:input.ftl list.ftl
input.ftl
<html lang="en">
<head>
<meta charset="UTF-8">
<title>员工添加/编辑</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<#include "/common/header.ftl">
</head>
<body>
<div class="container " style="margin-top: 20px">
<div class="row">
<div class="col-sm-3">
<!--菜单回显-->
<#assign currentMenu="employee"/>
<#include "/common/menu.ftl">
</div>
<div class="col-sm-9">
<div class="row">
<div class="col-sm-12">
<h1 class="page-head-line">员工编辑</h1>
</div>
</div>
<div class="row" align="left">
<form class="form-horizontal" action="/employee/saveOrUpdate" method="post">
<input type="hidden" name="id" value="${entity.id}">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">名称:</label>
<div class="col-sm-5">
<input type="text" class="form-control" id="name" name="name" placeholder="请输入名称" value="${entity.name}">
</div>
</div>
<#if !entity??>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">密码:</label>
<div class="col-sm-5">
<input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" >
</div>
</div>
<div class="form-group">
<label for="repassword" class="col-sm-2 control-label">确认密码:</label>
<div class="col-sm-5">
<input type="password" class="form-control" id="repassword" name="repassword" placeholder="请再输入一次密码" >
</div>
</div>
</#if>
<div class="form-group">
<label for="email" class="col-sm-2 control-label">邮箱:</label>
<div class="col-sm-5">
<input type="text" class="form-control" id="email" name="email" placeholder="请输入邮箱" value="${entity.email}">
</div>
</div>
<div class="form-group">
<label for="age" class="col-sm-2 control-label">年龄:</label>
<div class="col-sm-5">
<input type="text" class="form-control" id="age" name="age" placeholder="请输入员工年龄" value="${entity.age}">
</div>
</div>
<div class="form-group">
<label for="admin" class="col-sm-2 control-label">是否超管:</label>
<div class="col-sm-5">
<input type="checkbox" id="admin" name="admin" ${(entity?? && entity.admin)?string('checked', '')} class="checkbox" >
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">保存</button>
<a href="/employee/list" class="btn btn-default">取消</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
list.ftl
<html lang="en">
<head>
<meta charset="UTF-8">
<title>员工管理案例</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<#include "/common/header.ftl">
<style>
.page-head-line {
font-size: 30px;
text-transform: uppercase;
color: #337ab7;
font-weight: 800;
padding-bottom: 20px;
border-bottom: 2px solid #00a7ff;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container " style="margin-top: 20px">
<div class="row">
<div class="col-sm-3">
<!--菜单回显-->
<#assign currentMenu="employee"/>
<#include "/common/menu.ftl">
</div>
<div class="col-sm-9">
<div class="row">
<div class="col-sm-12">
<h1 class="page-head-line">员工管理</h1>
</div>
</div>
<!--高级查询--->
<form class="form-inline" id="searchForm" action="/employee/list" method="post">
<input type="hidden" name="currentPage" id="currentPage" value="${qo.currentPage}">
<input type="hidden" name="pageSize" id="pageSize" value="${qo.pageSize}">
<div class="form-group">
<label for="keyword">关键字:</label>
<input type="text" class="form-control" id="keyword" name="keyword"
placeholder="请输入姓名/邮箱" value="${qo.keyword}">
</div>
<button type="submit" id="query" class="btn btn-default"><span class="glyphicon glyphicon-search"></span>查询</button>
<a class="btn btn-success" href="/employee/input">
<span class="glyphicon glyphicon-plus"></span>添加
</a>
</form>
<table class="table table-striped table-hover" >
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>email</th>
<th>年龄</th>
<th>操作</th>
</tr>
</thead>
<#list pageInfo.list as e>
<tr>
<td>${e_index+1}</td>
<td>${e.name}</td>
<td>${e.email}</td>
<td>${e.age}</td>
<td>
<a class="btn btn-info btn-xs" href="/employee/input?id=${e.id}">
<span class="glyphicon glyphicon-pencil"></span>编辑
</a>
<a href="/employee/delete?id=${e.id}" class="btn btn-danger btn-xs" >
<span class="glyphicon glyphicon-trash"></span>删除
</a>
</td>
</tr>
</#list>
</table>
<#include "/common/page.ftl">
</div>
</div>
</div>
</body>
</html>
最后测试效果:
列表:
添加:
编辑:
到这,springboot综合案例就完成了。
源码:传送门