map集合可以通过key查数据 保证稳定性
list集合 0,1,2排序不一定是对应的数据
quartz代码没问题 却调用两次 可能是tomcat的配置文件有问题 tomcat\conf\server.xml删掉Context docBase.....
回顾
1、打断设计
打断设计就是表中字段的冗余,把外键消除了,当存在一对多时,是在一的一方加入多的一方的集合,这个集合用于存储多的主键,并且使用分隔符进行分隔(如用逗号分隔)
2、跳跃查询
跳跃查询就是在打断设计基础上进行查询数据时的优化,比传统的关联数据加载效率翻倍
使用打断设计原则:
当关联级别数据加载的层数大于4层时,就必须考虑打断设计,否则加载数据速度过慢。
3、再次优化
数据搬家
数据搬家就是实现表级别的数据冗余,在该项目中用于当添加出口报运单时,也要实现报运单下的货物和附件的数据搬家,搬家的数据来源于
购销合同的货物和附件,这样出口报运单就可以直接关联查询到它的货物和附件。
4、出口报运
当用户选择购销合同后,就可以进行出口报运,此时的出口报运单信息是不全面的,所以它的状态只能是一个草稿,其他信息在更新时再去完善
5、百万数据的POI
HSSFWorkbook:只能操作excel2003
XSSFWorkbook:可以操作excel2007+,虽然可以操作大量数据,但是实际操作时会出问题,问题原因是创建对象过多,而这些对象都是在内存中,所以可能导致溢出。
SXSSFWorkbook:是在XSSFWorkbook基础上优化,原理是首先设置一个内存中对象的数量值,默认为100个对象,当内存中所产生的对象数据超出规定的限制时,
就会将这些对象写入到临时的xml文件中,此时内存中的这些对象就可以销毁了,以后不断这样进行。同时也存在缺点:1、不能使用模版打印了
2、在写磁盘过程中消耗的IO操作时间过多,会导致内存中又产生很多对象,但是原来的对象还没有完整写入磁盘中。
采用分隔 产生多个文件来完成数据打印
6、内存监视小工具
jdk自带的jvisualvm.exe工具
通过这个工具就可以查看到cpu的使用情况,垃圾回收器的工作情况,堆内存使用情况
二、使用DHTML实现动态更新出口报运单
DHTML:动态的html
html+css+js
常用dhtml插件:
EasyUI,Extjs,tabledo,js
1、页面添加文件
<script type="text/javascript" src="${ctx}/components/jquery-ui/jquery-1.2.6.js"></script>
<script type="text/javascript" src="${ctx}/js/tabledo.js"></script>
<script type="text/javascript" src="${ctx}/js/datepicker/WdatePicker.js"></script>
2、进行更新操作
产品的申领
分组领取
包括:50个种类
班组:60个班组
当领取完成后,就要实现数据的更新,结果反映更新速度慢,问题是这些组用品已领完,以后是不会更新的,这样如果每次也更新它,就浪费时间
解决方法:
1、在每个用品每组对应的小格子中放入一个隐藏域,就可以放入3000个隐藏域,结果是处理速度反而更慢了,不考虑用
2、在每组放入一个隐藏域,这样放入60个隐藏域(0代表当前行的数据没有更新,1代表当前行的数据有更新)
引用tabledo.js来实现出口报运单下的货物列表展示
此处不用ajax方式实现处理
ajax请求需要经历1,2,3,4步骤,而传统方式只需要1,2步骤就可以
3、程序代码的实现
<input type=\"hidden\" name=\"mr_id\" value=\""+id+"\">货物编号
<input class=\"input\" type=\"hidden\" id=\"mr_changed\" name=\"mr_changed\">"修改标志
<input type=\"text\" name=\"mr_cnumber\" maxLength=\"10\" value=\""+cnumber+"\" onblur=\"setTRUpdateFlag(this)\" size=\"15\"> 数量
在Action中接受数据
三、读程
方法
1、通读
2、带着问题去读(客户反馈bug,带着学习的问题去读程)
读程中的问题
1、是否可以使用模版
否,由于用户的习惯,造成不能直接使用模版
2、数据和打印代码分离
封装每页数据到map中,封装所有页到list中
//填写每页的内容,之后在循环每页读取打印
Map<String,String> pageMap = null;
List<Map> pageList = new ArrayList(); //打印页
3、图片(logo图片和货物图片)插入到excel中
工具类中直接封装,直接调用工具类方法
//设置logo图片
poiUtil.setPicture(wb, patriarch, path+"make/xlsprint/logo.jpg", curRow, 2, curRow+4, 2);
//插入产品图片
if(UtilFuns.isNotEmpty(printMap.get("ProductImage"))){
System.out.println(printMap.get("ProductImage"));
poiUtil.setPicture(wb, patriarch, path+"ufiles/jquery/"+printMap.get("ProductImage"), curRow-1, 1, curRow, 3);
}
4、实现画线
poiUtil.setLine(wb, patriarch, curRow, 2, curRow, 8); //draw line
5、合并单元格划线
合并单元格,只实现第一个单元格的画线,其他的单元格必须手动补,通过直接创建这个单元格,设置画线的样式即可
//合并单元格
sheet.addMergedRegion(new CellRangeAddress(0,0,1,8));//横向合并单元格
//合并单元格画线
for(int j=2;j<9;j++){
nCell = nRow.createCell(j);
nCell.setCellStyle(poiUtil.notehv10_BorderThin(wb, defaultFont10));
}
6、加人民币前缀
public short rmb2Format(HSSFWorkbook wb) {
HSSFDataFormat format = wb.createDataFormat();
return format.getFormat("\"¥\"#,###,###.00"); // 设置格式
}
Short rmb2Format = poiUtil.rmb2Format(wb);
nCell.setCellStyle(poiUtil.moneyrv12_BorderThin(wb,defaultFont12,rmb2Format));
,代表千位符
#,代表数字,如果这个值为0,又在最前面,它的结果空
0,代表,当这位有值时,直接显示值,如果最后一位没有值时显示0
7、如何写公式
普通单元格内容
nCell.setCellType(HSSFCell.CELL_TYPE_FORMULA);
nCell.setCellFormula("F"+String.valueOf(curRow)+"*H"+String.valueOf(curRow));
8、多行文本自动换行
curStyle.setWrapText(true); //换行
9、单元格自适应高度
float height = poiUtil.getCellAutoHeight(printMap.get("Crequest"), 12f); //自动高度
nRow.setHeightInPoints(height);
10、插入一个分页符
if(p>0){
sheet.setRowBreak(curRow++); //在第startRow行设置分页符
}
11、审单人增加名称后,验货员不会向后推动
utilFuns.fixSpaceStr(contract.getCheckBy(),26)
12、日期转化成中文格式
UtilFuns.formatDateTimeCN(UtilFuns.dateTimeFormat(contract.getSigningDate()))
13、打印一款货物或者打印两款货物
if(contract.getPrintStyle().equals("2")){
14、同一个生产厂家的打印在一页上,不同则另起一页
存在问题:主要是迭代器的问题,可以改成List集合配合下标读取元素,在判断厂家前,查询的多个货物信息时,必须先排序,按生产厂家名称
否则,可能会先找到其他厂家的货物,造成纸张浪费等
Set<ContractProduct> oSet = contract.getContractProducts();
List<ContractProduct> oList = new ArrayList<ContractProduct>(oSet);
四、Quartz实现定时任务调度
1、需求及实现思路
当指定的交期到时,给相关人员发送一封邮件进行提醒,需要与工厂进行联系,定时查询库存预警信息,如果存在库存预警信息,发送邮件通知给相关工作人员
2、什么是Quartz框架
Quartz是一个开源的作业调度框架,完全由java写成,并设计用于J2SE和J2EE应用中,提供了巨大的灵活性而不牺牲简单性。能够用它来为执行
一个作业而创建简单的或复杂的调度
1、Job
表示一个任务(工作),要执行的具体内容
2、JobDetail
JobDetail表示一个具体的可执行的调度程序,Job是这个可执行调度程序所要执行的内容,另外JobDetail还包含了这个任务调度的方案和策略
3、Trigger
代表一个调度参数的配置,什么时候去调
4、Scheduler
代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger,当Trigger和JobDetail组合,就可以被Scheduler容器调度了
3、准备工作和测试
1、引入Quartz框架
修改pom.xml文件,添加依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
2、编写测试代码
创建类JobTest
/**
* 定义一个任务类
* @author Administrator
*
*/
public class MailJob {
public void send() throws Exception{
System.out.println("任务执行:"+new Date());
}
}
3、编写配置文件
applicationContext-job.xml 前缀和一般的spring配置文件一样
<description>Quartz配置文件</description>
<bean id="mailJob" class="my.job.MailJob" ></bean>
<bean id="methodInvokingJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="mailJob"></property>
<property name="targetMethod" value="send"></property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="methodInvokingJob"></property>
<property name="cronExpression" value="0/10 * * * * ? *"></property>
</bean>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers" >
<list>
<ref bean="cronTrigger"></ref>
</list>
</property>
</bean>
public class DeliveryPeriodJob {
private ContractService contractService;
public void setContractService(ContractService contractService) {
this.contractService = contractService;
}
/**
* 以当前时间为标准,查询出交期到期的购销合同,并进行邮件发送,以提醒负责人
* @throws Exception
*/
public void execute() throws Exception{
String hql = "from Contract where to_char(deliveryPeriod,'yyyy-MM-dd')=?";
String deteStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
List<Contract> list = contractService.find(hql, Contract.class, new String[]{deteStr});
if(list!=null && list.size()>0){
for(final Contract c :list){
Thread.sleep(3000);
Thread th = new Thread(new Runnable() {
public void run() {
try {
MailUtil.sendMail("[email protected]", "提醒:交期到了", "您有一个购销合同的交货日期于"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(c.getDeliveryPeriod())+"到期");
} catch (Exception e) {
e.printStackTrace();
}
}
});
th.start();
}
}else{
System.out.println("目前还没有购销合同交期到期的");
}
}
}