zoukankan      html  css  js  c++  java
  • 【Java EE 学习 70 下】【数据采集系统第二天】【Action中User注入】【设计调查页面】【Action中模型赋值问题】【编辑调查】

    一、Action中User注入问题

      Action中可能会经常用到已经登陆的User对象,如果每次都从Session中拿会显得非常繁琐。可以想一种方法,当Action想要获取User对象的时候直接使用,这种方法还是得需要借助拦截器的力量,直接在登录拦截器中实现即可,但是登陆拦截器怎么知道该Action想要获取User对象呢?这就需要给Action加上一个接口,如果该Action是该接口的实现类,则表示该Action想要获取User对象。接口仿照HttpRequestAware接口的形式,名字为用户关注接口:

     1 package com.kdyzm.struts.action.aware;
     2 
     3 import com.kdyzm.domain.User;
     4 /**
     5  * 用户关注接口,用于Action获取Session中的User对象
     6  * @author kdyzm
     7  *
     8  */
     9 public interface UserAware {
    10     public void setUser(User user);
    11 }

    这样在登陆拦截器中直接进行判断即可,如果用户已经登陆了,而且请求的Action是UserAware的实现类,那么就通过setUser方法将User注入到Action中。这样登录拦截器中的intercept方法就变成了如下的形式:

     1 public String intercept(ActionInvocation invocation) throws Exception {
     2         System.out.println("被登录拦截器拦截!");
     3         Action action=(Action) invocation.getAction();
     4         if(action instanceof LoginAction ||action instanceof RegisterAction){
     5             System.out.println("即将进行登录或者注册,直接放行!");
     6             return invocation.invoke();
     7         }
     8         HttpServletRequest request=ServletActionContext.getRequest();
     9         HttpSession session=request.getSession();
    10         User user=(User) session.getAttribute("user");
    11         if(user==null){
    12             System.out.println("用户未登录,必须先登录再访问其他资源!即将跳转到登陆界面!");
    13             return "toLoginPage";
    14         }else{
    15             System.out.println("用户已经登陆,登录拦截器已经放行!");
    16             //如果用户名不为空,而且实现了UserAware接口,就需要调用该接口中的相应方法给类中的成员变量赋值
    17             //TODO 给Action中User动态赋值的方法
    18             if(action instanceof UserAware){
    19                 ((UserAware)action).setUser(user);
    20             }
    21             return invocation.invoke();
    22         }
    23     }

    二、设计调查页面,设计调查页面几乎是该项目中最复杂的一个页面了在“我的调查”中的其中一个调查栏目中直接单击“设计调查”超链接,就直接跳转到设计调查页面,当然需要在Action将调查对象(Survey对象)先查询出来。完整的页面设计代码如下这个页面设计起来非常困难,我也是写了好几个小时才完成的,因为需要考虑到很多因素,需要一步一步的进行调试才行。

    完整代码是:

      1 <%@ page language="java" pageEncoding="utf-8"%>
      2 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
      3 <html>
      4 <head>
      5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      6 <link rel="stylesheet" href="${pageContext.servletContext.contextPath}/css/header.css" type="text/css">
      7 <style type="text/css">
      8     table{
      9         border: 1px solid black;
     10         border-collapse: collapse;
     11         width: 100%;
     12     }
     13     table tr{
     14         border-collapse: collapse;
     15     }
     16     tr td{
     17         border:1px solid black;
     18         border-collapse: collapse;
     19     }
     20     a{
     21         color: gray;
     22         text-decoration: none;
     23     }
     24     a:HOVER {
     25         color: red;
     26     }
     27     .tdHL{
     28         text-align: left;
     29         border-width: 0px;
     30     }
     31     .tdHR{
     32         text-align: right;
     33         border-width: 0px;
     34     }
     35     .pageTitle{
     36         background-color: #CCF;
     37     }
     38     .questionTitle{
     39         background-color: #CCC;
     40     }
     41 </style>
     42 <title>Insert title here</title>
     43 </head>
     44 <body>
     45     <%@ include file="/header.jsp" %>
     46     <div>
     47         <!-- 先设计一个变量保存住surveyid -->
     48         <s:set value="%{surveyId}" name="id"/>
     49         <table>
     50             <tr>
     51                 <td colspan="2">设计调查</td>
     52             </tr>
     53             <tr>
     54                 <td class="tdHL">
     55                     <!-- 这里使用sturs2标签直接判断图片是否存在! -->
     56                     <!-- 在这里加上一个logo标识 -->
     57                     <s:if test="isLogoImageExists()">
     58                         <img width="40px"  alt="这是logo标识" src="<s:url value='%{logoPath}'/>"/>
     59                     </s:if>
     60                     <s:else>
     61                         <!-- 如果图片不存在,则什么都不显示 -->
     62                     </s:else>
     63                     <s:property value="title"/>
     64                 </td>
     65                 <td class="tdHR">
     66                     <s:a action="SurveyAction_toUploadLogoPage.action" namespace="/">
     67                         <s:param name="surveyId" value="%{#id}"></s:param>
     68                     增加Logo
     69                     </s:a>
     70                     &nbsp;
     71                     <s:a action="SurveyAction_toEditSurveyPage.action" namespace="/">
     72                         <s:param name="surveyId" value="%{#id}"></s:param>
     73                     编辑调查</s:a>&nbsp;
     74                     <s:a action="PageAction_toAddPagePage.action" namespace="/">
     75                         <s:param value="%{#id}" name="surveyId"></s:param>
     76                     增加页</s:a>
     77                 </td>
     78             </tr>
     79             <tr>
     80                 <td colspan="2">
     81                     <!-- 主干内容开始 -->
     82                     <table>
     83                         <tr>
     84                             <td width="20px"></td>
     85                             <td width="*">
     86                                 <!-- 迭代页面集合 -->
     87                                 <table>
     88                                     <s:iterator value="%{pages}" var="page">
     89                                         <s:set var="pId" value="%{#page.pageId}"></s:set>
     90                                         <tr>
     91                                             <td>
     92                                                 <table>
     93                                                     <tr class="pageTitle">
     94                                                         <!-- 页面标题 -->
     95                                                         <td width="40%" class="tdHL">
     96                                                             <s:property value="%{#page.title}"/>
     97                                                         </td>
     98                                                         <td width="60%" class="tdHR">
     99                                                             <s:a action="PageAction_toEditPageTitlePage.action" namespace="/">
    100                                                                 <s:param name="pageId" value="%{#pId}"></s:param>
    101                                                                 <s:param name="surveyId" value="%{#id}"></s:param>
    102                                                             编辑页面标题</s:a>&nbsp;
    103                                                             <s:a action="PageAction_toSelectTargetPage.action" namespace="/">
    104                                                                 <s:param name="pageId" value="%{#pId}"></s:param>
    105                                                                 <s:param name="surveyId" value="%{#id}"></s:param>
    106                                                             移动/复制页
    107                                                             </s:a>
    108                                                             &nbsp;
    109                                                             <s:a action="QuestionAction_toSelectQuestionTypePage.action" namespace="/">
    110                                                                 <s:param name="pageId" value="%{#pId}"></s:param>
    111                                                                 <s:param name="surveyId" value="%{#id}"></s:param>
    112                                                             增加问题</s:a>&nbsp;
    113                                                             <s:a action="PageAction_deletePage.action" namespace="/">
    114                                                                 <s:param name="pageId" value="%{#pId}"></s:param>
    115                                                                 <s:param name="surveyId" value="%{#id}"></s:param>
    116                                                             删除页</s:a>
    117                                                         </td>
    118                                                     </tr>
    119                                                     <tr>
    120                                                         <td colspan="2">
    121                                                             <table>
    122                                                                 <tr>
    123                                                                     <td width="20px"></td>
    124                                                                     <td>
    125                                                                         <!-- 迭代问题的集合 -->
    126                                                                         <table>
    127                                                                             <s:iterator value="%{#page.questions}" var="question">
    128                                                                                 <s:set var="qid" value="%{#question.questionId}"></s:set>
    129                                                                                 <!-- 问题题干 -->
    130                                                                                 <tr class="questionTitle">
    131                                                                                     <td class="tdHL"><s:property value="%{#question.title}"/></td>
    132                                                                                     <td class="tdHR">
    133                                                                                         <s:a action="QuestionAction_editQuestion.action" namespace="/">
    134                                                                                             <s:param name="pageId" value="%{#pId}"></s:param>
    135                                                                                             <s:param name="surveyId" value="%{#id}"></s:param>
    136                                                                                             <s:param name="questionId" value="%{#qid}"></s:param>
    137                                                                                         编辑问题</s:a>&nbsp;
    138                                                                                         <s:a action="QuestionAction_deleteQuestion.action" namespace="/">
    139                                                                                             <s:param name="pageId" value="%{#pId}"></s:param>
    140                                                                                             <s:param name="surveyId" value="%{#id}"></s:param>
    141                                                                                             <s:param name="questionId" value="%{#qid}"></s:param>
    142                                                                                         删除问题</s:a>&nbsp;
    143                                                                                     </td>
    144                                                                                 </tr>
    145                                                                                 <!-- 问题主体,主要涉及的问题就是问题的分类 -->
    146                                                                                 <tr>
    147                                                                                     <td colspan="2">
    148                                                                                         <!-- 定义变量,为当前类型的题型 -->
    149                                                                                         <s:set value="%{#question.questionType}" var="qt"></s:set>
    150                                                                                         <!-- 第一种题型:带有单选框或者复选框的 
    151                                                                                             题目标识就是题号小于4,0-3
    152                                                                                         -->
    153                                                                                         <s:if test="#qt lt 4">
    154                                                                                             <s:iterator value="#question.optionTextArr">
    155                                                                                                 <input type='<s:property value="#qt<2?'radio':'checkbox'"/>'>
    156                                                                                                 <s:property/>
    157                                                                                                 <s:if test="#qt==1 || #qt==3">
    158                                                                                                     <br/>
    159                                                                                                 </s:if>
    160                                                                                             </s:iterator>
    161                                                                                             <!-- 处理other的情况 -->
    162                                                                                             <s:if test="#question.other">
    163                                                                                                 <input type='<s:property value="#qt<2?'radio':'checkbox'"/>'>其它
    164                                                                                                 <s:if test="#question.otherType==1">
    165                                                                                                     <input type="text">
    166                                                                                                 </s:if>
    167                                                                                                 <s:elseif test="#question.otherType==2">
    168                                                                                                     <s:select list="#question.otherSelectOptionArr">
    169                                                                                                     </s:select>
    170                                                                                                 </s:elseif>
    171                                                                                             </s:if>
    172                                                                                         </s:if>
    173                                                                                         <!-- 第二种题型,是下拉列表类型的题型 -->
    174                                                                                         <s:elseif test="#qt==4">
    175                                                                                             <s:select list="#question.optionTextArr"></s:select>
    176                                                                                         </s:elseif>
    177                                                                                         <s:elseif test="#qt==5">
    178                                                                                             <s:textfield></s:textfield>
    179                                                                                         </s:elseif>
    180                                                                                         <!-- 第三种题型,矩阵问题,6,7,8 -->
    181                                                                                         <s:else>
    182                                                                                             <table>
    183                                                                                                 <!-- 列头 -->
    184                                                                                                 <tr>
    185                                                                                                     <td></td>
    186                                                                                                     <s:iterator value="#question.matrixColTitleArr">
    187                                                                                                         <td><s:property/></td>
    188                                                                                                     </s:iterator>
    189                                                                                                 </tr>
    190                                                                                                 <!-- 输出N多行 -->
    191                                                                                                 <s:iterator value="#question.matrixRowTitleArr">
    192                                                                                                     <tr>
    193                                                                                                         <td><s:property/></td>
    194                                                                                                         <s:iterator value="#question.matrixColTitleArr">
    195                                                                                                             <td>
    196                                                                                                                 <s:if test="#qt==6">
    197                                                                                                                     <input type="radio">
    198                                                                                                                 </s:if>
    199                                                                                                                 <s:elseif test="#qt==7">
    200                                                                                                                     <input type="checkbox">
    201                                                                                                                 </s:elseif>
    202                                                                                                                 <s:elseif test="#qt==8">
    203                                                                                                                     <select>
    204                                                                                                                         <s:iterator value="#question.matrixSelectOptionArr">
    205                                                                                                                             <option>
    206                                                                                                                                 <s:property/>
    207                                                                                                                             </option>
    208                                                                                                                         </s:iterator>
    209                                                                                                                     </select>
    210                                                                                                                 </s:elseif>
    211                                                                                                             </td>
    212                                                                                                         </s:iterator>
    213                                                                                                     </tr>
    214                                                                                                 </s:iterator>
    215                                                                                             </table>
    216                                                                                         </s:else>
    217                                                                                     </td>
    218                                                                                 </tr>
    219                                                                             </s:iterator>
    220                                                                         </table>
    221                                                                     </td>
    222                                                                 </tr>
    223                                                             </table>
    224                                                         </td>
    225                                                     </tr>
    226                                                 </table>
    227                                             </td>
    228                                         </tr>
    229                                     </s:iterator>
    230                                 </table>
    231                             </td>
    232                         </tr>
    233                     </table>                
    234                 </td>
    235             </tr>
    236         </table>
    237     </div>
    238 </body>
    239 </html>
    View Code

    最核心的代码是对问题种类的判断:

     1 <s:set value="%{#question.questionType}" var="qt"></s:set>
     2 <!-- 第一种题型:带有单选框或者复选框的 
     3     题目标识就是题号小于4,0-3
     4 -->
     5 <s:if test="#qt lt 4">
     6     <s:iterator value="#question.optionTextArr">
     7         <input type='<s:property value="#qt<2?'radio':'checkbox'"/>'>
     8         <s:property/>
     9         <s:if test="#qt==1 || #qt==3">
    10             <br/>
    11         </s:if>
    12     </s:iterator>
    13     <!-- 处理other的情况 -->
    14     <s:if test="#question.other">
    15         <input type='<s:property value="#qt<2?'radio':'checkbox'"/>'>其它
    16         <s:if test="#question.otherType==1">
    17             <input type="text">
    18         </s:if>
    19         <s:elseif test="#question.otherType==2">
    20             <s:select list="#question.otherSelectOptionArr">
    21             </s:select>
    22         </s:elseif>
    23     </s:if>
    24 </s:if>
    25 <!-- 第二种题型,是下拉列表类型的题型 -->
    26 <s:elseif test="#qt==4">
    27     <s:select list="#question.optionTextArr"></s:select>
    28 </s:elseif>
    29 <s:elseif test="#qt==5">
    30     <s:textfield></s:textfield>
    31 </s:elseif>
    32 <!-- 第三种题型,矩阵问题,6,7,8 -->
    33 <s:else>
    34     <table>
    35         <!-- 列头 -->
    36         <tr>
    37             <td></td>
    38             <s:iterator value="#question.matrixColTitleArr">
    39                 <td><s:property/></td>
    40             </s:iterator>
    41         </tr>
    42         <!-- 输出N多行 -->
    43         <s:iterator value="#question.matrixRowTitleArr">
    44             <tr>
    45                 <td><s:property/></td>
    46                 <s:iterator value="#question.matrixColTitleArr">
    47                     <td>
    48                         <s:if test="#qt==6">
    49                             <input type="radio">
    50                         </s:if>
    51                         <s:elseif test="#qt==7">
    52                             <input type="checkbox">
    53                         </s:elseif>
    54                         <s:elseif test="#qt==8">
    55                             <select>
    56                                 <s:iterator value="#question.matrixSelectOptionArr">
    57                                     <option>
    58                                         <s:property/>
    59                                     </option>
    60                                 </s:iterator>
    61                             </select>
    62                         </s:elseif>
    63                     </td>
    64                 </s:iterator>
    65             </tr>
    66         </s:iterator>
    67     </table>
    68 </s:else>

    之前就说过,每个问题的位置不能改变,这是因为将会使用该问题的下标得到该问题是什么种类的问题,一种有九种类型的问题,每一种问题都对应一种独一无二的问题类型。

    最终设计效果如下图所示:当然如果只是当前阶段的话是没有这种效果的,必须结合之后的添加问题的功能才行。整个页面都是用表格标签进行了嵌套,所以显得比较难看,但是也没有好的方法,如果有时间的话就会对其进行优化。

    三、Action中模型赋值问题。(重点)

    每一个Action基本上都是BaseAction的子类,继承BaseAction的优点就是不需要每次都实现模型驱动接口并且重写getModel方法了,模型的赋值过程将会在父类中实现,这里当然也会用到泛型。

    但是实现了模型驱动接口需要注意一点事项:可能会有数据库中的信息和前端页面显示的信息不一致的情况发生。

    首先实现编辑调查功能,小功能非常小,所以略过不提。但是有必要说一下这个过程,因为这是引发该问题的关键

    在设计调查页面单击“编辑调查”->请求SurveyAction.toEditSurveyPage()方法,该方法查询数据库,赋值到model->跳转到editSurveyPage.jsp页面回显,这时候诡异的事情就发生了,回显的时候有异常的情况发生。回显的调查标题是“未命名”,但是该调查原来明明有标题是“居民生活水平调查”。为什么会发生这种情况呢?

    原因分析:栈顶指针未改变导致的。看一下在编辑调查方法中的代码:  

    1 //跳转到编辑调查的页面上去
    2     public String toEditSurveyPage() throws Exception{
    3         this.model=this.surveyService.getModelById(this.model.getSurveyId());
    4         return "toEditSurveyPage";
    5     }

    实际上该方法中只有一句代码而已。就是将数据库中查到的对象赋值给model对象。好像这样就将模型给“刷新”了,但是这也只是“好像”而已,实际上并没有刷新model对象。

    在栈顶中存放的是旧model的引用地址,说到底model只是一个变量而已,如果改变了model的值,只是将model的指针指向了新的地址,但是栈顶的model对象中的值并没有被改变。只是无法再通过model对象访问到而已。所以如果直接给model对象赋值但是不做其他修改是没有任何意义的。

    解决方法:

      方法1.再次压栈,示例代码如下:

    ActionContext.getContext().getValueStack().push(model);

      当然实际上值栈中就会有两份model对象了,这样做的好处就是解决了model赋值的问题,但是也有弊端,每次都需要这么写不嫌麻烦么?而且这么做一点都不“优雅”。

       方法2.通过prepare拦截器加上paramsPrepareStack拦截器栈组合完成该项任务。

      具体做法是首先将BaseAction实现Prepare接口,然后在Action中重写接口中的方法。伪代码如下:

    public void prepareDesignSurvey(){
                this.model = xxx ;
            }

      当然最重要的还是需要改变默认栈为parameterPrepareStack,否则还是没有任何效果。

      Action中的目标方法DesignSurvey中直接跳转页面即可,不需要再对model进行修改。

        为什么使用这种方法能够解决问题:实际上引发该问题的原因是模型赋值在模型驱动拦截器获取model之后完成的,这样就导致了即使改变model对象也不会改变栈顶指针,如果将两者顺序颠倒一下,即先给模型赋值,然后模型驱动拦截器再取值,这样就没问题了,关键是在合适的位置实现模型赋值,首先确定的是一定是在模型驱动拦截器之前,合适的位置就是prepareInterceptor拦截器,所以实现Prepare接口然后重写方法即可;但是仅仅这么做还是不够的,因为parametersInterceptor在默认拦截器栈中的顺序是在模型驱动拦截器之后,所以在prepareInterceptor拦截器中获取不到Action中的相关参数,一定会引发类似于id can't load的异常 ,解决方法就是使用paramsPreparedStack拦截器栈,该拦截器栈和默认的拦截器栈的唯一区别就是在prepare拦截器之前增加了一个parameter拦截器,正好解决了Action中属性赋值的问题。

        下面是两个拦截器栈的定义:

     1 <!-- An example of the paramsPrepareParams trick. This stack is exactly 
     2                 the same as the defaultStack, except that it includes one extra interceptor 
     3                 before the prepare interceptor: the params interceptor. This is useful for 
     4                 when you wish to apply parameters directly to an object that you wish to 
     5                 load externally (such as a DAO or database or service layer), but can't load 
     6                 that object until at least the ID parameter has been loaded. By loading the 
     7                 parameters twice, you can retrieve the object in the prepare() method, allowing 
     8                 the second params interceptor to apply the values on the object. -->
     9             <interceptor-stack name="paramsPrepareParamsStack">
    10                 <interceptor-ref name="exception" />
    11                 <interceptor-ref name="alias" />
    12                 <interceptor-ref name="i18n" />
    13                 <interceptor-ref name="checkbox" />
    14                 <interceptor-ref name="multiselect" />
    15                 <interceptor-ref name="params">
    16                     <param name="excludeParams">dojo..*,^struts..*</param>
    17                 </interceptor-ref>
    18                 <interceptor-ref name="servletConfig" />
    19                 <interceptor-ref name="prepare" />
    20                 <interceptor-ref name="chain" />
    21                 <interceptor-ref name="modelDriven" />
    22                 <interceptor-ref name="fileUpload" />
    23                 <interceptor-ref name="staticParams" />
    24                 <interceptor-ref name="actionMappingParams" />
    25                 <interceptor-ref name="params">
    26                     <param name="excludeParams">dojo..*,^struts..*</param>
    27                 </interceptor-ref>
    28                 <interceptor-ref name="conversionError" />
    29                 <interceptor-ref name="validation">
    30                     <param name="excludeMethods">input,back,cancel,browse</param>
    31                 </interceptor-ref>
    32                 <interceptor-ref name="workflow">
    33                     <param name="excludeMethods">input,back,cancel,browse</param>
    34                 </interceptor-ref>
    35             </interceptor-stack>

      方法3.修改模型驱动拦截器,设置刷新model标识为true

        模型驱动拦截器代码很短,看看它到底干了什么事:

     1 public class ModelDrivenInterceptor extends AbstractInterceptor {
     2 
     3     protected boolean refreshModelBeforeResult = false;
     4 
     5     public void setRefreshModelBeforeResult(boolean val) {
     6         this.refreshModelBeforeResult = val;
     7     }
     8 
     9     @Override
    10     public String intercept(ActionInvocation invocation) throws Exception {
    11         Object action = invocation.getAction();
    12 
    13         if (action instanceof ModelDriven) {
    14             ModelDriven modelDriven = (ModelDriven) action;
    15             ValueStack stack = invocation.getStack();
    16             Object model = modelDriven.getModel();
    17             if (model !=  null) {
    18                 stack.push(model);
    19             }
    20             if (refreshModelBeforeResult) {
    21                 invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
    22             }
    23         }
    24         return invocation.invoke();
    25     }
    26 
    27     /**
    28      * Refreshes the model instance on the value stack, if it has changed
    29      */
    30     protected static class RefreshModelBeforeResult implements PreResultListener {
    31         private Object originalModel = null;
    32         protected ModelDriven action;
    33 
    34 
    35         public RefreshModelBeforeResult(ModelDriven action, Object model) {
    36             this.originalModel = model;
    37             this.action = action;
    38         }
    39 
    40         public void beforeResult(ActionInvocation invocation, String resultCode) {
    41             ValueStack stack = invocation.getStack();
    42             CompoundRoot root = stack.getRoot();
    43 
    44             boolean needsRefresh = true;
    45             Object newModel = action.getModel();
    46 
    47             // Check to see if the new model instance is already on the stack
    48             for (Object item : root) {
    49                 if (item.equals(newModel)) {
    50                     needsRefresh = false;
    51                     break;
    52                 }
    53             }
    54 
    55             // Add the new model on the stack
    56             if (needsRefresh) {
    57 
    58                 // Clear off the old model instance
    59                 if (originalModel != null) {
    60                     root.remove(originalModel);
    61                 }
    62                 if (newModel != null) {
    63                     stack.push(newModel);
    64                 }
    65             }
    66         }
    67     }
    68 }

        在模型驱动拦截器中有个非常重要的属性:refreshModelBeforeResult,该属性是一个标识字段的属性,用于标识是否需要刷新model,什么是刷新model,就是重新获取model的值并压栈,这样最终就能够实现栈顶中的model对象是最新的model对象。

      实现原理:执行模型驱动拦截器的时候,会判断refreshModelBeforeResult的值是否为true,如果为true,则给invocation对象添加一个PreResultListener监听器,模型驱动拦截器中有一个静态类RefreshModelBeforeResult实现了该监听器的接口,观察该实现类的类名,翻译成中文就是“在执行Result之前刷新Model对象”,真是一个直白的方法名,我们知道执行结果集是在最后完成的,那么在执行结果集之前刷新Model对象的话就不会出现上述问题了。它实现刷新的原理十分简单,就是先让老的Model对象弹栈,再获取新的model对象并将新的model对象压栈,OK,前端页面获取的一定就是最新的Model对象了。

      方法4:使用BeanUtils中的copy属性的方法直接给model对象中的所有属性重新赋值,使用这种方式的好处就是不需要考虑model对象是新的对象还是老的对象,但是有一点不好之处就是该方法底层使用反射技术,效率比较低,而且每次都要写该方法实际上和方法一没有什么差别了,都比较麻烦,而且显得十分的“不优雅”。

    四、编辑调查,略。

  • 相关阅读:
    同余方程
    倒酒
    机器翻译
    vue 锚点定位
    解决vuex刷新页面数据丢失
    h5 input失去焦点软键盘把页面顶起
    js 监听ios手机键盘弹起和收起的事件
    js 将数组中的每一项安装奇偶重新组合成一个数组对象
    moment.js获取本周本月本年的开始日期和结束日期
    vue 所有的路由跳转加一个统一参数
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/5052234.html
Copyright © 2011-2022 走看看