随笔-86  评论-767  文章-3  trackbacks-3

第五章 LPMT中的控制结构

Struts 的控制逻辑中, Controller ActionServlet RequestProcessor 是由 Struts 自身实现的。用户需要实现的是 Model Action Perform 或者 Execute 方法。我们定义了两个 Action IssueAction MainAction ,在 Action 中根据参数 action 的类型判断并实现各种逻辑操作。下面以 IssueAction IssueActionForm IssueDetail.jsp 为例说明 LPMT 中的控制结构实现。

5.1 Action中的控制结构实现

IssueAction 中,定义参数 action 来判断各种操作类型。 Action 值来自客户端请求的 URL action = httpServletRequest.getParameter("action").trim()

action == “view” :分页查看所有 Issue

action == “viewDetail” 查看单个 Issue 及其 IssueDatas ChangeLogs

action == “create” 新建一个 Issue

action == “edit” :编辑选定 Issue

action == “delete” :删除选定 Issue

action == “save” :保存新建或修改过的 Issue

action == ” createIssueData” :为选定的 Issue 新建 IssueData

action == “saveIssueData” :保存新建或修改过的 IssueData

action == “editIssueData” :修改选定的 IssueData

action == “deleteIssueData” :删除选定的 IssueData

在判定操作类型之后, Action 根据需要初始化对象,调用 IssueBean 的方法完成相应的业务逻辑操作,最后返回相应的 ActionMapping 对象。

5.2 ActionForm中的控制逻辑实现

IssueActionForm 中,处理对应表单页面的所有项之外,我们另外定义了一个 actionType 参数,来保存并传递 Action 的操作类型。

private String actionType = "create";

Action 判定操作类型之后,要设置对应 IssueActionForm 对象的 actionType 值。比如:

issueActionForm.setActionType(action);

issueDataActionForm.setActionType(action);

5.3 View中的控制逻辑实现

IssueAction 对应的 IssueDetail.jsp 页面中,需要根据当前 IssueActionForm 参数 actionType 的值来判断当前操作类型,继而实现相应的显示逻辑。比如:

actionType = “create” 时,操作类型为新建 Issue ,此时显示一张空白表单,初始化 Component Environment 等可选项;当 actionType = “edit” 时,操作类型为编辑 Issue ,此时要载入表单值,如 issueId title Component 等等;当 actionType = “viewDetail” 时,操作类型为查看 Issue 内容。这里使用 <logic:equal> 标签来实现控制显示逻辑,用 <logic:present> <logic:notPresent> 判断对应的 issueActionForm 是否已经载入页面。我们以显示 IssueId 为例:

       <logic:equal name="issueActionForm" property="actionType" value="create">

              <html:text property="issueId"/>

       </logic:equal>

       <logic:equal name="issueActionForm" property="actionType" value="edit">

              <logic:present name="issueActionForm">

                     <html:text name="issueActionForm" property="issueId"/>

              </logic:present>

              <logic:notPresent name="issueActionForm">

                     <b>Error:No issue.</b>

              </logic:notPresent>

       </logic:equal>

       <logic:equal name="issueActionForm" property="actionType" value="viewDetail">

              <logic:present name="issueActionForm">

                     <bean:write name="issueActionForm" property="issueId" />

              </logic:present>

              <logic:notPresent name="issueActionForm">

                     <b>Error:No issue.</b>

              </logic:notPresent>

       </logic:equal>

页面效果如下:

13.jpg


第六章 LPMT中的WebForm技术实现

Web 系统设计中, WebForm 作为直接呈现给客户端的 View ,其实现技术一直为业界所关注。从最初的单纯的 HTML ,到后来的 CGI PERL ,到最近的 ASP JSP ,到目前的标签库,业界一直在寻找一种能够快速开发、灵活、高效率、可重用的技术来实现业务逻辑呈现。在 LPMT 中,我们采用 HTML 结合 Jakarta Struts 标签的技术来实现, JSP 页面作为单纯的 View 使用,而业务逻辑完全由 Action 完成。同样是运行于 Server 端的技术,与单纯的 ASP JSP 技术相比,运用 Jakarta Struts 标签库构建的 JSP 页面结构更清晰,可重用性和扩展性更优秀。

