ManagementDay10(DHTML动态更新 通过隐藏域更新 读程 任务调度 定时发东西)

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>

    <!-- 定义一个方法调用MethodInvokingJobDetailFactoryBean -->
    <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 {
    //注入ContractService
    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);//让当前线程休眠  3秒

                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("目前还没有购销合同交期到期的");
        }
    }
}

猜你喜欢

转载自blog.csdn.net/civilizationv/article/details/80459434