10.Spring Boot 实战~Spring Boot总结 ( 增,删,查,改,上传,分页 )
本文是上一篇文章的后续,详情点击该链接~
项目需求
增,删,查,改,上传,分页
项目准备
搭建项目结构
导入依赖
<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.alvingroupId>
<artifactId>test_frameworkartifactId>
<version>1.0-SNAPSHOTversion>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.3.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelper-spring-boot-starterartifactId>
<version>1.2.13version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<parameters>trueparameters>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<executions>
<execution>
<id>repackageid>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
plugins>
pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
application.yml配置文件
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_framework?serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
thymeleaf:
prefix: classpath:/myviews/
suffix: .html
mybatis:
mapper-locations: classpath:/mybatisxml/**/*.xml
数据库
create database test_framework;
use test_framework;
drop table if exists tb_customer;
create table tb_customer(
id integer not null auto_increment,
name varchar(32) comment '姓名',
gender varchar(8) comment '性别',
age int(3) comment '年龄',
img varchar(64) comment '头像文件路径及文件名',
orig_img varchar(64) comment '客户上传的头像文件原始命名',
primary key(id)
);
drop table if exists tb_phone;
create table tb_phone(
id integer not null auto_increment,
phone_no varchar(18) comment '联系方式',
customer_id integer comment '客户主键',
primary key (id)
);
INSERT INTO tb_customer VALUES (1, '李子明', '男', 20, '/imgs/1.jpg', '1.jpg');
INSERT INTO tb_customer VALUES (2, '赵天', '男', 24, '/imgs/2.jpg', '2.jpg');
INSERT INTO tb_customer VALUES (3, '王羽', '男', 18, '/imgs/3.jpg', '3.jpg');
INSERT INTO tb_customer VALUES (4, '赵珊', '女', 23, '/imgs/4.jpg', '4.jpg');
INSERT INTO tb_customer VALUES (5, '刘海信', '男', 66, '/imgs/7.jpg', '7.jpg');
INSERT INTO tb_customer VALUES (6, '陈天一', '女', 21, '/imgs/5.jpg', '5.jpg');
INSERT INTO tb_customer VALUES (8, '黄贵根', '男', 19, '/imgs/f4d1847c-16ea-413f-a3eb-fa7b2c2d1750.png', 'timg.png');
后台代码
CustomerController
package com.alvin.controller;
import com.alvin.pojo.Customer;
import com.alvin.pojo.Phone;
import com.alvin.service.CustomerService;
import com.alvin.service.PhoneService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.util.Map;
@Controller
public class CustomerController {
@Autowired
private CustomerService customerService;
@Autowired
private PhoneService phoneService;
@RequestMapping("/removeCustomer")
public String removeCustomer(Integer id){
boolean isRemoved = customerService.removeCustomer(id);
if(isRemoved){
return "redirect:/";
}
return "redirect:/toError";
}
@RequestMapping("/modifyCustomer")
public String modifyConsumer(Customer customer, MultipartFile uploadImg){
boolean isModified = customerService.modifyCustomer(customer, uploadImg);
if(isModified) {
return "redirect:/showCustomer?id=" + customer.getId();
}
return "redirect:/toError";
}
@RequestMapping("/toModifyCustomer")
public String toModifyCustomer(Integer id, Model model){
Customer customer = customerService.getCustomerById(id);
model.addAttribute("customer", customer);
return "modifyCustomer";
}
@RequestMapping("/addPhone")
public String addPhone(Phone phone){
boolean isAdded = phoneService.addPhone(phone);
if(isAdded) {
return "redirect:/showCustomer?id=" + phone.getCustomerId();
}
return "redirect:/toError";
}
@RequestMapping("/toAddPhone")
public String toAddPhone(Integer customerId, Model model){
model.addAttribute("customerId", customerId);
return "addPhone";
}
@RequestMapping("/showCustomer")
public String showCustomer(Integer id, Model model){
Customer customer = customerService.getCustomerById(id);
model.addAttribute("customer", customer);
return "showCustomer";
}
@PostMapping("/addCustomer")
public String addCustomer(Customer customer, MultipartFile uploadImg){
boolean isAdded = customerService.addCustomer(customer, uploadImg);
if(isAdded){
return "redirect:/";
}
return "redirect:/toError";
}
@RequestMapping("/toError")
public String toError(){
return "error";
}
@RequestMapping("/toAddCustomer")
public String toAddCustomer(){
return "addCustomer";
}
@RequestMapping(value = {"/", "/index", "/default", "/welcome"})
public String toIndex(Model model,
@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "rows", defaultValue = "5") int rows){
Map<String, Object> map = customerService.getCustomersByPage(page, rows);
model.addAllAttributes(map);
return "index";
}
}
CustomerMapper接口
package com.alvin.mapper;
import com.alvin.pojo.Customer;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CustomerMapper {
List<Customer> selectCustomers();
int selectCount();
int insert(Customer customer);
Customer selectById(Integer id);
int update(Customer customer);
int deleteCustomer(Integer id);
}
PhoneMapper
package com.alvin.mapper;
import com.alvin.pojo.Phone;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PhoneMapper {
int insert(Phone phone);
int deleteByCustomer(Integer id);
}
Customer
package com.alvin.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer implements Serializable {
private Integer id;
private String name;
private String gender;
private int age;
private String img;
private String origImg;
private List<Phone> phoneList;
}
Phone
package com.alvin.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Phone implements Serializable {
private Integer id;
private String phoneNo;
private String customerId;
}
CustomerServiceImpl
package com.alvin.service.impl;
import com.alvin.mapper.CustomerMapper;
import com.alvin.mapper.PhoneMapper;
import com.alvin.pojo.Customer;
import com.alvin.service.CustomerService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.*;
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerMapper customerMapper;
@Autowired
private PhoneMapper phoneMapper;
@Override
@Transactional
public boolean removeCustomer(Integer id) {
phoneMapper.deleteByCustomer(id);
int rows = customerMapper.deleteCustomer(id);
if(rows != 1){
throw new RuntimeException("删除客户失败");
}
return true;
}
@Override
@Transactional
public boolean modifyCustomer(Customer customer, MultipartFile uploadImg) {
String prefix = System.getProperty("user.dir") + File.separator + "src/main/resources/static/imgs/";
try {
int length = uploadImg.getInputStream().available();
System.out.println("文件长度是:" + length + " 字节");
if(length != 0){
String origName = uploadImg.getOriginalFilename();
Customer old = customerMapper.selectById(customer.getId());
String img = prefix + old.getImg();
File oldImg = new File(img);
oldImg.delete();
String tmpImg = UUID.randomUUID().toString() + origName.substring(origName.lastIndexOf("."));;
String newImg = prefix + tmpImg;
File newImgFile = new File(newImg);
uploadImg.transferTo(newImgFile);
customer.setImg("/imgs/"+tmpImg);
customer.setOrigImg(origName);
}
int rows = customerMapper.update(customer);
if(rows != 1){
throw new RuntimeException("修改客户数据失败");
}
}catch (IOException e){
e.printStackTrace();
}
return true;
}
@Override
public Customer getCustomerById(Integer id) {
return customerMapper.selectById(id);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = {RuntimeException.class})
public boolean addCustomer(Customer customer, MultipartFile uploadImg) {
try {
String origImg = uploadImg.getOriginalFilename();
String tmpName = UUID.randomUUID().toString() + origImg.substring(origImg.lastIndexOf("."));
Properties properties = System.getProperties();
for(Map.Entry entry : properties.entrySet()){
System.out.println(entry.getKey() + " --- " + entry.getValue());
}
System.out.println("====================================");
Map<String, String> env = System.getenv();
for(Map.Entry<String, String> entry: env.entrySet()){
System.out.println(entry.getKey() + " - " + entry.getValue());
}
String dir = System.getProperty("user.dir") + File.separator + "src/main/resources/static/imgs/";
File file = new File(dir, tmpName);
System.out.println(file.getAbsolutePath());
uploadImg.transferTo(file);
customer.setImg("/imgs/"+tmpName);
customer.setOrigImg(origImg);
int rows = customerMapper.insert(customer);
if(rows != 1){
throw new RuntimeException("新增客户失败");
}
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return true;
}
@Override
public Map<String, Object> getCustomersByPage(int page, int rows) {
Map<String, Object> resultMap = new HashMap<>();
PageHelper.startPage(page, rows);
List<Customer> customerList = customerMapper.selectCustomers();
resultMap.put("customerList", customerList);
resultMap.put("currentPage", page);
int totalRows = customerMapper.selectCount();
int totalPages = totalRows % rows == 0 ? totalRows/rows : (totalRows/rows + 1);
resultMap.put("totalPages", totalPages);
return resultMap;
}
}
PhoneServiceImpl
package com.alvin.service.impl;
import com.alvin.mapper.PhoneMapper;
import com.alvin.pojo.Phone;
import com.alvin.service.PhoneService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class PhoneServiceImpl implements PhoneService {
@Autowired
private PhoneMapper phoneMapper;
@Override
@Transactional(rollbackFor = {RuntimeException.class})
public boolean addPhone(Phone phone) {
int rows = phoneMapper.insert(phone);
if(rows != 1){
throw new RuntimeException("新增联系方式失败");
}
return true;
}
}
CustomerService接口
package com.alvin.service;
import java.util.Map;
import com.alvin.pojo.Customer;
import org.springframework.web.multipart.MultipartFile;
public interface CustomerService {
Map<String, Object> getCustomersByPage(int page, int rows);
boolean addCustomer(Customer customer, MultipartFile uploadImg);
Customer getCustomerById(Integer id);
boolean modifyCustomer(Customer customer, MultipartFile uploadImg);
boolean removeCustomer(Integer id);
}
PhoneService接口
package com.alvin.service;
import com.alvin.pojo.Phone;
public interface PhoneService {
boolean addPhone(Phone phone);
}
MyApplication启动类
package com.alvin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = {"com.alvin.mapper"})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Mybatis映射
CustomerMapper.xml
<mapper namespace="com.alvin.mapper.CustomerMapper">
<resultMap id="customerMap" type="com.alvin.pojo.Customer">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="gender" property="gender"/>
<result column="age" property="age"/>
<result column="img" property="img"/>
<result column="orig_img" property="origImg"/>
resultMap>
<resultMap id="customerPhoneListMap" type="com.alvin.pojo.Customer">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="gender" property="gender"/>
<result column="age" property="age"/>
<result column="img" property="img"/>
<result column="orig_img" property="origImg"/>
<collection property="phoneList" javaType="java.util.List"
ofType="com.alvin.pojo.Phone">
<id column="p_id" property="id"/>
<result column="phone_no" property="phoneNo"/>
<result column="customer_id" property="customerId"/>
collection>
resultMap>
<delete id="deleteCustomer">
delete from tb_customer
<where>
id = #{id}
where>
delete>
<update id="update">
update tb_customer
<set>
<trim suffixOverrides=",">
<if test="name != null">
name = #{name},
if>
<if test="age != 0">
age = #{age},
if>
<if test="gender != null">
gender = #{gender},
if>
<if test="img != null">
img = #{img},
if>
<if test="origImg != null">
orig_img = #{origImg},
if>
trim>
set>
<where>
id = #{id}
where>
update>
<select id="selectById" resultMap="customerPhoneListMap">
select
c.id, c.name, c.gender, c.age, c.img, c.orig_img,
p.id as p_id, p.phone_no, p.customer_id
from
tb_customer c
left join
tb_phone p
on c.id = p.customer_id
<where>
and c.id = #{id}
where>
select>
<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into tb_customer(id, name, gender, age, img, orig_img)
values(default, #{name}, #{gender}, #{age}, #{img}, #{origImg})
insert>
<select id="selectCustomers" resultMap="customerMap">
select id, name, gender, age, img, orig_img from tb_customer
select>
<select id="selectCount" resultType="_int">
select count(id) from tb_customer
select>
mapper>
PhoneMapper.xml
<mapper namespace="com.alvin.mapper.PhoneMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
insert into tb_phone(id, phone_no, customer_id)
values(default, #{phoneNo}, #{customerId})
insert>
<delete id="deleteByCustomer">
delete from tb_phone
<where>
customer_id = #{id}
where>
delete>
mapper>
前台
addCustomer.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>客户联系方式管理系统title>
head>
<body>
<div style="width: 800px; margin: auto">
<form action="/addCustomer" method="post" enctype="multipart/form-data">
<div style="width: 500px; margin: auto; text-align: left">
<label style="width: 200px; padding-right: 5px; text-align: right">姓名:label>
<input type="text" name="name">
div>
<div style="width: 500px; margin: auto; text-align: left">
<label style="width: 200px; padding-right: 5px; text-align: right">性别:label>
<input type="radio" name="gender" value="男"> 男
<input type="radio" name="gender" value="女"> 女
div>
<div style="width: 500px; margin: auto; text-align: left">
<label style="width: 200px; padding-right: 5px; text-align: right">年龄:label>
<input type="text" name="age">
div>
<div style="width: 500px; margin: auto; text-align: left">
<label style="width: 200px; padding-right: 5px; text-align: right">头像:label>
<input type="file" name="uploadImg">
div>
<div style="width: 600px; text-align: center; margin: auto">
<input type="submit" value="提交">
<input type="reset" value="重置">
div>
form>
div>
body>
html>
addPhone.html
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>客户联系方式管理系统title>
head>
<body>
<div style="width: 800px; margin: auto; text-align: center">
<form action="/addPhone" method="post">
<input type="hidden" name="customerId" th:value="${customerId}">
<div style="width: 400px; margin: auto; text-align: center">
<label>电话:label>
<input type="text" name="phoneNo">
div>
<div style="width: 800px; margin: auto; text-align: center">
<input type="submit" value="提交">
div>
form>
div>
body>
html>
error.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>客户联系方式管理系统title>
head>
<body style="text-align: center; margin: auto">
<h3>服务器忙,请稍后重试!<a href="/">返回首页a>h3>
body>
html>
index.html
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>客户联系方式管理系统title>
head>
<body style="text-align: center">
<h3>客户联系方式管理系统h3>
<div style="width:800px; margin: auto; text-align: right; padding-right: 20px">
<a th:href="@{/toAddCustomer}">新增客户a>
div>
<table style="text-align: center; margin: auto; width: 800px" border="1" cellspacing="0" cellpadding="0">
<caption>客户列表caption>
<thead>
<tr>
<th>序号th>
<th>姓名th>
<th>性别th>
<th>年龄th>
<th>头像th>
<th>头像文件名th>
<th>操作th>
tr>
thead>
<tbody>
<tr th:each="customer: ${customerList}">
<th th:text="${customer.id}">th>
<th th:text="${customer.name}">th>
<th th:text="${customer.gender}">th>
<th th:text="${customer.age}">th>
<th>
<img th:src="@{${customer.img}}" style="height:40px"/>
th>
<th th:text="${customer.origImg}">th>
<th>
<a th:href="@{/showCustomer(id=${customer.id})}">查看a>
<a th:href="@{/removeCustomer(id=${customer.id})}">删除a>
th>
tr>
<tr>
<th colspan="7">
<a th:if="${currentPage != 1}" th:href="@{/index(page=${currentPage-1})}">上一页a>
<a th:if="${currentPage != totalPages}" th:href="@{/index(page=${currentPage+1})}">下一页a>
th>
tr>
tbody>
table>
body>
html>
modifyCustomer.html
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div style="width:800px; margin: auto; text-align: center">
<form action="/modifyCustomer" method="post" enctype="multipart/form-data">
<input type="hidden" name="id" th:value="${customer.id}">
<table cellspacing="0" cellpadding="0" border="1" style="width:100%">
<tr>
<td>姓名td>
<td><input type="text" name="name" th:value="${customer.name}">td>
tr>
<tr>
<td>性别td>
<td>
<div th:if="${customer.gender == '男'}">
<input type="radio" value="男" name="gender" checked>男
<input type="radio" value="女" name="gender">女
div>
<div th:if="${customer.gender == '女'}">
<input type="radio" value="男" name="gender">男
<input type="radio" value="女" name="gender" checked>女
div>
td>
tr>
<tr>
<td>年龄td>
<td><input type="text" name="age" th:value="${customer.age}">td>
tr>
<tr>
<td>头像td>
<td>
<img th:src="@{${customer.img}}" style="height: 50px">
<br>
<input type="file" name="uploadImg">
td>
tr>
<tr>
<td colspan="2">
<input type="submit" value="修改">
<a th:href="@{/showCustomer(id=${customer.id})}">返回a>
td>
tr>
table>
form>
div>
body>
html>
showCustomer.html
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>客户联系方式管理系统title>
head>
<body>
<div style="width: 800px; margin: auto; text-align: right">
<a th:href="@{/toModifyCustomer(id=${customer.id})}">修改客户a>
<a th:href="@{/toAddPhone(customerId=${customer.id})}">新增联系方式a>
<a th:href="@{/}">返回首页a>
div>
<div style="width: 800px; margin: auto; text-align: center">
<table cellpadding="0" cellspacing="0" border="1" style="width:100%">
<caption>客户详情caption>
<tr>
<td style="width:20%">客户信息td>
<td>
<table cellpadding="0" cellspacing="0" border="1" style="width:100%">
<tr>
<td>姓名td>
<td th:text="${customer.name}">td>
tr>
<tr>
<td>性别td>
<td th:text="${customer.gender}">td>
tr>
<tr>
<td>年龄td>
<td th:text="${customer.age}">td>
tr>
<tr>
<td>头像td>
<td>
<img style="height: 50px" th:src="@{${customer.img}}">
td>
tr>
table>
td>
tr>
<tr>
<td style="width:20%">联系方式td>
<td>
<table cellpadding="0" cellspacing="0" border="1" style="width:100%">
<tr th:if="${customer.phoneList.size() > 0}" th:each="phone:${customer.phoneList}">
<td>电话td>
<td th:text="${phone.phoneNo}">td>
<td>修改和删除td>
tr>
table>
td>
tr>
table>
div>
body>
html>