6.1 Jakarta Struts 标签库

Jakarta Struts1.0 的标签库包括:

l        Bean 标签:

提供一组操作标签,用于在必要的时候封装逻辑,使用JavaBeansHTTP CookiesHTTP Headers。这些标签封装在文件名为struts-bean.tld的标签包中。

l        Logical 标签:

提供一组用来在JSP页中有条件地产生输出文本,在对象集合中循环从而重复地产生输出文本,以及应用程序流程控制的标签。Logical标签库定义的标记能够执行条件逻辑、重复循环、转发/重定向等功能,可以完全替代scriptlet。这些标签封装在文件名为struts-logic.tld的标签包中。

l        HTML 标签:

用来生成HTML标签,显示表单元素、控件及其数据,使用会话IDURL进行编程,以及显示错误信息。这些标签封装在文件名为struts-html.tld的标签包中。

l        Templete 标签:

提供一组用于定义可重用的模板视图的标签,包括:<template:get/><template:insert/><template:put>。这些标签被封装在文件名为struts-template.tld的标签包中。

Struts1.1 还引入了struts-nestedstruts-tiles两个标签库。在LPMT中,我们采用了Struts1.0的四个标签库。

6.2 WebFormJakarta Struts标签技术实现

WebForm 即是通常 MVC 设计模式中的 View 。在 LPMT 中, View 由通过 HTML Struts 标签构建的 JSP 页面充当。 JSP 页面作为 View 使用,只负责显示业务逻辑的处理结果,并不负责业务逻辑处理。为使 View 具有较高的可复用性,通常将多个逻辑显示集合在一个 View 完成;为使 View 具有较高的稳定性, JSP 页面应该保留通用的接口,即使 Action 的业务逻辑改变了, View 仍然不需要修改。另外,为使 View 具有较高的可扩展性和可维护性,降低未来可能的维护成本, View 结构应该清晰易读。以 IssueDetail.jsp 为例说明 WebForm Jakarta Struts 技术实现。

IssueDetail.jsp 的设计需求是要实现 Issue 创建、查看、修改、删除的页面显示。当操作类型为创建 create ”时, View 应该初始化一张空白的 Issue 表单,等待用户输入;当操作类型为查看 viewDetail ”时, View 应该把相应的 Issue 的值及其 IssueData ChangeLog 显示出来,内容为不可编辑;当操作类型为修改时, View 表单应该初始化相应 Issue 的值并于相应的 HTML 控件集合,内容为可编辑;当操作类型为删除 delete ”时, View 不显示或者显示 Issue 的内容,不可编辑。 为实现上述上述逻辑,我们采用 <logic:equal> 标签,通过判断 issueActionForm 对象的 actionType 参数的 value 值来判断操作类型,继而实现相应的显示逻辑。以显示 Issue description 值为例,代码实现如下:

<logic:equal name="issueActionForm" property="actionType" value="create">

              <html:textarea property="description" rows="8" cols="40"/>

       </logic:equal>

    <logic:equal name="issueActionForm" property="actionType" value="edit">

              <logic:present name="issueActionForm">

                     <html:textarea property="description" rows="8" cols="40"/>

              </logic:present>

              <logic:notPresent name="issueActionForm">

                     <b>Error:No issue.</b>

              </logic:notPresent>

       </logic:equal>

       <logic:equal name="issueActionForm" property="actionType" value="viewDetail">

              <logic:present name="issueActionForm">

                     <bean:write name="issueActionForm" property="description" />

              </logic:present>

              <logic:notPresent name="issueActionForm">

                     <b>Error:No issue.</b>

              </logic:notPresent>

       </logic:equal>

       而在 View 通用性设计方面, IssueDetail.jsp 通过使用 <logic:present> <logic:notPresent> 标签判断对象 issueActionForm 是否已经加载到 scope 以及加载进来的 issueActionForm actionType 等属性值来完成逻辑显示。这意味着当 Action 完成相应的业务逻辑之后,在返回指向 IssueDetail.jsp ActionMapping 对象之前,只需要把相应的 IssueActionForm 对象实例加载到如 Request Session 或者 PageContext 即任何一个 scope 里面就可以了,不需要在 URL 中传递任何参数。

