在大型软件开发项目中,面向服务的体系结构非常常见,因为它提供了可供不同团队或部门使用的功能接口。 创建用户界面时,应应用相同的原理。
对于具有开票部门和客户管理部门等的大型公司,组织结构图可能如下所示:

如果计费部门要开发一个用于创建发票的新对话框,则可能如下所示:

如您所见,上面的屏幕在上部引用了一个客户。 单击短名称文本字段后面的“ ..”按钮将打开以下对话框,允许用户选择客户:

按“选择”后,客户数据将显示在发票表格中。

也可以通过简单地输入客户编号或在发票屏幕上的文本字段中输入简称来选择客户。 如果输入唯一的短名称,则根本不会出现选择对话框。 而是直接显示客户数据。 只有不明确的简称会导致打开客户选择屏幕。

客户功能将由属于客户管理团队的开发人员提供。 一种典型的方法是由客户管理开发团队提供一些服务,而计费部门的开发人员创建用户界面并调用这些服务。

但是,这种方法涉及到这两个不同部门之间的耦合要强于实际需要。 发票只需要一个唯一的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

使用JSF的面向服务的UI相关推荐

  1. jsf服务_使用JSF的面向服务的UI

    jsf服务 在大型软件开发项目中,面向服务的体系结构非常常见,因为它提供了可供不同团队或部门使用的功能接口. 创建用户界面时,应应用相同的原理. 对于具有开票部门和客户管理部门等的大型公司,组织结构图 ...

  2. 基于面向服务体系架构(SOA)和面向资源体系架构(ROA)的业务组件模型

    引言 在<面向服务体系架构(SOA)和业务组件(BC)的思考>(以下简称< SOA 和 BC >)一文中介绍了基于面向服务体系架构(SOA)的组件模型,本文按照"分离 ...

  3. [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店...

    原文:[.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店 一.前言 在前面专题一中,我已经介绍了我写这系列文章的初衷了.由于dax.net中的DDD框架和Bytear ...

  4. 一起谈.NET技术,使用WCF实现SOA面向服务编程—— 架构设计

    SOA本身就是一种面向企业级服务的系统架构,简单来说,SOA就是一种进行系统开发的新的体系架构,在基于SOA架构的系统中,具体应用程序的功能是由 一些松耦合并且具有统一接口定义方式的组件(也就是ser ...

  5. 面向服务与微服务架构

    背景 最近阅读了 Martin Fowler 和 James Lewis 合著的一篇文章 Microservices, 文中主要描述和探讨了最近流行起来的一种服务架构模式--微服务,和我最近几年工作的 ...

  6. 从WebService到面向服务架构SOA理解【二】

    概要: (1)通过上一篇项目的WebService搭建学习,能够有了对WebService一定的认识. (2)接下来记录自己通过对WebService的学习对面向服务架构的理解. WebService ...

  7. 面向服务架构(SOA)与微服务架构

    面向服务架构 面向服务架构的思想在整个软件的架构中已经不是什么新鲜的东西.我简单地认为服务化是模块化的延伸,所以服务化有着和模块化类似的优点和缺点.无论你采用哪种协议定义服务与服务之间的通信方式(如W ...

  8. 论面向服务的架构及其应用

      声明:本文为本人在软考系统架构设计师备考期间的练手写作,不保证内容的原创性与正确性,仅供参考,请勿照抄和用于学术论文等正规场合,因不当使用产生后果一律自负. 摘要   2019年3月,我单位联合某 ...

  9. 【转】面向服务及其在互联系统策略中的角色

    面向服务的业务环境 面向服务是一种创建分布式系统的方法.在它最抽象的层面,面向服务作为一个服务提供程序,包含了一切--从大型机应用程序到打印机到码头工作人员到隔夜交货公司.服务提供程序通过接口公开了功 ...

最新文章

  1. 【BZOJ 1036】[ZJOI2008]树的统计Count
  2. Spring相关API-getBean()方法的使用
  3. 【算法学习笔记】哈夫曼树的构建和哈夫曼编码的实现代码
  4. 内网用户之间使用MSN Messenger快速传送文件的小窍门
  5. “DNAT+云链接+CDN”加速方案,助力出海企业落地生长
  6. infinitescroll php,WordPress: 增加无限分页(Infinite Scroll)功能
  7. ajax php 错误提示,php – jQuery AJAX错误处理
  8. R-数据挖掘 | 聚类分析中的各种相异(似)度计算
  9. 自己编译nvm-window,解决无法修改镜像下载node很慢的问题!
  10. 达梦8用户和角色管理
  11. xp怎样修改计算机mac地址,WinXP系统MAC地址修改的方法
  12. WatchOS开发教程之六: 表盘功能开发
  13. oracle回收DBA权限以及授权表空间
  14. 表单设计:五类表单构成要素设计
  15. 计算机主机实际功率,PC动力之源,一起来算算电源真实功率吧!
  16. luoguT30208 太极剑(贪心)
  17. Chrome html播放器卡顿,谷歌Chrome浏览器卡顿原因及解决办法
  18. ShareX 屏幕截图分享好工具
  19. 在 LaTeX 中定义变量
  20. Kindle 可旋转桌面时钟

热门文章

  1. 机器学习评价指标大汇总
  2. RandomAccessFile类解析
  3. vim 命令模式 筛选_10个步骤的筛选器模式
  4. apache spark_Apache Spark Job的剖析
  5. java char类型空值_展望Java的未来:空值类型
  6. cloud foundry_介绍“又一个” Cloud Foundry Gradle插件
  7. conditional_如何:在Spring中使用@Conditional和Condition注册组件
  8. java 多线程性能_Java中多线程的性能比较
  9. maven 打包编译_您是否真的想加快Maven的编译/打包速度? 那么takari生命周期插件就是答案。...
  10. 掌握Java 11的Constantdynamic