使用JSF的面向服務的UI

在大型軟件開發項目中,面向服務的體系結構非常常見,因為它提供了可供不同團隊或部門使用的功能接口。 創建用戶界面時,應應用相同的原理。
對于具有開票部門和客戶管理部門等的大型公司,組織結構圖可能如下所示:

如果計費部門要開發一個用于創建發票的新對話框,則可能如下所示:

如您所見,上面的屏幕在上部引用了一個客戶。 單擊短名稱文本字段后面的“ ..”按鈕將打開以下對話框,允許用戶選擇客戶:

按“選擇”后,客戶數據將顯示在發票表格中。

也可以通過簡單地輸入客戶編號或在發票屏幕上的文本字段中輸入簡稱來選擇客戶。 如果輸入唯一的短名稱,則根本不會出現選擇對話框。 而是直接顯示客戶數據。 只有不明確的簡稱會導致打開客戶選擇屏幕。

客戶功能將由屬于客戶管理團隊的開發人員提供。 一種典型的方法是由客戶管理開發團隊提供一些服務,而計費部門的開發人員創建用戶界面并調用這些服務。

但是,這種方法涉及到這兩個不同部門之間的耦合要強于實際需要。 發票只需要一個唯一的ID即可引用客戶數據。 創建發票對話框的開發人員實際上并不想知道如何查詢客戶數據或在后臺使用哪些服務來獲取該信息。

客戶管理開發人員應提供UI的完整部分,以顯示客戶ID并處理客戶的選擇:

使用JSF 2,使用復合組件很容易實現。 客戶管理部門和計費部門之間的邏輯接口包括三個部分:

  • 復合組件(XHTML)
  • 復合組件的支持bean
  • 偵聽器界面,用于處理選擇結果


提供者(客戶管理部門)

復合組件:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"xmlns:ui="http://java.sun.com/jsf/facelets"xmlns:h="http://java.sun.com/jsf/html"xmlns:f="http://java.sun.com/jsf/core"xmlns:composite="http://java.sun.com/jsf/composite"xmlns:ice="http://www.icesoft.com/icefaces/component"xmlns:ace="http://www.icefaces.org/icefaces/components"xmlns:icecore="http://www.icefaces.org/icefaces/core"><ui:composition><composite:interface name="customerSelectionPanel" displayName="Customer Selection Panel" shortDescription="Select a customer using it's number or short name"><composite:attribute name="model" type="org.fuin.examples.soui.view.CustomerSelectionBean" required="true" />  </composite:interface><composite:implementation><ui:param name="model" value="#{cc.attrs.model}"/><ice:form id="customerSelectionForm"><icecore:singleSubmit submitOnBlur="true" /><h:panelGroup id="table" layout="block"><table><tr><td><h:outputLabel for="customerNumber"value="#{messages.customerNumber}" /></td><td><h:inputText id="customerNumber"value="#{model.id}" required="false" /></td><td>&nbsp;</td><td><h:outputLabel for="customerShortName"value="#{messages.customerShortName}" /></td><td><h:inputText id="customerShortName"value="#{model.shortName}" required="false" /></td><td><h:commandButton action="#{model.select}"value="#{messages.select}" /></td></tr><tr><td><h:outputLabel for="customerName"value="#{messages.customerName}" /></td><td colspan="5"><h:inputText id="customerName"value="#{model.name}" readonly="true" /></td></tr></table></h:panelGroup></ice:form></composite:implementation></ui:composition></html>

復合組件的后備bean:

package org.fuin.examples.soui.view;import java.io.Serializable;import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.inject.Named;import org.apache.commons.lang.ObjectUtils;
import org.fuin.examples.soui.model.Customer;
import org.fuin.examples.soui.services.CustomerService;
import org.fuin.examples.soui.services.CustomerShortNameNotUniqueException;
import org.fuin.examples.soui.services.UnknownCustomerException;@Named
@Dependent
public class CustomerSelectionBean implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String shortName;private String name;private CustomerSelectionListener listener;@Injectprivate CustomerService service;public CustomerSelectionBean() {super();listener = new DefaultCustomerSelectionListener();}public Long getId() {return id;}public void setId(final Long id) {if (ObjectUtils.equals(this.id, id)) {return;}if (id == null) {clear();} else {clear();this.id = id;try {final Customer customer = service.findById(this.id);changed(customer);} catch (final UnknownCustomerException ex) {FacesUtils.addErrorMessage(ex.getMessage());}}}public String getShortName() {return shortName;}public void setShortName(final String shortNameX) {final String shortName = (shortNameX == "") ? null : shortNameX;if (ObjectUtils.equals(this.shortName, shortName)) {return;}if (shortName == null) {clear();} else {if (this.id != null) {clear();}this.shortName = shortName;try {final Customer customer = service.findByShortName(this.shortName);changed(customer);} catch (final CustomerShortNameNotUniqueException ex) {select();} catch (final UnknownCustomerException ex) {FacesUtils.addErrorMessage(ex.getMessage());}}}public String getName() {return name;}public CustomerSelectionListener getConnector() {return listener;}public void select() {// TODO Implement...}public void clear() {changed(null);}private void changed(final Customer customer) {if (customer == null) {this.id = null;this.shortName = null;this.name = null;listener.customerChanged(null, null);} else {this.id = customer.getId();this.shortName = customer.getShortName();this.name = customer.getName();listener.customerChanged(this.id, this.name);}}public void setListener(final CustomerSelectionListener listener) {if (listener == null) {this.listener = new DefaultCustomerSelectionListener();} else {this.listener = listener;}}public void setCustomerId(final Long id) throws UnknownCustomerException {clear();if (id != null) {clear();this.id = id;changed(service.findById(this.id));}}private static final class DefaultCustomerSelectionListener implementsCustomerSelectionListener {@Overridepublic final void customerChanged(final Long id, final String name) {// Do nothing...}}}

用于處理結果的偵聽器接口:

package org.fuin.examples.soui.view;/*** Gets informed if customer selection changed.*/
public interface CustomerSelectionListener {/*** Customer selection changed.** @param id New unique customer identifier - May be NULL.* @param name New customer name - May be NULL.*/public void customerChanged(Long id, String name);}

用戶(計費部門)

發票Bean只是通過注入來使用客戶選擇Bean,并使用偵聽器接口連接到它:

package org.fuin.examples.soui.view;import java.io.Serializable;import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.New;
import javax.inject.Inject;
import javax.inject.Named;@Named("invoiceBean")
@SessionScoped
public class InvoiceBean implements Serializable {private static final long serialVersionUID = 1L;@Inject @Newprivate CustomerSelectionBean customerSelectionBean;private Long customerId;private String customerName;@PostConstructpublic void init() {customerSelectionBean.setListener(new CustomerSelectionListener() {@Overridepublic final void customerChanged(final Long id, final String name) {customerId = id;customerName = name;}});}public CustomerSelectionBean getCustomerSelectionBean() {return customerSelectionBean;}public String getCustomerName() {return customerName;}}

最后,在發票XHTML中,使用了復合組件并將其鏈接到注入的支持bean:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"xmlns:ui="http://java.sun.com/jsf/facelets"xmlns:h="http://java.sun.com/jsf/html"xmlns:f="http://java.sun.com/jsf/core"xmlns:fuin="http://fuin.org/examples/soui/facelets"xmlns:customer="http://java.sun.com/jsf/composite/customer"><ui:composition template="/WEB-INF/templates/template.xhtml"><ui:param name="title" value="#{messages.invoiceTitle}" /><ui:define name="header"></ui:define><ui:define name="content"><customer:selection-panel model="#{invoiceBean.customerSelectionBean}" /></ui:define><ui:define name="footer"></ui:define></ui:composition></html>

摘要
總之,用戶界面中引用其他部門數據的部分應由提供數據的部門負責。 然后,可以很容易地對提供的代碼進行任何更改,而無需對使用代碼進行任何更改。 此方法的另一個重要好處是可以統一應用程序的用戶界面。 顯示相同數據的控件和面板始終看起來相同。 每個部門還可以為其提供的用戶界面組件創建一個存儲庫,從而使設計新對話框的過程像將正確的組件放在一起一樣容易。

參考: A Java Developer's Life博客上的JCG合作伙伴 Michael Schnell提供的面向服務的UI 。


翻譯自: https://www.javacodegeeks.com/2012/09/service-oriented-ui-with-jsf.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371289.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371289.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371289.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

pocib模板流程圖_各單據流程POCIB

POCIB各階段流程報關流程從廣義上講&#xff0c;報關是指進出境運輸工具負責人、進出境口貨物收發貨人、進出境物品的所有人或者他們的代理人向海關辦理運輸工具、貨物、物品進出境手續及相關手續的全過程。其中&#xff0c;進出境運輸工具負責人、進出口貨物收發貨人、進出境物…

WinDbg 查看靜態變量

有如下Class。若想查看靜態變量內容。因為靜態變量和類綁定&#xff0c;僅需要查看類即可。 namespace ConsoleApplication13 {class Program{public static string public_string "pubstr_static";public static string private_string "pristr_static"…

vue 固定div 滾動_vue.js-div滾動條隱藏但有滾動效果的實現方法

組件被包在一個高度固定的divmounted () {var boDiv document.getElementById(this.id);if(boDiv undefined){return;}var isFirefoxnavigator.userAgent.indexOf("Firefox")if(isFirefox>0){boDiv.addEventListener(DOMMouseScroll, function(event) { //火狐v…

JBoss核心Java Web服務

這篇博客文章涉及Web服務。 好吧&#xff0c;更確切地說&#xff0c;它處理JBoss上的“普通” java Web服務。 這意味著我們將創建一個沒有任何其他框架&#xff08;如CXF&#xff0c;Axis等&#xff09;的Web服務。 JBoss它自己提供對Web服務的支持。 因此&#xff0c;如果您真…

JavaSE--for each

參考&#xff1a;http://blog.csdn.net/yasi_xi/article/details/25482173 學習多線程的時候實例化線程數組而挖掘出來的一直以來的理解誤區 之前一直以為for each 本質上和for循環以及迭代器沒什么區別 1 package foreach;2 3 public class ForeachDemo1 {4 5 public …

[BZOJ1726][Usaco2006 Nov]Roadblocks第二短路

1726: [Usaco2006 Nov]Roadblocks第二短路 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 1277 Solved: 607 [Submit][Status][Discuss]Description 貝茜把家搬到了一個小農場&#xff0c;但她常常回到FJ的農場去拜訪她的朋友。貝茜很喜歡路邊的風景&#xff0c;不想那么快…

mysql 5.1.62_MySQL 5.5.62 安裝方法(標準配置版)

1.此安裝方法適用于絕大多數MySQL版本&#xff0c;首先在MySQL官網上下載好所需版本。2.(官網可能不太好找)在我的博客列表中有一篇是MySQL官網下載鏈接&#xff0c;直達下載界面&#xff0c;方便。3.下載。(安裝版 MSI Installer)4.下載安裝包然后雙擊開始安裝選擇同意協議并…

簡化Java內存分析

作為一名典型的Java開發人員&#xff0c;除了遵循關閉連接&#xff0c;流等典型的最佳實踐外&#xff0c;我從未監視過應用程序的內存使用情況。最近&#xff0c;我們在JBoss服務器中遇到了一些問題&#xff0c;不得不深入研究內存管理Java中最好的事情之一是&#xff0c;創建對…

nyoj 1129 Salvation 模擬

思路&#xff1a;每個坐標有四種狀態&#xff0c;每個點對應的每種狀態只能走一個方向&#xff0c;如果走到一個重復的狀態說明根本不能走到終點&#xff0c;否則繼續走即可。 坑點&#xff1a;有可能初始坐標四周都是墻壁&#xff0c;如果不判斷下可能會陷入是死循環。 貼上測…

詳解mysql數據庫的啟動與終止_詳解MySQL數據庫的啟動與終止(一)

由于MySQL服務器具有多種安裝分發&#xff0c;而且能夠運行在多種操作平臺之上&#xff0c;因此它的啟動與停止的方法也多種多樣。你可以根據實際情況使用其中的一種。在你安裝、升級或者維護系統時&#xff0c;你可能需要多次啟動和終止服務器&#xff0c;你需要了解啟動和終止…

easyui 插入中間行

function inserrow() {var index_dx 0;var index_lt 0;var rows $(#dg).datagrid(getRows)//獲取當前的數據行前期數據準備for (var i 0; i < rows.length; i) {if (rows[i][運營商] 電信) {index_dx i;dxptjss_dx parseInt(rows[i][短信平臺接收數]);} else {index_…

使用JNA的透明JFrame

在“ 使JFrame透明”中&#xff0c;我展示了一種使用AWTUtilities類使框架透明的方法。 但是使用該類會導致訪問限制編譯時錯誤&#xff0c;該文章中還顯示了Eclipse中的解析。 現在&#xff0c;這里是使用Java本機的版本。 我使用Java本機訪問&#xff08;JNA&#xff09;庫來…

Problem: Query on the tree(二分+劃分樹)

題目鏈接&#xff1a; Problem: Query on the tree Time limit: 1s Mem limit: 64 MB Problem DescriptionThere is a tree with n node, labeled from 1 to n, and the root of the tree is 1. For every node i, if its father is j, its value vivj*i%20161119, the…

day04_09 while循環03

練習題: 3.如何輸入一個如下的直角三角形,用戶指定輸出行數:(如果上下反轉,右如何實現?) ********** 以下是自己的思路,沒有按照上課老師的思路,反正經過不斷的測試改進得出的算法 num int(input("請輸入行數")) line 1 while line < num1:lie 1 while lie &l…

idal 創建springboot 項目_手把手的SpringBoot教程,SpringBoot創建web項目(四)

在實際的開發過程中&#xff0c;我們需要前端頁面向Java端提交請求&#xff0c;這些請求一般分為get方式和post方式&#xff0c;不管是哪一種方式&#xff0c;一般都會攜帶一些參數。這一節&#xff0c;我們來演示一下如何給Controller傳遞參數。代碼&#xff1a;RestControlle…

JavaOne 2012:Lambda之路

我最熱切期待的JavaOne 2012演講之一是Brian Goetz的“通往Lambda的道路”。 昨晚的技術主題演講中的Lambda味道僅增加了預期。 這是在希爾頓廣場A / B舉行的&#xff0c;距離我上次在金門大橋A / B / C參加的演講僅幾步之遙。 我原本希望打包相對較大的Plaza A / B&#xff08…

沉浸式go-cache源碼閱讀!

大家好&#xff0c;我是豆小匠。 這期來閱讀go-cache的源碼&#xff0c;了解本地緩存的實現方式&#xff0c;同時掌握一些閱讀源碼的技巧~ 1. 源碼獲取 git clone https://github.com/patrickmn/go-cache.git用Goland打開可以看到真正實現功能的也就兩個go文件&#xff0c;ca…

CoreAnimation 變換

CoreAnimation 變換 CoreAnimation 目錄 博客園MakeDown支持不佳,如有需要請進GitHub 本片博客主要內容: 仿射變換 - CGAffineTransform3D變換 - CATransform3D仿射變換 - CGAffineTransform CGAffineTransform 是用于二維空間的旋轉,縮放和平移的屬性.首先展示一個簡單的樣例,…

20170907wdVBA_GetCellsContentToExcel

WORD 加載項 代碼模板 Dim cmdBar As CommandBar, cmdBtn As CommandBarControl Const cmdBtnCap As String "批量提取操作步驟"Sub AutoExec()Call DelCmdBtnCall AddCmdBtnEnd Sub Sub AutoExit()Call DelCmdBtn End SubSub AddCmdBtn()Set cmdBar Application.C…

mysql 5.7 mirror_Centos7 Docker離線部署Mysql5.7

1 環境信息查看系統內核[rootlocalhost /]# cat /etc/redhat-releaseCentOS Linux release 7.5.1804 (Core)2 虛擬機拉取鏡像此處資源獲取在虛擬機中進行&#xff0c;完成后上傳到服務器安裝2.1 拉取mysql5.7鏡像[rootlocalhost /]# docker pull mysql:5.72.2 導出鏡像[rootloc…