比如在 IssueAction 中,当操作类型为查看相应 Issue 的详细内容时, URL 请求为 http://localhost:8000/issuecontrol/issueAction.do?action=viewDetail&issueId=... IssueAction 先取得 URL 传递过来的 issueId 参数值,然后通过 IssueBean.getIssueById 方法取得对应的 IssueActionForm 对象实例 issueActionForm ,设置 issueActionForm 对象的 actionType 参数,把 issueActionForm 放到 httpServletRequest 对象中,最后设置转向参数 address 的值为 ”viewIssueDetail” 。代码示例如下:

if("viewDetail".equals(action)) {

String issueId = "";

            if(httpServletRequest.getParameter("issueId")!=null)

issueId = httpServletRequest.getParameter("issueId").trim();

IssueActionForm issueActionForm = IssueBean.getIssueById(issueId);

if(issueActionForm == null) {

runningErrors.add(new ActionError("Issue(IssueID=" + issueId + ") not found."));

             httpServletRequest.setAttribute("runningErrors",runningErrors);

             address = "error";

        }

        else {

             httpServletRequest.setAttribute("issueActionForm",issueActionForm);

                     issueActionForm.setActionType(action);

        address = "viewIssueDetail";

          }

}

当操作类型为新建一个 Issue 实例的时候, URL 请求为 http://localhost:8000/issuecontrol/issueAction.do?action=create IssueAction 取得 typeActionForm 对象数组、 componentActionForm 对象数组、 flagActionForm 对象数组、 environmentActionForm 对象数组和 priorityActionForm 对象数组并放到 httpServletRequest 对象中,最后设置转向参数 address 的值为 ”viewIssueDetail” 。代码示例如下:

       else if("create".equals(action)) {

          httpServletRequest.setAttribute("typeActionForms",IssueBean.getAllTypes());

httpServletRequest.setAttribute("componentActionForms",IssueBean.getAllComponents());

httpServletRequest.setAttribute("flagActionForms",IssueBean.getAllFlags());    httpServletRequest.setAttribute("environmentActionForms",IssueBean.getAllEnvironments());

        httpServletRequest.setAttribute("priorityActionForms",IssueBean.getAllPriorities());

              address = "viewIssueDetail";

}

当操作类型为编辑修改一个 Issue 实例的时候, URL 请求为 http://localhost:8000/issuecontrol/issueAction.do?action=edit&issueId =... IssueAction 根据取得的参数 issueId 的值取得相应的 IssueActionForm 对象实例 issueActionForm ,设置 issueActionForm 的参数 actionType 的值,取得 typeActionForm 对象数组、 componentActionForm 对象数组、 flagActionForm 对象数组、 environmentActionForm 对象数组和 priorityActionForm 对象数组并将所有对象实例放到 httpServletRequest 对象中,最后设置转向参数 address 的值为 ”viewIssueDetail” 。代码示例如下:

