文章目录
美年旅游_预约管理_预约设置
1.预约设置需求分析
前面我们已经完成了自由行管理、跟团游管理、套餐管理等。接下来我们需要进行预约设置,其实就是设置每一天的旅游预约最大数量。客户可以通过微信端在线预约,在线预约时需要选择旅游的时间,使得选择旅游时间的已预约人数加1,如果客户选择的时间已经预约满则无法进行预约。
2.t_ordersetting表结构:
orderDate:预约日期
number:最多可预约人数
reservations:已预约人数
导入mysql数据
DROP TABLE IF EXISTS `t_ordersetting`;
CREATE TABLE `t_ordersetting` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`orderDate` date DEFAULT NULL COMMENT '约预日期',
`number` int(11) DEFAULT NULL COMMENT '可预约人数',
`reservations` int(11) DEFAULT NULL COMMENT '已预约人数',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8;
第二章. Apache POI
2.1. POI介绍
2.1.1 简介
开发中经常会涉及到excel的处理,如导出Excel,导入Excel到数据库中,操作Excel目前有两个框架,一个是apache 的poi, 另一个是 Java Excel
Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office(Excel、WORD、PowerPoint、Visio等)格式档案读和写的功能。
官方主页: http://poi.apache.org/index.html
API文档: http://poi.apache.org/apidocs/index.html
maven坐标:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
2.1.2 Apache POI常用的类
POI结构:
HSSF - 提供读写Microsoft Excel XLS格式档案的功能
XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能(我们使用)
HWPF - 提供读写Microsoft Word DOC格式档案的功能
HSLF - 提供读写Microsoft PowerPoint格式档案的功能
HDGF - 提供读Microsoft Visio格式档案的功能
HPBF - 提供读Microsoft Publisher格式档案的功能
HSMF - 提供读Microsoft Outlook格式档案的功能
我们使用:XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能
2.2. 入门案例
2.2.1. 从Excel文件读取数据
【需求】
使用POI可以从一个已经存在的Excel文件中读取数据
【路径】
1:创建工作簿对象
2:获得工作表对象
3:遍历工作表对象 获得行对象
4:遍历行对象 获得单元格(列)对象
5:获得数据
6:关闭
【讲解】
- 实现
使用POI可以从一个已经存在的Excel文件中读取数据
在meinian_common中建立测试类,TestPoi.java
package com.atguigu;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
// 读取excel
public class TestPoi {
@Test
public void readExcel() throws IOException {
//创建工作簿
XSSFWorkbook workbook = new XSSFWorkbook("D:\\hello.xlsx");
//获取工作表,既可以根据工作表的顺序获取,也可以根据工作表的名称获取
XSSFSheet sheet = workbook.getSheetAt(0);
//遍历工作表获得行对象
for (Row row : sheet) {
//遍历行对象获取单元格对象
for (Cell cell : row) {
//获得单元格中的值
String value = cell.getStringCellValue(); //注意:数字类型,需要修改excel单元格的类型,否则报错。
System.out.println(value);// new String(value.getBytes("UTF-8"),"GBK"));
}
}
workbook.close();
}
【小结】
通过上面的入门案例可以看到,POI操作Excel表格封装了几个核心对象:
XSSFWorkbook:工作簿
XSSFSheet:工作表
XSSFRow:行
XSSFCell:单元格
上面案例是通过遍历工作表获得行,遍历行获得单元格,最终获取单元格中的值。
错误
解决方案
还有一种方式就是获取工作表最后一个行号,从而根据行号获得行对象,通过行获取最后一个单元格索引,从而根据单元格索引获取每行的一个单元格对象,代码如下:
public class TestPoi {
// 导出excel,获取最后一行
@Test
public void exportExcel_lastRow() throws IOException {
//创建工作簿
XSSFWorkbook workbook = new XSSFWorkbook("D:\\hello.xlsx");
//获取工作表,既可以根据工作表的顺序获取,也可以根据工作表的名称获取
XSSFSheet sheet = workbook.getSheetAt(0);
//获取当前工作表最后一行的行号,行号从0开始
int lastRowNum = sheet.getLastRowNum();
for(int i=0;i<=lastRowNum;i++){
//根据行号获取行对象
XSSFRow row = sheet.getRow(i);
// 再获取单元格对象
short lastCellNum = row.getLastCellNum();
for(short j=0;j<lastCellNum;j++){
// 获取单元格对象的值
String value = row.getCell(j).getStringCellValue();
System.out.println(value);
}
}
workbook.close();
}
2.2.2. 向Excel文件写入数据
【需求】
使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘
【路径】
1.创建工作簿对象
2.创建工作表对象
3.创建行对象
4.创建列(单元格)对象, 设置内容
5.通过输出流将workbook对象下载到磁盘
【实现】
使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘
// 导入excel
@Test
public void importExcel() throws IOException {
//在内存中创建一个Excel文件
XSSFWorkbook workbook = new XSSFWorkbook();
//创建工作表,指定工作表名称
XSSFSheet sheet = workbook.createSheet("尚硅谷");
//创建行,0表示第一行
XSSFRow row = sheet.createRow(0);
//创建单元格,0表示第一个单元格
row.createCell(0).setCellValue("编号");
row.createCell(1).setCellValue("姓名");
row.createCell(2).setCellValue("年龄");
XSSFRow row1 = sheet.createRow(1);
row1.createCell(0).setCellValue("1");
row1.createCell(1).setCellValue("小明");
row1.createCell(2).setCellValue("10");
XSSFRow row2 = sheet.createRow(2);
row2.createCell(0).setCellValue("2");
row2.createCell(1).setCellValue("小王");
row2.createCell(2).setCellValue("20");
//通过输出流将workbook对象下载到磁盘
FileOutputStream out = new FileOutputStream("D:\\atguigu.xlsx");
workbook.write(out);
out.flush();//刷新
out.close();//关闭
workbook.close();
}
小结:POI技术
• 创建工作簿的时候, 不需要传入参数(excel不存在的)
• 使用输出流,输出excel
应用场景:
1:从excel中读取数据,写入到数据库(导入);
2:从数据库查询数据,写入到excel文件(导出)
2.2.3.POI工具类的介绍
将资料中的POIUtils工具类复制到 meinian_common 工程
1.POI介绍
POI就是一个工具类库, 用来操作Office, 我们主要用来操作Excel
2.POI入门案例
(1)从Excel文件读取数据
(2)向Excel文件写入数据
3.POI工具类的介绍
使用工具类, 读取Excel, 每一行读取到了String[] 里面, 多行就是多个String[] , 最终封装到List
第三章. 批量导入预约设置信息
1:前台代码
(1)提供模板文件
(2)实现模板文件下载
(3)文件上传
2:后台代码
业务:
• 从excel中读取预约设置信息,批量导入到数据库
(1)OrderSettingController.java(Controller)
(2)OrderSettingService.java(服务接口)
(3)OrderSettingServiceImpl.java(服务实现类)
(4)OrderSettingDao.java(Dao接口)
(5)OrderSettingDao.xml(Mapper映射文件)
【讲解】
【需求】
从Excel读取预约设置的数据,批量导入到数据库
【设计】
预约设置信息对应的数据表为t_ordersetting,预约设置操作对应的页面为ordersetting.html
1:t_ordersetting表结构:
rderDate:预约日期
number:可预约人数
reservations:已预约人数
【路径】
批量导入预约设置信息操作过程:
第一步、点击模板下载按钮下载Excel模板文件【文件下载】
第二步、将预约设置信息录入到模板文件中
第三步、点击上传文件按钮将录入完信息的模板文件上传到服务器【文件上传】
第四步、通过POI读取上传文件的数据并保存到数据库【poi导入】
2:将 ordersetting.html 放置到 meinian_web\src\main\webapp\pages 中
3.1. 前台代码
3.1.1. 提供模板文件
资料中已经提供了Excel模板文件ordersetting_template.xlsx,将文件放在meinian_web工程的template目录下
3.1.2. 实现模板文件下载
(1)为模板下载按钮绑定事件实现模板文件下载
<el-button style="margin-bottom: 20px;margin-right: 20px" type="primary" @click="downloadTemplate()">模板下载</el-button>
(2)downloadTemplate()
//下载模板文件
downloadTemplate(){
window.location.href="../../template/ordersetting_template.xlsx";
},
3.1.3. 文件上传
(1)使用ElementUI的上传组件实现文件上传并绑定相关事件
<el-upload action="/ordersetting/upload.do"
name="excelFile"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="beforeUpload">
<el-button type="primary">上传文件</el-button>
</el-upload>
(2)handleSuccess方法:用于显示上传成功或者失败信息。
//上传成功提示
handleSuccess(response, file) {
if(response.flag){
this.$message({
message: response.message,
type: 'success'
});
}else{
this.$message.error(response.message);
}
},
(3)beforeUpload方法:用于校验上传的文件是否是excel文件
//上传之前进行文件格式校验
beforeUpload(file){
//alert("文件名:" + file.name);
//alert("文件类型:" + file.type);
var f_index = file.name.lastIndexOf(".");
if(f_index != -1){
var f_type = file.name.substring(f_index+1, file.name.length).toLowerCase();
if(f_type == 'xls' || f_type == 'xlsx'){
return true;
}
}
const isXLS = file.type === 'application/vnd.ms-excel';
if(isXLS){
return true;
}
const isXLSX = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
if (isXLSX) {
return true;
}
this.$message.error('上传文件只能是xls或者xlsx格式!');
return false;
},
3.2. 后台代码
3.2.1. Controller
【路径】
1.点击上传文件, 把编写好的Excel上传到OrderSettingController
2.创建OrderSettingController, 创建upload()方法
//1.使用POI解析文件 得到List<String[]> list
//2.把List<String[]> list转成 List<OrderSetting> list
//3.调用业务 进行保存
3.创建OrderSettingService
//1.遍历List<OrderSetting> list
//2.判断当前的日期之前是否设置过
// 2.1 设置过, 更新数量
// 2.2 没有设置过, 保存
4.创建OrderSettingDao
//根据日期查询
//根据日期更新number
//保存OrderSetting
在 meinian_web 工程创建 OrderSettingController 并提供upload方法
package com.atguigu.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.atguigu.constant.MessageConstant;
import com.atguigu.entity.Result;
import com.atguigu.pojo.OrderSetting;
import com.atguigu.service.OrdersettingService;
import com.atguigu.utils.POIUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@RestController
@RequestMapping("/ordersetting")
public class OrdersettingController {
@Reference
private OrdersettingService ordersettingService;
@RequestMapping("/upload")
public Result upload(MultipartFile excelFile){
try {
// 使用poi工具类解析excel文件,读取里面的内容
List<String[]> lists = POIUtils.readExcel(excelFile);
// 把List<String[]> 数据转换成 List<OrderSetting>数据
List<OrderSetting> orderSettings = new ArrayList<>();
// 迭代里面的每一行数据,进行封装到集合里面
for (String[] str : lists) {
// 获取到一行里面,每个表格数据,进行封装
OrderSetting orderSetting = new OrderSetting(new Date(str[0]),Integer.parseInt(str[1]));
orderSettings.add(orderSetting);
}
/*
for (String[] arrStrings : lists) {
//获取第一个字符串类型的日期
String dateStr = arrStrings[0];
//获取第一个字符串类型的人数
String numberStr = arrStrings[1];
//new一个 orderSetting对象
OrderSetting orderSetting = new OrderSetting();
//为这个对象set数据
orderSetting.setOrderDate(new Date(dateStr));
orderSetting.setNumber(Integer.parseInt(numberStr));
//往List集合例添加数据
orderSettings.add(orderSetting);
}
*/
// 调用业务进行保存
ordersettingService.add(orderSettings);
return new Result(true, MessageConstant.IMPORT_ORDERSETTING_SUCCESS);
} catch (Exception e) {
e.printStackTrace();
return new Result(true, MessageConstant.IMPORT_ORDERSETTING_FAIL);
}
}
}
3.2.2. 服务接口
创建OrderSettingService服务接口并提供新增方法
package com.atguigu.service;
import com.atguigu.pojo.OrderSetting;
import java.util.List;
public interface OrdersettingService {
void add(List<OrderSetting> orderSettings);
}
3.2.3. 服务实现类
创建服务实现类OrderSettingServiceImpl并实现新增方法
package com.atguigu.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.atguigu.dao.OrdersettingDao;
import com.atguigu.pojo.OrderSetting;
import com.atguigu.service.OrdersettingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service(interfaceClass = OrdersettingService.class)
@Transactional
public class OrdersettingServiceImpl implements OrdersettingService {
@Autowired
private OrdersettingDao ordersettingDao;
@Override
public void add(List<OrderSetting> orderSettings) {
// 1:遍历List<OrderSetting>
for (OrderSetting orderSetting : orderSettings) {
// 判断当前的日期之前是否已经被设置过预约日期,使用当前时间作为条件查询数量
long count = ordersettingDao.findCountByOrderDate(orderSetting.getOrderDate());
// 如果设置过预约日期,更新number数量
if (count>0){
ordersettingDao.editNumberByOrderDate(orderSetting);
}else {
// 如果没有设置过预约日期,执行保存
ordersettingDao.add(orderSetting);
}
}
}
}
3.2.4. Dao接口
创建Dao接口OrderSettingDao并提供更新和新增方法
package com.atguigu.dao;
import com.atguigu.pojo.OrderSetting;
import java.util.Date;
public interface OrdersettingDao {
void add(OrderSetting orderSetting);
long findCountByOrderDate(Date orderDate);
void editNumberByOrderDate(OrderSetting orderSetting);
}
3.2.5. Mapper映射文件
创建Mapper映射文件OrderSettingDao.xml并提供相关SQL
<?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.atguigu.dao.OrdersettingDao">
<!--根据预约日期查询-->
<select id="findCountByOrderDate" parameterType="java.util.Date" resultType="long">
select count(*) from t_ordersetting where orderDate = #{orderDate}
</select>
<!--新增-->
<insert id="add" parameterType="ordersetting">
insert into t_ordersetting(orderDate,number) values (#{orderDate},#{number})
</insert>
<!--根据日期更新预约人数-->
<update id="editNumberByOrderDate" parameterType="orderSetting">
update t_ordersetting set number = #{number} where orderDate = #{orderDate}
</update>
</mapper>
查看t_ordersetting表
【小结】
1:前台代码
(1)提供模板文件
(2)实现模板文件下载
(3)文件上传
2:后台代码
• 从excel中读取预约设置信息,批量导入到数据库
(1)OrderSettingController.java(Controller)
(2)OrderSettingService.java(服务接口)
(3)OrderSettingServiceImpl.java(服务实现类)
(4)OrderSettingDao.java(Dao接口)
(5)OrderSettingDao.xml(Mapper映射文件)