zoukankan      html  css  js  c++  java
  • 【Java EE 学习 72 下】【数据采集系统第四天】【移动/复制页分析】【使用串行化技术实现深度复制】

    一、移动、复制页的逻辑实现

    移动、复制页的功能是在设计调查页面的时候需要实现的功能。规则是如果在同一个调查中的话就是移动,如果是在不同调查中的就是复制。

    无论是移动还是复制,都需要注意一个问题,那就是页面在一个调查中的位置问题,这就需要一个变量来标识该该页面在一个调查中的位置。我们在Page对象中添加一个成员变量orderNo,该变量是float类型的变量,默认值和pageId相同,在设置pageId的同时设置好orderNo,我们使用该变量来对一个调查中的所有页面进行排序。

    移动、复制页的流程就是:

    在设计调查页面中的页面上给出一个超链接:”移动、复制页“->Action查找到所有的Survey并将所有Survey中的所有页面显示出来,用户选择在页面之前还是之后并提交->Action根据原页面和目标页面进行判断是需要进行移动页面还是复制页面,并调用相应的方法进行移动、复制页->重定向到设计调查页面上。

    1.移动页面的实现分析

    移动页面的实现相对来说要简单很多。首先,移动页面一定是在同一个调查中,所以我们只需要将原页面的orderNo进行相应的更改即可,更改之后重定向到设计调查页面上查看更改是否生效。

    2.复制页面的实现分析

    复制页面相对移动页面来说要复杂的多,首先复制页面不是在同一个调查中,而且需要将原来的页面进行拷贝,Page对象中有几个成员变量,特别是questions成员变量更应该着重考虑。复制页面非常容易被误导成变量的引用复制,实际上不是这样,所谓复制就是将原来的对象原原本本的拷贝一份,即使原来的对象不存在了,拷贝的那份对象也能够毫无影响的继续运作。

    这里借助串行化技术实现对对象的深度复制。串行化使用到的技术主要是对象流和内存流。对象序列化之后写入内存,让后再从内存中取出来形成新的对象。这样就完成了对对象的深度复制。实现深度复制的代码如下:

     1 //实现深度复制的方法
     2     //在实现深度复制之前必须修改Bean类中的相关字段,
     3     //比如Page类中的pageId必须加上transient修饰,还有Question类中的questionId字段也必须加上transient修饰
     4     private Serializable copyPage(Page oldPage) {
     5         oldPage.getQuestions().size();
     6         try {
     7             ByteArrayOutputStream baos=new ByteArrayOutputStream();
     8             ObjectOutputStream oos=new ObjectOutputStream(baos);
     9             oos.writeObject(oldPage);
    10             ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
    11             ObjectInputStream ois=new ObjectInputStream(bais);
    12             Serializable serializable=(Serializable) ois.readObject();
    13             return serializable;
    14         } catch (IOException e) {
    15             e.printStackTrace();
    16         } catch (ClassNotFoundException e) {
    17             e.printStackTrace();
    18         }
    19         return null;
    20     }

    实现深度复制需要注意几点:

      (1).在进行深度复制之前,必须解决懒加载可能出现的异常。以上的代码中,接收了一个Page对象,首先调用了该对象的getQuestions().size();这么做是为了防止出现懒加载异常的情况。如果不这么做的话会出现什么情况呢?在复制该对象之前,由于Page对象的questions成员变量默认启用了懒加载策略。所以并不会到数据库中查询Question对象填充questions成员变量。这样一来深度复制之后的Page对象中的questions对象就没有实际的值。一旦调用该成员变量就会出现懒加载异常。

      (2).深度复制之前必须修改Bean中的定义。将Page类中的pageId使用transient关键字修饰,同样,也需要对Question类中的questionId使用transient关键字修饰。transient关键的作用就是在串行化对象的时候忽略该字段。这样得到的深度复制后的页面对象中的相应字段就是null。比如Page对象,它的pageId为NULL,同时该对象中的所有questions列表中的Question对象中的questionId也是NULL。因为需要重新保存到数据库,如果不这么做就会报错,因为无论是Page对象还是Question对象都是主键自动增长的。当然我们能够手动设置pageId和questionId为NULL,但是并不管用,原因未明,所以直接使用transient关键字对其进行修饰是最最快最省事的方法。

    3.orderNo的设置问题。

      我在这里设置orderNo值越小,排名越靠前,反之排名越靠后。

      如果是需要放到第一页的前面,则将目标也的orderNo的值设置为比第一页的orderNo小0.01,如果放置到最后一页的后面,则设置目标页的orderNo的值为最后一页的orderNo大0.01,其他情况下使用两者的平均值。 

      所有的orderNo的值都保留两位小数点。

    因为需要知道页面中的最大页码和最小页码,所以在PageService中就需要提供两个方法判断获取最大值和最小值的方法。

     1     @Override
     2     public boolean isLastPage(Page page) {
     3         String hql="from Page where survey.surveyId=? order by orderNo desc";
     4         List<Page>pages=this.pageDao.findEntitysByHQL(hql,page.getSurvey().getSurveyId());
     5         return pages.get(0).getPageId()==page.getPageId();
     6     }
     7     @Override
     8     public boolean isFirstPage(Page page) {
     9         String hql="from Page where survey.surveyId=? order by orderNo asc";
    10         List<Page>pages=this.pageDao.findEntitysByHQL(hql,page.getSurvey().getSurveyId());
    11         return pages.get(0).getPageId()==page.getPageId();
    12     }

    4.实现移动页的代码

     1 /**
     2      * 移动的规则就是:
     3      * 如果是最前面的页面,则将页面的orderNo设置为第一个页面的orderNo-0.01,
     4      * 如果是最后面的一个页面,则将页面的orderNo设置为最后一个页面的orderN+0.01,
     5      * 如果是中间的一个页面,则使用两边orderNo的平均值
     6      * 
     7      * @param position
     8      * @param oldPage
     9      * @param newPage
    10      */
    11     private void doMovePage(String position, Page oldPage, Page newPage) {
    12         //第一种情况是position是0,代表是放到目标页的前面
    13         if("0".equals(position)){
    14             //如果是放到目标页的前面的话,需要考虑目标页是不是第一页的情况
    15             if(isFirstPage(newPage)){
    16                 //是第一页的话使用第一页的orderNo-0.01
    17                 oldPage.setOrderNo(newPage.getOrderNo()-0.01F);
    18             }else{
    19                 //否则的话取平均值
    20                 oldPage.setOrderNo((this.getPrePage(newPage).getOrderNo()+newPage.getOrderNo())/2);
    21             }
    22         }else if("1".equals(position)){//第二种情况是position是1,带包是放到目标页的后面
    23             //如果是放到目标页的后面,需要考虑目标页是不是最后一页的情况
    24             if(isLastPage(newPage)){
    25                 oldPage.setOrderNo(newPage.getOrderNo()+0.01F);
    26             }else{
    27                 //否则的话取平均值
    28                 oldPage.setOrderNo((this.getNextPage(newPage).getOrderNo()+newPage.getOrderNo())/2);
    29             }
    30         }
    31         pageService.updatePage(oldPage);
    32     }

    5.实现复制页的代码:

     1 //不同页面之间使用页面复制,深度复制
     2     private void doCopyPage(String position, Page oldPage, Page newPage) {
     3         Page copyPage=(Page) this.copyPage(oldPage);
     4         //第一种情况是position是0,代表是放到目标页的前面
     5         if("0".equals(position)){
     6             //如果是放到目标页的前面的话,需要考虑目标页是不是第一页的情况
     7             if(isFirstPage(newPage)){
     8                 //是第一页的话使用第一页的orderNo-0.01
     9                 copyPage.setOrderNo(newPage.getOrderNo()-0.01F);
    10             }else{
    11                 //否则的话取平均值
    12                 copyPage.setOrderNo((this.getPrePage(newPage).getOrderNo()+newPage.getOrderNo())/2);
    13             }
    14         }else if("1".equals(position)){//第二种情况是position是1,带包是放到目标页的后面
    15             //如果是放到目标页的后面,需要考虑目标页是不是最后一页的情况
    16             if(isLastPage(newPage)){
    17                 copyPage.setOrderNo(newPage.getOrderNo()+0.01F);
    18             }else{
    19                 //否则的话取平均值
    20                 copyPage.setOrderNo((this.getNextPage(newPage).getOrderNo()+newPage.getOrderNo())/2);
    21             }
    22         }
    23         float temp=copyPage.getOrderNo();
    24         copyPage.setSurvey(newPage.getSurvey());
    25         pageService.addNewPage(copyPage);
    26         copyPage.setOrderNo(temp);
    27         pageService.updatePage(copyPage);
    28         for(Question question:copyPage.getQuestions()){
    29             questionService.saveQuestion(question);
    30         }
    31     }
    32     //实现深度复制的方法
    33     //在实现深度复制之前必须修改Bean类中的相关字段,
    34     //比如Page类中的pageId必须加上transient修饰,还有Question类中的questionId字段也必须加上transient修饰
    35     private Serializable copyPage(Page oldPage) {
    36         oldPage.getQuestions().size();
    37         try {
    38             ByteArrayOutputStream baos=new ByteArrayOutputStream();
    39             ObjectOutputStream oos=new ObjectOutputStream(baos);
    40             oos.writeObject(oldPage);
    41             ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
    42             ObjectInputStream ois=new ObjectInputStream(bais);
    43             Serializable serializable=(Serializable) ois.readObject();
    44             return serializable;
    45         } catch (IOException e) {
    46             e.printStackTrace();
    47         } catch (ClassNotFoundException e) {
    48             e.printStackTrace();
    49         }
    50         return null;
    51     }

    之前曾经在Survey对象中添加了量个字段,minOrderno和maxOrderno,这两个字段和现在的问题完全没有关系,但是在之后的参与调查中的导航功能有密切的关系。

    二、移动页的实现演示

    在第一个调查中移动有四页,而且页面都按照顺序进行了排序。现在想要将第一页移动到第三页和第四页之间。

      首先,单击第一页旁边的”移动、复制页“超链接,跳转到选择位置的界面上去,该界面显示了所有的调查中的所有的页面。而且原页面使用了重色标注出来了。

    我们单击第三页的”之后“单选按钮,然后点击之后的确定,直接跳转到设计调查页面上去了,同时我们发现,第一页真的到了第三页和第四页之间,同时第一页原来的位置被第二页所取代。

    其实想要实现这个效果有两种方式可以是西安,第一种是放到放到第三页之后,第二种是放到第四页之前,这里选择一种即可。

    三、复制页的实现演示

    现在我一共创建了6个调查,其中第一个调查设计的最多,有四页的问题。我给第二个调查添加几个页面并添加几个问题如下图所示:

    现在我想将第一个调查中的标题为“第一页”的页面复制到第二个调查中的第二页和第三页之间

    步骤如下,单击第一个调查的标题为“第一页”的页面中的“复制、移动页”超链接。

    然后单击确定按钮,发现跳转到了调查二,同时原页面已经被复制到了指定的位置。

  • 相关阅读:
    IntelliJ破解
    IDEA的配置
    已解决No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
    逆向工程,调试Hello World !程序(更新中)
    一种离谱到极致的页面侧边栏效果探究
    前端H5如何实现分享截图
    我女儿说要看雪,但是我家在南方,于是我默默的拿起了键盘,下雪咯。
    Web基本教程~05.CSS属性
    送你一朵小红花,CSS实现一朵旋转的小红花
    Vue 项目性能优化 —实战—面试
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/5053702.html
Copyright © 2011-2022 走看看