一.回顾
购销合同
1.什么是购销合同
2.分析出表结构的关系
3.设计表的三范式及反三范式
4.添加冗余字段,使得查询速度更快
5.分散计算原理
购销合同总金额的计算
6.实现购销合同的相关CRUD操作
7.实现货物的CRUD操作
8.实现附件的CRUD操作
二.细粒度权限控制
就是在粗粒度权限控制的基础上,加入对于不同用户显示的数据也不一样的控制。实 质就是数据的控制。
1.数据库表的准备
public class BaseEntity implements Serializable {
protected String createBy; //创建者的 id
protected String createDept;//创建者所在部门的id
protected Date createTime;//创建时间
protected String updateBy;//更新者的id
protected Date updateTime;//更新时间
补充Contract Action.insert()中的方法
public String insert() throws Exception {
//1.加入细粒度权限控制的数据
User user = super.getCurUser();
model.setCreateBy(user.getId());//设置创建者的id
model.setCreateDept(user.getDept().getId());//设置创建者所在部门的id
//1.调用业务方法,实现保存
contractService.saveOrUpdate(model);
//跳页面
return "alist";
}
准备用户
OOP员工 都属于船运部
AOP员工 都属于船运部
SOA部门经理 都属于船运部
给用户授予角色
OOP 船运专员
AOP 船运专员
SOA 船运经理
给角色分配模块
配置[船运专员]角色的模块
船运经理
准备三条记录
从jUserCreate.jsp页面中,可以得出用户主要通过等级来决定可以看到什么数据
修改 Contract Action.list()方法
public String list() throws Exception {
String hql = "from Contract where 1=1 ";
//如何确定出用户的等级
User user = super.getCurUser();
int degree = user.getUserinfo().getDegree();
if(degree==4){
//说明是员工
hql+=" and createBy='"+user.getId()+"'";
}else if(degree==3){
//说明是部门经理,管理本部门
hql+=" and createDept='"+user.getDept().getId()+"'";
}else if(degree==2){
//说明是管理本部门及下属部门?????
}else if(degree==1){
//说明是副总?????
}else if(degree==0){
//说明是总经理
}
contractService.findPage(hql, page, Contract.class, null);
//设置分页的url地址
page.setUrl("contractAction_list");
//将page对象压入栈顶
super.push(page);
return "list";
}
三.存在一个添加购销合同下货物时的bug
<td>
${o.contractProducts.size() }
/
<c:set var="extNo" value="0"></c:set>
<c:forEach items="${o.contractProducts }" var="cp" >
<c:if test="${cp.extCproducts.size()!=0 }">
<c:set var="extNo" value="${extNo+cp.extCproducts.size() }"></c:set>
</c:if>
</c:forEach>
${extNo }
</td>
对于购销合同的货物数/附件数加载存在的问题?
存在的问题是:当加载一条购销合同记录时,会通过关联级别的数据加载,来加载购 销合同下的货物列表,同时还要加载货物列表下的附件列表,所以造成加载速度变慢 的问题。
解决思路:
在购销合同的表中加入两个冗余字段,将来在添加购销合同下的货物时就同时更新购 销合同表中的货物数量,在添加附件时,就更新购销合同表中的附件数量。
又产生了新的问题?
因为冗余字段的添加,导致程序员的开发和维护工作量添加。目的是保证数据的一致 性。
作业:希望改造上面的问题,使用的是分散计算思想,在Contract.c表中添加两个冗 余字段
【面试:】 当系统开发完成后,项目刚上线一切正常,但随着数据量的增加,系统运行半年后, 后期加载数据页面速度很慢,用户无法接受,请问你有什么好的优化方案。
五.POI报表
1.POI介绍
Apache 专门操作 excel api
2.主流操作excel api Jxl Poi
1)Jxl 只能操作 excel 2003
2)Poi 可以操作整个 office (excel、doc(vb 宏)、ppt、visio);包括所有的 excel 版本
六.应用场景
应用于将数据写入excel ,用户可以共享数据。作为备份数据(不包括大字段)、还原 数据。
1.导入POI的相关jar包
不包括 commons-codec-1.5.jar
Maven项目:
Pom.xml文件中的xml酉己置:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.11</version>
</dependency>
2.需求:需要8步
a) 创建一个工作簿workbook
b) 创建一个工作表sheet
c) 创建一个行对象row (下标起始值为0)
d) 创建一个单元格对象cell (下标起始值为0)
e) 给单元格设置内容
f) 设置单元格的样式,设置字体和字体的大小
g) 保存,关闭流对象
h) 下载
3 .实现代码
Workbook -HSSFWorkbook/XSSFWorkbook/SXSSFWorkbook
//1.创建工作簿
//Workbook wb = new HSSFWorkbook();//只支持excel2003版本 扩展名xls
//Workbook wb = new XSSFWorkbook(); //支持excel2007+版本 扩展名xlsx
Workbook wb = new SXSSFWorkbook(); //支持excel2007+版本 扩展名xlsx 不支持模板操作,可以将产生的一部分对象从内存中转移到磁盘。
//默认转移对象的个数为100,如果new SXSSFWorkbook(500)代表内存中对象个数达到500就转移到磁盘
public class POITest {
@Test
public void testPoi() throws Exception{
//1.创建工作簿
Workbook wb = new HSSFWorkbook();
//2.创建工作表
Sheet sheet = wb.createSheet();
//3.创建行对象
Row row = sheet.createRow(4);//参数为下标
//4.创建单元格
Cell cell = row.createCell(3);//下标
//5.设置单元格内容
cell.setCellValue("传智.宋江");
//6.设置单元格样式
CellStyle cellStyle = wb.createCellStyle();//创建了样式对象
Font font = wb.createFont();//创建字体对象
font.setFontHeightInPoints((short)48);//设置字体大小
font.setFontName("方正舒体");//设置字体名字
font.setColor(Font.COLOR_RED);
cellStyle.setFont(font);//设置样式对象,使用某种字体
cell.setCellStyle(cellStyle);
//7.保存,关闭流
OutputStream os = new FileOutputStream("D:/abc.xls");
wb.write(os);
//os.write(wb.toString().getBytes());
os.close();
//8.下载
}
}
七.出货表的打印
1.是按船期进行统计的。
2.数据来源哪些表?
通过分析得出:来自于购销合同表,货物表
3.思考怎么查?
Hql语句
//=======================================数据输出=================================================
String hql= "from ContractProduct where to_char(contract.shipTime,'yyyy-MM') ='"+inputDate+"'";
List<ContractProduct> list = contractProductService.find(hql, ContractProduct.class, null);//查询出符合指定船期的货物列表
4 .出货表页面的进入
只要在该页面提供一个日历选择框就可以选择船期了 ,再使用poi实现数据打印
OutProductAction.print()
/**
* 打印出货表
* @return
* @throws Exception
*
* printNotTemplate
*/
public String print() throws Exception {
//通用变量
int rowNo=0,cellNo=1;
Row nRow =null;
Cell nCell = null;
//1.创建工作簿
//Workbook wb = new HSSFWorkbook();//只支持excel2003版本 扩展名xls
//Workbook wb = new XSSFWorkbook(); //支持excel2007+版本 扩展名xlsx
Workbook wb = new SXSSFWorkbook(); //支持excel2007+版本 扩展名xlsx 不支持模板操作,可以将产生的一部分对象从内存中转移到磁盘。
//默认转移对象的个数为100,如果new SXSSFWorkbook(500)代表内存中对象个数达到500就转移到磁盘
//2.创建工作表
Sheet sheet = wb.createSheet();
//设置列宽 本身是个bug会出现一些偏差
sheet.setColumnWidth(cellNo++, 26*256);
sheet.setColumnWidth(cellNo++, 11*256);
sheet.setColumnWidth(cellNo++, 29*256);
sheet.setColumnWidth(cellNo++, 12*256);
sheet.setColumnWidth(cellNo++, 15*256);
sheet.setColumnWidth(cellNo++, 10*256);
sheet.setColumnWidth(cellNo++, 10*256);
sheet.setColumnWidth(cellNo++, 8*256);
cellNo=1;//重置
//3.创建行对象
//=========================================大标题=============================
nRow = sheet.createRow(rowNo++);//创建行对象
nRow.setHeightInPoints(36);//设置行高
nCell = nRow.createCell(cellNo);//创建单元格对象
//合并单元格
sheet.addMergedRegion(new CellRangeAddress(0,0,1,8));//横向合并单元格
//设置单元格的内容
nCell.setCellValue(inputDate.replace("-0", "-").replace("-", "年")+"月份出货表");//2015-01 2015-12
//设置单元格样式
nCell.setCellStyle(this.bigTitle(wb));
//=======================================小标题=================================
String titles[] = {"客户","订单号","货号","数量","工厂","工厂交期","船期","贸易条款"};
//创建小标题的行对象
nRow = sheet.createRow(rowNo++);
nRow.setHeightInPoints(26.25f);//设置行高
//创建单元格对象,并设置内容 ,并设置样式
for(String title :titles){
nCell = nRow.createCell(cellNo++);//创建单元格对象
nCell.setCellValue(title);//设置内容
nCell.setCellStyle(this.title(wb));//设置样式
}
//=======================================数据输出=================================================
String hql= "from ContractProduct where to_char(contract.shipTime,'yyyy-MM') ='"+inputDate+"'";
List<ContractProduct> list = contractProductService.find(hql, ContractProduct.class, null);//查询出符合指定船期的货物列表
for(int i=1;i<=1000;i++){
for(ContractProduct cp :list){
nRow = sheet.createRow(rowNo++);//产生数据行
nRow.setHeightInPoints(24);//设置行高
cellNo=1;
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getContract().getCustomName());//客户名称
nCell.setCellStyle(this.text(wb));//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getContract().getContractNo());//订单号--- 合同号
nCell.setCellStyle(this.text(wb));//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getProductNo()); // 货号
nCell.setCellStyle(this.text(wb));//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getCnumber());// 数量
nCell.setCellStyle(this.text(wb));//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getFactoryName());//工厂名
nCell.setCellStyle(this.text(wb));//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getDeliveryPeriod()));//交期
nCell.setCellStyle(this.text(wb));//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getShipTime()));//船期
nCell.setCellStyle(this.text(wb));//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getContract().getTradeTerms());//贸易条款
nCell.setCellStyle(this.text(wb));//设置文本样式
}
}
//======================================输出到客户端(下载)========================================
DownloadUtil downUtil = new DownloadUtil();
ByteArrayOutputStream baos = new ByteArrayOutputStream();//流 内存中的缓存区
wb.write(baos);//将excel表格中的内容输出到缓存
baos.close();//刷新缓存
HttpServletResponse response = ServletActionContext.getResponse();//得到response对象
downUtil.download(baos, response, "出货表.xlsx");//如果是中文,下载时可能会产生乱码,如何解决?
return NONE;
}
//大标题的样式
public CellStyle bigTitle(Workbook wb){
CellStyle style = wb.createCellStyle();
Font font = wb.createFont();
font.setFontName("宋体");
font.setFontHeightInPoints((short)16);
font.setBoldweight(Font.BOLDWEIGHT_BOLD); //字体加粗
style.setFont(font);
style.setAlignment(CellStyle.ALIGN_CENTER); //横向居中
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //纵向居中
return style;
}
//小标题的样式
public CellStyle title(Workbook wb){
CellStyle style = wb.createCellStyle();
Font font = wb.createFont();
font.setFontName("黑体");
font.setFontHeightInPoints((short)12);
style.setFont(font);
style.setAlignment(CellStyle.ALIGN_CENTER); //横向居中
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //纵向居中
style.setBorderTop(CellStyle.BORDER_THIN); //上细线
style.setBorderBottom(CellStyle.BORDER_THIN); //下细线
style.setBorderLeft(CellStyle.BORDER_THIN); //左细线
style.setBorderRight(CellStyle.BORDER_THIN); //右细线
return style;
}
//文字样式
public CellStyle text(Workbook wb){
CellStyle style = wb.createCellStyle();
Font font = wb.createFont();
font.setFontName("Times New Roman");
font.setFontHeightInPoints((short)10);
style.setFont(font);
style.setAlignment(CellStyle.ALIGN_LEFT); //横向居左
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //纵向居中
style.setBorderTop(CellStyle.BORDER_THIN); //上细线
style.setBorderBottom(CellStyle.BORDER_THIN); //下细线
style.setBorderLeft(CellStyle.BORDER_THIN); //左细线
style.setBorderRight(CellStyle.BORDER_THIN); //右细线
return style;
}
八.正确的方向
模板打印
1.制作模板文件(模板文件路径:/make/xlsprint/tOUTPRODUCT.xls )
2.导入(加载)模板文件,从而得到一个工作簿
3.读取工作表
4读取行
5.读取单元格
6.读取单元格样式
7.设置单元格内容
8.其它单元格就可以使用读到的样式了
tOUTPRODUCT.xls
OutProductAction.print()
//使用模板打印
public String print() throws Exception {
//通用变量
int rowNo=0,cellNo=1;
Row nRow =null;
Cell nCell = null;
//1.读取工作簿
String path = ServletActionContext.getServletContext().getRealPath("/")+"/make/xlsprint/tOUTPRODUCT.xls";
System.out.println(path);
InputStream is = new FileInputStream(path);
Workbook wb = new HSSFWorkbook(is);
//2.读取工作表
Sheet sheet = wb.getSheetAt(0);
cellNo=1;//重置
//3.创建行对象
//=========================================大标题=============================
nRow = sheet.getRow(rowNo++);//读取行对象
nCell = nRow.getCell(cellNo);
//设置单元格的内容
nCell.setCellValue(inputDate.replace("-0", "-").replace("-", "年")+"月份出货表");//2015-01 2015-12
//=======================================小标题=================================
rowNo++;
//=======================================数据输出=================================================
nRow = sheet.getRow(rowNo);//读取第三行
CellStyle customCellStyle = nRow.getCell(cellNo++).getCellStyle();
CellStyle orderNoCellStyle = nRow.getCell(cellNo++).getCellStyle();
CellStyle productNoCellStyle = nRow.getCell(cellNo++).getCellStyle();
CellStyle cNumberCellStyle = nRow.getCell(cellNo++).getCellStyle();
CellStyle factoryCellStyle = nRow.getCell(cellNo++).getCellStyle();
CellStyle deliveryPeriodCellStyle = nRow.getCell(cellNo++).getCellStyle();
CellStyle shipTimeCellStyle = nRow.getCell(cellNo++).getCellStyle();
CellStyle tradeTermsCellStyle = nRow.getCell(cellNo++).getCellStyle();
String hql= "from ContractProduct where to_char(contract.shipTime,'yyyy-MM') ='"+inputDate+"'";
List<ContractProduct> list = contractProductService.find(hql, ContractProduct.class, null);//查询出符合指定船期的货物列表
for(ContractProduct cp :list){
nRow = sheet.createRow(rowNo++);//产生数据行
nRow.setHeightInPoints(24);//设置行高
cellNo=1;
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getContract().getCustomName());//客户名称
nCell.setCellStyle(customCellStyle);//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getContract().getContractNo());//订单号--- 合同号
nCell.setCellStyle(orderNoCellStyle);//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getProductNo()); // 货号
nCell.setCellStyle(productNoCellStyle);//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getCnumber());// 数量
nCell.setCellStyle(cNumberCellStyle);//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getFactoryName());//工厂名
nCell.setCellStyle(factoryCellStyle);//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getDeliveryPeriod()));//交期
nCell.setCellStyle(deliveryPeriodCellStyle);//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(UtilFuns.dateTimeFormat(cp.getContract().getShipTime()));//船期
nCell.setCellStyle(shipTimeCellStyle);//设置文本样式
nCell = nRow.createCell(cellNo++);//产生单元格对象
nCell.setCellValue(cp.getContract().getTradeTerms());//贸易条款
nCell.setCellStyle(tradeTermsCellStyle);//设置文本样式
}
//======================================输出到客户端(下载)========================================
DownloadUtil downUtil = new DownloadUtil();
ByteArrayOutputStream baos = new ByteArrayOutputStream();//流 内存中的缓存区
wb.write(baos);//将excel表格中的内容输出到缓存
baos.close();//刷新缓存
HttpServletResponse response = ServletActionContext.getResponse();//得到response对象
downUtil.download(baos, response, "出货表.xls");//如果是中文,下载时可能会产生乱码,如何解决?
return NONE;
}
九.作业
1.读程
2.往后编写:出口报运模块