【问题标题】:How to Manage Client Specific Configuration如何管理客户端特定配置
【发布时间】:2012-01-10 03:31:40
【问题描述】:

对于一个由多个客户使用的产品,其中不同的客户要求在用户界面和功能方面进行不同的定制,如何适应这些更改而不会使代码与客户特定的代码混在一起?

是否有任何框架(适用于任何编程语言)对此有所帮助?

要添加更多细节,UI 是基于 Web 并使用 JSP 编写的。

【问题讨论】:

  • 配置语言不可知?我不这么认为.....

标签: java configuration customization


【解决方案1】:

这是管理同一应用程序的不同版本的最困难的业务需求之一,因此不要指望这种情况下的开放框架,但是每个涉及的公司都会为此开发自己的系统。

至于业务逻辑修改,您将受益于强大的接口和IoC(例如Spring)。您将为您的特定情况覆盖服务并更改所需的方法,然后将修改后的服务版本注入 IoC。

至于 UI,更难,因为你选择了 JSP,它的灵活性很小。当您在 Swing 或 GWT 中编程时,您可以用同样的方式进行 UI 修改 - 覆盖所需的 UI 类,更改它们,注入修改后的版本。使用 JSP - 在您的自定义版本中,可能会对 .jsp 文件进行大量修改。

现在更改修改/错误修复 - 完全使用版本控制系统。当然,您的客户特定版本是分支,而主要的标准版本是主干。对主干进行错误修复,然后合并到客户特定的分支。对于接口/覆盖实现,大多数合并都是简单的方法,但是,对于 JSP,我希望经常发生冲突......

通常,代码更改合并比任何基于 XML 的内容更容易。

【讨论】:

    【解决方案2】:

    简单的OOP怎么样?设置一个实际的接口/基类,并根据某种配置,根据客户端实例化子类 A 或 B。对于这样一个与语言无关的问题,很难提供更多细节,但我认为这是非常现实的。

    【讨论】:

    • 感谢您的回答。 UI 元素呢?
    【解决方案3】:

    在 Win32/.NET 世界中常见的这个问题的一个解决方案是将特定于客户端的“代码”移动到资源文件中。许多 .NET 项目(.NET 通过 System.Resources 命名空间内置支持此模式)使用此模式进行国际化,方法是将 UI 字符串放入每种语言的一个文件中,然后在运行时从适当的文件加载 UI 字符串.

    这种模式如何应用于 JSP 应用程序?好吧,在这里您可以为每个客户端保留一个资源文件(或者,使用数据库代替文件),并在您提供页面时从资源文件中加载特定于用户的自定义设置。

    例如,假设您最大的客户希望将他们的徽标覆盖在您网站中每个网页的某些部分上。您的页面可以加载 CustomerLogo 属性,并将其用作页面该部分的 HTML 图像的 src 属性。如果您将页面提供给重要客户,则加载 URL“/static/images/importantCustomerLogo.png”,否则将回退到指定 URL“/static/images/logo.png”的默认资源文件。”

    这样,您可以将用于将属性加载到一个或两个 Java 文件中的代码抽象出来,并在整个网站中使用这些属性。您的代码库中唯一特定于客户的部分将是一组资源文件,这些文件可以采用易于阅读和修改的干净 XML 格式。结果是,最初没有开发应用程序的人可以修改 XML,而无需先阅读代码,因此您不必维护资源文件 - 销售部门可以为您完成这项工作。

    【讨论】:

      【解决方案4】:

      GWT 通过一个名为 deferred binding 的功能开箱即用地做到这一点

      在编译 GWT 应用程序时,编译器实际上会针对每个不同的浏览器生成不同版本的代码。这是开箱即用的自动完成,GWT 组件负责处理不同的浏览器血腥细节。

      此功能可以扩展为基于自定义属性的产品任意编译。这是一个简化的示例:假设您对普通视图和详细视图有不同的视图定义

      public abstract class AbstractView { ....}
      public abstract class NormalView extends AbstractView { ... }
      public abstract class DetailedView extends AbstractView { ....}
      

      您可以创建一个将生成两个不同版本的模块定义,一个使用NormalView 类,另一个使用DetailedView(在您的 gwt.xml 文件中)

      <define-property name="customMode" values="normal,detailed" />
      
      <replace-with class="com.example.NormalView">
        <when-type-is class="com.example.AbstractView" />
        <when-property-is name="customMode" value="normal" />
      </replace-with>
      
      <replace-with class="com.example.DetailedView">
        <when-type-is class="com.example.AbstractView" />
        <when-property-is name="customMode" value="detailed" />
      </replace-with>
      

      使用

      AbstractView view = GWT.create(AbstractView.class);
      

      将在运行时提供适当的实例。

      您可以将特定于客户端的代码封装到特定的类中,并为不同的实现公开通用接口。

      你还需要根据当前查看的客户端选择合适的编译版本(这个可以使用jsp)


      请不要将上面的代码示例作为测试,可能存在语法问题,只是为了传达总体思路


      JSP 后端是 GWT 应用程序的理想托管环境,您将能够利用 requestfactory 机制在客户端和服务器之间轻松通信。

      显然这里有一个学习曲线,IMO official documentation 是一个很好的起点。

      【讨论】:

        【解决方案5】:

        我想您可能会尝试阅读 OSGi 相关文章(或书籍)...这个平台将为您的模块化问题提供非常实用的答案。它特别设计为能够处理与依赖关系一起生活的不同模块和版本控制。 正如答案中提到的,通过 OSGi 声明式服务进行依赖注入是 Spring 的一个非常有价值的替代方案,具有动态功能。部署提供服务的包,您的引用将自动更新,删除它,它们也将被刷新。 .. 看看这项技术,然后问一些问题? 问候 杰罗姆

        【讨论】:

          猜你喜欢
          • 2022-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-31
          • 2018-07-21
          • 2017-03-12
          • 2023-03-20
          • 2017-04-02
          相关资源
          最近更新 更多