else if("edit".equals(action)) {

address = "viewIssueDetail";

String issueId = "";

if(httpServletRequest.getParameter("issueId") != null)

IssueId = httpServletRequest.getParameter("issueId").trim();

IssueActionForm issueActionForm = IssueBean.getIssueById(issueId);

if(issueActionForm == null) {

runningErrors.add(new ActionError("Issue(IssueID=" + issueId + ") not found."));

          httpServletRequest.setAttribute("runningErrors",runningErrors);

          address = "error" ;

}

else {

issueActionForm.setActionType(action);

          httpServletRequest.setAttribute("issueActionForm",issueActionForm);

httpServletRequest.setAttribute("typeActionForms",IssueBean.getAllTypes());        httpServletRequest.setAttribute("componentActionForms",IssueBean.getAllComponents());

httpServletRequest.setAttribute("flagActionForms",IssueBean.getAllFlags());        httpServletRequest.setAttribute("environmentActionForms",IssueBean.getAllEnvironments());        httpServletRequest.setAttribute("priorityActionForms",IssueBean.getAllPriorities());

address = "viewIssueDetail";

       }

}

另外,由于 View 只负责逻辑显示,而不需要实现业务逻辑,因此结构非常清晰,扩展和修改都将非常容易,可以将扩展和修改维护的成本降低到很小的水平。

6.3 与单纯的JSP代码的比较

与目前业界比较常用的单纯 ASP/JSP 代码构建的 WebForm 方法相比,上述 WebForm 构建技术有明显的优势:

l        构建成本低,效率高

Jakarta Struts 标签库提供了一系列的标签用于快速构建 JSP View ,标签库包括一般的 HTML 元素和控件 (html 标签 ) ,流程和逻辑控制的标签 (logic 标签 ) bean 操作标签等等。这里以循环显示所有的 Component 为例比较一下两种方法的效率,假设 Component 对象数组可以从 request 中得到。

Logical 标签:

<logic:iterate id="components" name="componentActionForms">

              <bean:write name="components" property="component" />

</logic:iterate>

单纯的 JSP 代码:

<%

       ComponentActionForm[] components

= (ComponentActionForm[])request.getAttribute(“componentActionForms”);

              For(int i=0;i<components.length;i++) {

                     out.println(components[i].getComponent);

}

%>

可以预见,显示逻辑越复杂,用 Jakarta Struts 标签库构建的 JSP View 效率越高,结构也更清晰,构建和维护成本更低。详细代码请看附录 IssueDetail.jsp 代码。

l        可扩展性高

对于单纯的 JSP/ASP 代码构建的 View 而言,由于业务逻辑通常是在 JSP 页面完成的,所以当业务逻辑改变或扩展之后,相应的 View 也必须改变;如果业务逻辑是在多个页面完成的话,修改的成本更大,可扩展性更差。而用 Jakarta Struts 标签库构建的 View ,由于业务逻辑在相应的 Action 中完成,所以只需要修改相应的 Action 操作就可以了。尤其当 Action 复用程度比较高的时候,这种修改需要的工作量更小,而且 View 根本不需要修改,这种优势也是 MVC 设计模式 Model View 的分离所带来的良好的可扩展性。

l        可重用性高

运用 Jakarta Struts Logical 标签,可以构建高度可复用的 WebForm 。虽然单纯的 JSP/ASP 代码技术也可以实现,但由此所带来的构建、修改和维护成本将随着逻辑的复杂度增加而急剧增长。比如上文提到的,运用 Jakarta Struts Logical 标签,我们很容易将 Issue 的创建、查看、修改、删除显示逻辑集中在一个 IssueDetail.jsp View 中完成。

l        可读性高,结构清晰

Jakarta Struts 标签和 HTML 代码很接近,不需要额外的用 <%%> 等标签包含起来,可读性更高。而 Jakarta Struts 标签集合了逻辑和流程控制,与 HTML 结合所构建的 JSP View 结构更清晰。下图为 HTML 中内嵌 JSP 代码和 Struts 标签的代码截图,可以看到,使用 Struts 标签的 View 结构更清晰,更易读。

14.jpg

14 HTML 中内嵌 JSP 代码

15.jpg

15 HTML中内嵌Struts标签代码

posted on 2005-01-27 14:52 eamoi 阅读(3356) 评论(0)  编辑  收藏 所属分类: Java毕业设计文档

只有注册用户登录后才能发表评论。


网站导航: