typora-copy-images-to: img
day05 预约管理-预约设置
学习目标
- 了解什么是Apache POI
- 掌握Apache POI的使用方法
- 掌握批量导入预约设置信息的实现过程
- 掌握日历方式展示预约设置信息的实现过程
- 掌握基于日历实现预约设置信息的实现
第一章-预约设置分析和Apache POI
知识点-预约设置需求
1.目标
- 掌握预约设置的需求
2.路径
- 预约设置需求分析
- 对应的表结构和实体类
3.讲解
3.1预约设置需求分析
前面我们已经完成了检查项管理、检查组管理、套餐管理等。接下来我们需要进行预约设置,其实==就是设置每一天的体检预约最大数量。==客户可以通过微信端在线预约,在线预约时需要选择体检的时间,如果客户选择的时间已经预约满则无法进行预约。
3.2对应的表结构和实体类
- 表结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O3Dvxar0-1577015359050)(img/1560819134767.png)]
- 实体类
public class OrderSetting implements Serializable{
private Integer id ;
private Date orderDate;//预约设置日期
private int number;//可预约人数
private int reservations ;//已预约人数
}
4.小结
- 预约设置说白了就是设置当天最大的预约人数.(考虑放假情况)
知识点-Apache POI
1.目标
- 了解什么是Apache POI
- 掌握Apache POI的使用方法
2.路径
- POI介绍
- POI入门案例
- POI工具类的介绍
3.讲解
3.1 POI介绍
Apache POI是用Java编写的免费开源的跨平台的Java工具,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能,其中使用最多的就是使用POI操作Excel文件。
还有另外一个工具包jxl,专门操作Excel
- 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>
- 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格式档案的功能
3.2 入门案例
3.2.1 从Excel文件读取数据
- 需求:使用POI可以从一个已经存在的Excel文件中读取数据
- 步骤
- 创建工作簿对象
- 获得工作表对象
- 遍历工作表对象 获得行对象
- 遍历行对象 获得列对象
- 获得内容
- 关闭
- 实现
public void fun01() throws Exception {
//1 创建工作簿对象
XSSFWorkbook workbook = new XSSFWorkbook("G:/hello.xlsx");
//2 获得工作表对象
XSSFSheet sheet = workbook.getSheetAt(0);
//3 遍历工作表 获得行对象
for (Row row : sheet) {
//4 遍历行对象 获得列对象
for (Cell cell : row) {
//5 获得列里面的内容
System.out.println(cell.getStringCellValue());
}
System.out.println("------------");
}
//6.关闭
workbook.close();
}
-
小结:
通过上面的入门案例可以看到,POI操作Excel表格封装了几个核心对象:
XSSFWorkbook:工作簿
XSSFSheet:工作表
Row:行
Cell:单元格上面案例是通过遍历工作表获得行,遍历行获得单元格,最终获取单元格中的值。
还有一种方式就是获取工作表最后一个行号,从而根据行号获得行对象,通过行获取最后一个单元格索引,从而根据单元格索引获取每行的一个单元格对象,代码如下:
//1.创建工作簿对象
XSSFWorkbook workbook = new XSSFWorkbook("G:/hello.xlsx");
//2.获得工作表对象
XSSFSheet sheet = workbook.getSheetAt(0);
//3.获得最后一行的行号
int lastRowNum = sheet.getLastRowNum();
//4.遍历行
for(int i =0;i<=lastRowNum;i++){
XSSFRow row = sheet.getRow(i);
//5.获得最后一列的列号
short lastCellNum = row.getLastCellNum();
//6.遍历列
for(int j = 0;j<lastCellNum;j++){
//7.取出数据
XSSFCell cell = row.getCell(j);
System.out.println(cell.getStringCellValue());
}
}
//8.关闭
workbook.close();
3.2.2 向Excel文件写入数据
- 需求: 使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘
- 步骤
//1.创建工作簿对象
//2.创建工作表对象
//3.创建行对象
//4.创建列对象, 设置内容
//5.通过流写到文件(磁盘)
//6.关闭
- 实现
//使用POI可以在内存中创建一个Excel文件并将数据写入到这个文件,最后通过输出流将内存中的Excel文件下载到磁盘
public void fun03() throws Exception {
//1 创建工作簿对象
XSSFWorkbook workbook = new XSSFWorkbook();
//2 创建工作表对象
XSSFSheet xssfSheet = workbook.createSheet("学生名单");
//3 创建行
XSSFRow row01 = xssfSheet.createRow(0);
//4 创建列,设置内容
row01.createCell(0).setCellValue("姓名");
row01.createCell(1).setCellValue("性别");
row01.createCell(2).setCellValue("地址");
XSSFRow row02 = xssfSheet.createRow(1);
row02.createCell(0).setCellValue("张三");
row02.createCell(1).setCellValue("男");
row02.createCell(2).setCellValue("深圳");
XSSFRow row03 = xssfSheet.createRow(2);
row03.createCell(0).setCellValue("李四");
row03.createCell(1).setCellValue("男");
row03.createCell(2).setCellValue("北京");
//5.通过输出流对象写到磁盘
FileOutputStream os = new FileOutputStream("G:/student.xlsx");
workbook.write(os);
os.flush();
os.close();
workbook.close();
}
- 小结
- 创建工作簿的时候, 不需要传入参数(excel不存在的)
- 使用输出流
3.3POI工具类的介绍
拷贝02_工具类/POIUtils.java到health_common
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZiTMbomz-1577015359052)(img/1558095960493.png)]
4.小结
-
POI就是一个工具, 用来操作Office, 我们主要用来操作Excel
-
使用工具类 读取ordersetting_template.xlsx, 每一行读取成了一个String[], 多行就是多个String[],再用List
数组的第一个值是日期, 第二个值就是最大预约数量
第二章-预约设置业务实现
案例-批量导入预约设置信息
1.需求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xNbSthyI-1577015359053)(img/1559180928491.png)]
2.分析
2.1业务分析
预约设置信息对应的数据表为t_ordersetting,预约设置操作对应的页面为ordersetting.html
t_ordersetting表结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-okqXKKbV-1577015359054)(img/2.png)]
orderDate:预约日期
number:可预约人数
reservations:已预约人数
批量导入预约设置信息操作过程:
1、点击模板下载按钮下载Excel模板文件
2、将预约设置信息录入到模板文件中
3、点击上传文件按钮将录入完信息的模板文件上传到服务器
4、通过POI读取上传文件的数据并保存到数据库
2.2实现步骤分析
- 点击上传文件, 把编写好的Excel上传到OrderSettingController
- 创建OrderSettingController, 创建upload()方法
//1.使用工具类解析上传文件 获得List<String[]> list
//2.把List<String[]> 封装成List<OrderSetting>
//3.调用业务, 进行增加
//4.响应
- 创建OrderSettingService OrderSettingServiceImpl
//1.遍历List<OrderSetting>
//2.调用Dao,判断当前日期是否设置过
//2.1有设置过, 调用Dao 更新
//2.2 没有设置过,调用Dao 增加
- 创建OrderSettingDao 创建三个方法
3.代码实现
3.1 前端实现
3.1.1 提供模板文件
资料中已经提供了Excel模板文件ordersetting_template.xlsx,将文件放在health_web工程的template目录下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ssunFiYS-1577015359055)(img/4.png)]
3.1.2 实现模板文件下载
为模板下载按钮绑定事件实现模板文件下载
<el-button style="margin-bottom: 20px;margin-right: 20px" type="primary"
@click="downloadTemplate()">模板下载</el-button>
//模板文件下载
downloadTemplate(){
window.location.href="../../template/ordersetting_template.xlsx";
}
3.1.3 文件上传
使用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>
handleSuccess(response, file) {
if(response.flag){
this.$message({
message: response.message,
type: 'success'
});
}else{
this.$message.error(response.message);
}
}
beforeUpload(file){
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
将资料中的POIUtils工具类复制到health_common工程
在health_web工程创建OrderSettingController并提供upload方法
package com.itheima.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.constant.MessageConstant;
import com.itheima.entity.Result;
import com.itheima.pojo.OrderSetting;
import com.itheima.service.OrderSettingService;
import com.itheima.utils.POIUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
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;
import java.util.Map;
/**
* 预约设置
*/
@RestController
@RequestMapping("/ordersetting")
public class OrderSettingController {
@Reference
private OrderSettingService orderSettingService;
/**
* Excel文件上传,并解析文件内容保存到数据库
* @param excelFile
* @return
*/
@RequestMapping("/upload")
public Result upload(@RequestParam("excelFile")MultipartFile excelFile){
try {
//读取Excel文件数据
List<String[]> list = POIUtils.readExcel(excelFile);
if(list != null && list.size() > 0){
List<OrderSetting> orderSettingList = new ArrayList<>();
for (String[] strings : list) {
OrderSetting orderSetting =
new OrderSetting(new Date(strings[0]), Integer.parseInt(strings[1]));
orderSettingList.add(orderSetting);
}
orderSettingService.add(orderSettingList);
}
} catch (IOException e) {
e.printStackTrace();
return new Result(false, MessageConstant.IMPORT_ORDERSETTING_FAIL);
}
return new Result(true,MessageConstant.IMPORT_ORDERSETTING_SUCCESS);
}
}
3.2.2 服务接口
创建OrderSettingService服务接口并提供新增方法
package com.itheima.service;
import com.itheima.pojo.OrderSetting;
import java.util.List;
import java.util.Map;
public interface OrderSettingService {
public void add(List<OrderSetting> list);
}
3.2.3 服务实现类
创建服务实现类OrderSettingServiceImpl并实现新增方法
package com.itheima.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.dao.OrderSettingDao;
import com.itheima.pojo.OrderSetting;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
/**
* 预约设置服务
*/
@Service(interfaceClass = OrderSettingService.class)
@Transactional
public class OrderSettingServiceImpl implements OrderSettingService {
@Autowired
private OrderSettingDao orderSettingDao;
//批量添加
public void add(List<OrderSetting> list) {
if(list != null && list.size() > 0){
for (OrderSetting orderSetting : list) {
//检查此数据(日期)是否存在
long count = orderSettingDao.findCountByOrderDate(orderSetting.getOrderDate());
if(count > 0){
//已经存在,执行更新操作
orderSettingDao.editNumberByOrderDate(orderSetting);
}else{
//不存在,执行添加操作
orderSettingDao.add(orderSetting);
}
}
}
}
}
3.2.4 Dao接口
创建Dao接口OrderSettingDao并提供更新和新增方法
package com.itheima.dao;
import com.itheima.pojo.OrderSetting;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public interface OrderSettingDao {
public void add(OrderSetting orderSetting);
public void editNumberByOrderDate(OrderSetting orderSetting);
public long findCountByOrderDate(Date orderDate);
}
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.itheima.dao.OrderSettingDao" >
<!--新增-->
<insert id="add" parameterType="com.itheima.pojo.OrderSetting">
insert into t_ordersetting
(orderDate,number,reservations)
values
(#{orderDate},#{number},#{reservations})
</insert>
<!--根据日期更新预约人数-->
<update id="editNumberByOrderDate" parameterType="com.itheima.pojo.OrderSetting">
update t_ordersetting set number = #{number} where orderDate = #{orderDate}
</update>
<!--根据预约日期查询-->
<select id="findCountByOrderDate" parameterType="java.util.Date" resultType="long">
select count(*) from t_ordersetting where orderDate = #{orderDate}
</select>
</mapper>
4.小结
- 导入的时候, 先需要根据orderDate进行查询 判断是否设置过
- 如果没有设置过 直接增加
- 如果有设置过 根据orderDate更新number(人数)
案例-使用日历展示预约设置信息
1.需求
前面已经完成了预约设置功能,现在就需要通过日历的方式展示出来每天设置的预约人数。
在页面中已经完成了日历的动态展示,我们只需要查询当前月份的预约设置信息并展示到日历中即可,同时在日历中还需要展示已经预约的人数,效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pBhsRnCS-1577015359056)(img/1.png)]
2.分析
- 在initData()里面
//1.请求服务器(携带当前月2019-08), 获得当前月的预约设置
this.leftobj = [
{date: 1, number: 120, reservations: 1},
{date: 3, number: 120, reservations: 1},
{date: 4, number: 120, reservations: 120},
{date: 6, number: 120, reservations: 1},
{date: 8, number: 120, reservations: 1}
];
- 在OrderSettingController里面创建getOrderSettingByMonth()
//1.绑定请求参数(2019-08)
//2.调用业务 获得当前月的预约设置 List<OrderSetting> list
//3.响应
- 在OrderSettingService里面创建getOrderSettingByMonth(String date)
public List<OrderSetting> getOrderSettingByMonth(String date){//2019-08
//1.拼接日期 封装到Map 2019-08-01 2019-08-31
//2.调用Dao, 根据日期查询
}
- 在OrderSettingDao里面区间查询
SELECT * FROM t_ordersetting WHERE orderDate BETWEEN '2019-08-01' AND '2019-08-31'
3.实现
3.1 前端实现
3.1.1 使用静态数据调试
为了能够快速看到效果,我们可以先使用静态数据模拟,然后再改为发送ajax请求查询数据库。
实现步骤:
(1)预约设置数据对应的模型数据为leftobj,在initData方法最后为leftobj模型数据赋值:
this.leftobj = [
{ date: 1, number: 120, reservations: 1 },
{ date: 3, number: 120, reservations: 1 },
{ date: 4, number: 120, reservations: 120 },
{ date: 6, number: 120, reservations: 1 },
{ date: 8, number: 120, reservations: 1 }
];
其中date表示日期,number表示可预约人数,reservations表示已预约人数
(2)使用VUE的v-for标签遍历上面的leftobj模型数据,展示到日历上:
<template>
<template v-for="obj in leftobj">
<template v-if="obj.date == dayobject.day.getDate()">
<template v-if="obj.number > obj.reservations">
<div class="usual">
<p>可预约{{obj.number}}人</p>
<p>已预约{{obj.reservations}}人</p>
</div>
</template>
<template v-else>
<div class="fulled">
<p>可预约{{obj.number}}人</p>
<p>已预约{{obj.reservations}}人</p>
<p>已满</p>
</div>
</template>
</template>
</template>
<button v-if="dayobject.day > today"
@click="handleOrderSet(dayobject.day)" class="orderbtn">设置</button>
</template>
4.1.2 发送ajax获取动态数据
将上面的静态模拟数据去掉,改为发送ajax请求,根据当前页面对应的月份查询数据库获取预约设置信息,将查询结果赋值给leftobj模型数据
//发送ajax请求,根据当前页面对应的月份查询预约设置信息
axios.post(
"/ordersetting/getOrderSettingByMonth.do?date="+this.currentYear+'-'+this.currentMonth
).then((response)=>{
if(response.data.flag){
//为模型数据赋值,通过双向绑定展示到日历中
this.leftobj = response.data.data;
}else{
this.$message.error(response.data.message);
}
});
3.2 后台代码
3.2.1 Controller
在OrderSettingController中提供getOrderSettingByMonth方法,根据月份查询预约设置信息
/**
* 根据日期查询预约设置数据(获取指定日期所在月份的预约设置数据)
* @param date
* @return
*/
@RequestMapping("/getOrderSettingByMonth")
public Result getOrderSettingByMonth(String date){//参数格式为:2019-03
try{
List<Map> list = orderSettingService.getOrderSettingByMonth(date);
//获取预约设置数据成功
return new Result(true,MessageConstant.GET_ORDERSETTING_SUCCESS,list);
}catch (Exception e){
e.printStackTrace();
//获取预约设置数据失败
return new Result(false,MessageConstant.GET_ORDERSETTING_FAIL);
}
}
3.2.2 服务接口
在OrderSettingService服务接口中扩展方法getOrderSettingByMonth
public List<Map> getOrderSettingByMonth(String date);//参数格式为:2019-03
3.2.3 服务实现类
在OrderSettingServiceImpl服务实现类中实现方法getOrderSettingByMonth
//根据日期查询预约设置数据
public List<Map> getOrderSettingByMonth(String date) {//2019-3
String dateBegin = date + "-1";//2019-3-1
String dateEnd = date + "-31";//2019-3-31
Map map = new HashMap();
map.put("dateBegin",dateBegin);
map.put("dateEnd",dateEnd);
List<OrderSetting> list = orderSettingDao.getOrderSettingByMonth(map);
List<Map> data = new ArrayList<>();
for (OrderSetting orderSetting : list) {
Map orderSettingMap = new HashMap();
orderSettingMap.put("date",orderSetting.getOrderDate().getDate());//获得日期(几号)
orderSettingMap.put("number",orderSetting.getNumber());//可预约人数
orderSettingMap.put("reservations",orderSetting.getReservations());//已预约人数
data.add(orderSettingMap);
}
return data;
}
3.2.4 Dao接口
在OrderSettingDao接口中扩展方法getOrderSettingByMonth
public List<OrderSetting> getOrderSettingByMonth(Map date);
3.2.5 Mapper映射文件
在OrderSettingDao.xml文件中扩展SQL
<!--根据月份查询预约设置信息-->
<select id="getOrderSettingByMonth"
parameterType="hashmap"
resultType="com.itheima.pojo.OrderSetting">
select * from t_ordersetting where orderDate between #{dateBegin} and #{dateEnd}
</select>
4.小结
- 查询当前月份的预约设置(前端传递当前的年-月: 2019-06)
SELECT * FROM t_ordersetting WHERE orderDate BETWEEN '2019-08-01' AND '2019-08-31'
或者
SELECT * FROM t_ordersetting WHERE orderDate LIKE '2019-08-%'
- 页面需要的数据
[
{date: 1, number: 120, reservations: 1},
{date: 3, number: 120, reservations: 1},
{date: 4, number: 120, reservations: 120},
{date: 6, number: 120, reservations: 1},
{date: 8, number: 120, reservations: 1}
]
案例-基于日历实现预约设置
1.需求
本章节要完成的功能为通过点击日历中的设置按钮来设置对应日期的可预约人数。效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRJ9VbIF-1577015359057)(img/5.png)]
2.分析
-
点击设置, 弹出dialog
-
在dialog的输入框里填写预约的人数, 点击了确定 请求服务器(人数, 当前的日期(2019-08-18))
-
在后台
- 判断当前日期是否设置过
- 没有设置过, 新增
- 设置过, 根据日期进行更新
- 判断当前日期是否设置过
3.实现
3.1 前端实现
3.1.1 为设置按钮绑定事件
为日历中的设置按钮绑定单击事件,当前日期作为参数
<button v-if="dayobject.day > today"
@click="handleOrderSet(dayobject.day)" class="orderbtn">设置</button>
//预约设置
handleOrderSet(day){
alert(day);
}
3.1.2 弹出预约设置窗口并发送ajax请求
完善handleOrderSet方法,弹出预约设置窗口,用户点击确定按钮则发送ajax请求
//预约设置
handleOrderSet(day){
this.$prompt('请输入可预约人数', '预约设置', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[0-9]*[1-9][0-9]*$/,
inputErrorMessage: '只能输入正整数'
}).then(({ value }) => {
//发送ajax请求根据日期修改可预约人数
axios.post("/ordersetting/editNumberByDate.do",{
orderDate:this.formatDate(day.getFullYear(),day.getMonth()+1,day.getDate()), //日期
number:value //可预约人数
}).then((response)=>{
if(response.data.flag){
this.initData(this.formatDate(day.getFullYear(), day.getMonth() + 1, 1));
this.$message({
type: 'success',
message: response.data.message
});
}else{
this.$message.error(response.data.message);
}
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消'
});
});
}
3.2 后台代码
3.2.1 Controller
在OrderSettingController中提供方法editNumberByDate
/**
* 根据指定日期修改可预约人数
* @param orderSetting
* @return
*/
@RequestMapping("/editNumberByDate")
public Result editNumberByDate(@RequestBody OrderSetting orderSetting){
try{
orderSettingService.editNumberByDate(orderSetting);
//预约设置成功
return new Result(true,MessageConstant.ORDERSETTING_SUCCESS);
}catch (Exception e){
e.printStackTrace();
//预约设置失败
return new Result(false,MessageConstant.ORDERSETTING_FAIL);
}
}
3.2.2 服务接口
在OrderSettingService服务接口中提供方法editNumberByDate
public void editNumberByDate(OrderSetting orderSetting);
3.2.3 服务实现类
在OrderSettingServiceImpl服务实现类中实现editNumberByDate
//根据日期修改可预约人数
public void editNumberByDate(OrderSetting orderSetting) {
long count = orderSettingDao.findCountByOrderDate(orderSetting.getOrderDate());
if(count > 0){
//当前日期已经进行了预约设置,需要进行修改操作
orderSettingDao.editNumberByOrderDate(orderSetting);
}else{
//当前日期没有进行预约设置,进行添加操作
orderSettingDao.add(orderSetting);
}
}
3.2.4 Dao接口
在OrderSettingDao接口中提供方法
public void editNumberByOrderDate(OrderSetting orderSetting);
public long findCountByOrderDate(Date orderDate);
3.2.5 Mapper映射文件
在OrderSettingDao.xml映射文件中提供SQL
<!--根据日期更新可预约人数-->
<update id="editNumberByOrderDate" parameterType="com.itheima.pojo.OrderSetting">
update t_ordersetting set number = #{number} where orderDate = #{orderDate}
</update>
<!--根据预约日期查询-->
<select id="findCountByOrderDate" parameterType="java.util.Date" resultType="long">
select count(*) from t_ordersetting where orderDate = #{orderDate}
</select>
4.小结
- 点击了确定请求服务器, 携带(当前的日期, 人数) 我们使用了对象封装
{orderDate: date, number: value}
- 在后台里面使用 OrderSetting绑定, 自动把字符串转成了Date类型, 因为配置文件里面配置了, 不需要写类型转换器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GkAOfkML-1577015359058)(img/1566188367316.png)]
- 先判断当前的日期是否设置过
- 没有设置过, 进行新增
- 有设置过, 就更新
-------常用光工具类
package com.itheima.utils;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
public class POIUtils {
private final static String xls = "xls";
private final static String xlsx = "xlsx";
private final static String DATE_FORMAT = "yyyy/MM/dd";
/**
* 读入excel文件,解析后返回
* @param file
* @throws IOException
*/
public static List<String[]> readExcel(MultipartFile file) throws IOException {
//检查文件
checkFile(file);
//获得Workbook工作薄对象
Workbook workbook = getWorkBook(file);
//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
List<String[]> list = new ArrayList<String[]>();
if(workbook != null){
for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){
//获得当前sheet工作表
Sheet sheet = workbook.getSheetAt(sheetNum);
if(sheet == null){
continue;
}
//获得当前sheet的开始行
int firstRowNum = sheet.getFirstRowNum();
//获得当前sheet的结束行
int lastRowNum = sheet.getLastRowNum();
//循环除了第一行的所有行
for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){
//获得当前行
Row row = sheet.getRow(rowNum);
if(row == null){
continue;
}
//获得当前行的开始列
int firstCellNum = row.getFirstCellNum();
//获得当前行的列数
int lastCellNum = row.getPhysicalNumberOfCells();
String[] cells = new String[row.getPhysicalNumberOfCells()];
//循环当前行
for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){
Cell cell = row.getCell(cellNum);
cells[cellNum] = getCellValue(cell);
}
list.add(cells);
}
}
workbook.close();
}
return list;
}
//校验文件是否合法
public static void checkFile(MultipartFile file) throws IOException{
//判断文件是否存在
if(null == file){
throw new FileNotFoundException("文件不存在!");
}
//获得文件名
String fileName = file.getOriginalFilename();
//判断文件是否是excel文件
if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){
throw new IOException(fileName + "不是excel文件");
}
}
public static Workbook getWorkBook(MultipartFile file) {
//获得文件名
String fileName = file.getOriginalFilename();
//创建Workbook工作薄对象,表示整个excel
Workbook workbook = null;
try {
//获取excel文件的io流
InputStream is = file.getInputStream();
//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
if(fileName.endsWith(xls)){
//2003
workbook = new HSSFWorkbook(is);
}else if(fileName.endsWith(xlsx)){
//2007
workbook = new XSSFWorkbook(is);
}
} catch (IOException e) {
e.printStackTrace();
}
return workbook;
}
public static String getCellValue(Cell cell){
String cellValue = "";
if(cell == null){
return cellValue;
}
//如果当前单元格内容为日期类型,需要特殊处理
String dataFormatString = cell.getCellStyle().getDataFormatString();
if(dataFormatString.equals("m/d/yy")){
cellValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue());
return cellValue;
}
//把数字当成String来读,避免出现1读成1.0的情况
if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
cell.setCellType(Cell.CELL_TYPE_STRING);
}
//判断数据的类型
switch (cell.getCellType()){
case Cell.CELL_TYPE_NUMERIC: //数字
cellValue = String.valueOf(cell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING: //字符串
cellValue = String.valueOf(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN: //Boolean
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA: //公式
cellValue = String.valueOf(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK: //空值
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR: //故障
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
}