有时(根据我的经验,很多时候)您需要为应用程序添加白色标签。 您通常可以以SaaS方式运行它,但是一些重要的或高知名度的客户端可能想要专用的部署或本地部署,或者只是在云部署中“自己的一角”。
白色标签通常包括不同CSS,不同的徽标和其他图像以及不同的页眉和页脚文本。 其余产品保持不变。 那么,我们如何以最小的侵入性方式支持白标? (我将在示例中使用Spring MVC,但是将逻辑移植到其他框架非常简单)
首先,让我们概述支持白标的三种不同方式。 您可以(可能应该)实现所有这些功能,因为它们在不同的场景中很有用,并且有很多重叠之处。
- 标有白色的安装–更改整个部署的样式。 对于本地安装或托管安装很有用。
- 白标子域–允许通过特定子域访问不同样式的服务
- 标有白色的客户–登录后允许特定客户查看自定义样式
要实现全白标安装 ,我们必须在文件系统上配置放置定制css文件和图像以及定制文本的路径。 这是启动时传递给应用程序的.properties文件的示例:
styling.dir=/var/config/whitelabel
styling.footer=©2018 Your Company
styling.logo=/images/logsentinel-logo.png
styling.css=/css/custom.css
styling.title=Your Company
在Spring/Spring启动中,如果某个URL模式匹配,则可以从文件系统中服务器文件。 例如:
@Component
@Configuration
public class WebMvcCustomization implements WebMvcConfigurer {@Value("${styling.dir}")private String whiteLabelDir;@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/whitelabel/**").addResourceLocations(whiteLabelDir);}
}
最后,您需要自定义HTML模板,但是当所有其他选项也都实现时,我们将在最后讨论。
接下来是白标子域 。 对我来说,这是最好的选择,因为它允许您一次安装多个具有特定样式的客户。 样式仅取决于访问服务所通过的域/子域。
为此,我们需要引入一个实体WhitelabelStyling
和一个相应的数据库表。 我们可以创建一些管理界面来进行配置,或者直接在数据库中进行配置。 该实体可能看起来像这样:
@Table("whitelabel_styling")
public class WhitelabelStyling {@PrimaryKeyprivate String key;@Columnprivate String title;@Columnprivate String css;@Column@CassandraType(type = DataType.Name.BLOB)private byte[] logo;@Columnprivate String footer;@Columnprivate String domain;// getters and setters
}
密钥是您选择的任意字符串。 它可能与(sub)域或其他一些有意义的字符串相同。 其余大部分是显而易见的。 有了这些之后,我们需要能够提供资源。 为此,我们需要一个控制器,您可以在这里看到 。 控制器选择一个白色标签的密钥,并尝试从数据库中加载相应的条目,然后提供结果。 在这种情况下,控制器端点为/whitelabel-resources/logo.png
和/whitelabel-resources/style.css
。
为了为特定的子域设置适当的密钥,您需要每个请求的模型属性(即,在要呈现的所有页面的模型中设置的值)。 这样的事情(每天刷新一次白标签缓存;如果您不想在每个请求中都访问数据库,则必须使用缓存):
@ModelAttribute("domainWhitelabel")
public WhitelabelStyling perDomainStyling(HttpServletRequest request) {String serverName = request.getServerName();if (perDomainStylings.containsKey(serverName)) {return perDomainStylings.get(serverName);}return null;
}@Scheduled(fixedRate = DateTimeConstants.MILLIS_PER_DAY)
public void refreshAllowedWhitelabelDomains() {perDomainStylings = whitelabelService.getWhitelabelStyles().stream().collect(Collectors.toMap(WhitelabelStyling::getDomain, Function.identity()));
}
最后,使用相同的控制器,以与上述相同的方式为每个客户添加白标签 ,不是基于request.getServerName()
而是基于当前已认证用户的属性来获取当前密钥。 管理员(通过UI或直接在数据库中)可以为每个用户分配一个whitelabel密钥,然后在登录后,该用户将看到自定义样式。
我们已经看到了解决方案的Java部分的外观,但是我们需要修改HTML模板以选择自定义项。 一种简单的方法如下所示(使用卵石模板):
{% if domainWhitelabel != null %}<link href="/whitelabel-resources/style.css?key={{ domainWhitelabel.key }}" rel="stylesheet">
{% elseif user.whitelabelStyling != null and user.whitelabelStyling.css != '' %}<link href="/whitelabel-resources/style.css" rel="stylesheet">
{% elseif beans.environment.getProperty('styling.dir') != '' and beans.environment.getProperty('styling.css.enabled') == true %}<link href="{{'/whitelabel/'+ beans.environment.getProperty('styling.css')}}" rel="stylesheet">
{% else %}<link href="{{ beans.environment.getProperty('styling.css')}}" rel="stylesheet">
{% endif %}
这非常简单–如果配置了域级别的白色标签,则使用该标签; 如果不是,请检查当前用户是否分配了特定的白标签; 如果没有,请检查是否配置了全局安装白色标签; 如果不是,请使用默认值。 此代码段利用了上面的WhitelabelController
(在前两种情况下)和倒数WhitelabelController
情况下使用了自定义资源处理程序。
总体而言,这是一个灵活,简单的解决方案,即使在现有系统上也不需要花费几天的时间即可实施和测试。 我将再次表达我对基于域的样式的偏爱,因为它们允许使用多个不同样式和徽标使用相同的多租户安装。 当然,应该正确配置Web服务器/负载均衡器/域,以允许子域并让您轻松管理它们,但这是不合时宜的。
我认为白色标签是许多产品的好方法。 显然,除非业务需要它,否则不要实施它,但要记住,它可能会落伍,并且相对容易实施。
翻译自: https://www.javacodegeeks.com/2018/07/implementing-white-labelling.html