JBoss Fuse –使用MVEL将您的静态配置转换为动态模板

最近,我重新发现了我遗忘的JBoss Fuse功能,并且我认为其他人可能会从此提醒中受益

这篇文章将重点放在JBoss Fuse和Fabric8上,所有正在寻找最小侵入性方法来为其静态配置文件添加一定程度的动态支持的开发人员也可能会对此感兴趣。

在OSGi和Fabric8中进行动态配置的想法

OSGi框架因其类加载行为而经常被人们记住。 但其中一部分还定义了框架必须实现的其他概念和功能。 其中之一是ConfigAdmin

ConfigAdmin是一项服务,用于定义逻辑上绑定到部署单元的一组外部化的属性文件。

此外部属性文件的生命周期与OSGi捆绑软件生命周期链接: 如果您修改外部属性文件,则将通知您的捆绑软件 。 根据您对捆绑软件进行编码的方式,您可以决定对通知做出反应,并以编程方式或通过不同的帮助程序框架(例如,蓝图) 来调用使用新配置的代码。

这种机制既方便又强大,并且所有使用OSGi的开发人员都熟悉它。

Fabric8建立在ConfigAdmin的思想之上,并对其进行了扩展

通过其配置功能,Fabric8定义了概要文件的概念,该概要文件封装了部署单元和配置。 它在普通OSGi的基础上增加了一些功能,并且允许管理任何种类的部署单元,不仅是OSGi捆绑软件,还有任何种类的配置或静态文件。

如果查看官方文档,则会找到Fabric8层提供的“扩展”列表,并且您会发现它们主要分为两类: Url Handlers和Property Resolvers 。

我建议对本技术感兴趣的每个人都仔细阅读文档。 但是要提供一个简短的摘要和一个简短的示例,请假设您的Fabric概要文件具有使用特定占位符在运行时解析某些值的功能。 例如

# sample url handler usage, ResourceName is a filename relative to the namespace of the containing Profile:
profile:ResourceName# sample property handler, the value is read at deploy time, from the Apache Zookeeper distributed registry that is published when you run JBoss Fuse
${zk:/fabric/registry/containers/config/ContainerName/Property}

开箱即用有多个处理程序,涵盖了开发人员认为最常见的用例:Zookeeper,配置文件,蓝图,Spring,系统属性,受管端口等。

而且,您可能还想扩展定义自己的扩展的机制:例如,您可能想对存储在某个系统上的性能指标做出反应,您可以编写一个扩展,并使用其语法约定从系统中注入值。

所有这些功能的限制:静态配置文件

我上面介绍的功能令人兴奋且强大,但是它们有一个隐含的限制它们仅适用于.properties文件或Fabric可以识别的文件

这意味着,如果您必须管理Fabric Profile,OSGi属性或与之交互的其他特定技术(例如Camel),则可以使用这些功能,但是对于Fabric-Unaware而言它们没有启用

想象一下,您有读取.xml配置文件的自定义代码。 并想象您的代码没有引用任何Fabric对象或服务。

您的代码将按原样处理该.xml文件。 标记或路径不会有任何魔术替代,因为尽管您在Fabric内部运行,但您并未使用任何直接支持的技术,也未在通知Fabric时可能需要其服务。

解决此问题,您有3种选择

  1. 您为Fabric 编写了扩展 ,以处理和识别您的静态资源,并将动态替换委派给框架代码。
  2. 您可以更改部署单元中包含的代码 ,而不是直接消耗静态资源,而是要求Fabric服务为您内插它们
  3. *您使用mvel:网址处理程序(并避免触摸任何其他代码!)

什么是MVEL?

MVEL实际上是一种编程语言 : https : //en.wikipedia.org/wiki/MVEL 。 特别是,它也是脚本语言 ,您可以从源代码直接运行而跳过编译步骤。

实际上,它具有多个特定的特性,可能使其很有趣地嵌入到另一个应用程序中,并可以在运行时用于定义新的行为。 例如,由于所有这些原因,它也是JBoss Drools项目支持的语言之一,可与您可能希望在运行时定义或修改的业务规则一起使用。

为什么对我们有用? 主要有两个原因:

  1. 它可以很好地用作模板语言
  2. Fabric8已经有一个mvel: url处理程序,它隐式地还充当资源处理程序!

模板语言

模板语言是那些语言系列(通常是领域特定语言),您可以在其中更改按原样阅读的文本的静态部分和将在解析时处理的动态指令 。 我可能以更复杂的方式说出了我上面已经介绍过的相同想法:您可以在文本中包含标记,这些标记将按照特定的约定进行翻译。

这听起来完全像我们上面介绍的处理程序所提供的功能。 有一个重要的区别:虽然那些是上下文特定的处理程序,但MVEL是一种通用技术。 因此,不要指望它对Zookeeper或Fabric配置文件有任何了解,而是希望它能够支持通用编程语言概念,例如循环,代码调用,反射等。

面料支持它!

可在以下位置找到对Fabric中支持的参考: http : //fabric8.io/gitbook/urlHandlers.html

但是,让我添加一个实现该功能的原始代码的一段,因为即使在JBoss Fuse的上下文之外,这也是您可能会发现此方法有趣的部分: https : //github.com/fabric8io/fabric8/blob/1 .x / fabric / fabric-core / src / main / java / io / fabric8 / service / MvelUrlHandler.java#L115-L126

public InputStream getInputStream() throws IOException {assertValid();String path = url.getPath();URL url = new URL(path);CompiledTemplate compiledTemplate = TemplateCompiler.compileTemplate(url.openStream());Map<String, Object> data = new HashMap<String, Object>();Profile overlayProfile = fabricService.get().getCurrentContainer().getOverlayProfile();data.put(“profile”, Profiles.getEffectiveProfile(fabricService.get(), overlayProfile));data.put(“runtime”, runtimeProperties.get());String content = TemplateRuntime.execute(compiledTemplate, data).toString();return new ByteArrayInputStream(content.getBytes());
}

这里发生了什么事?

首先,由于未在代码段中显示,请记住这是一个url处理程序。 这意味着针对通过特定uri引用的文件触发了行为获取。 在这种情况下,它是mvel: 。 例如,有效路径可能是mvel:jetty.xml

要注意的另一个有趣且相对简单的事情是与MVEL解释器的交互。 像大多数模板技术一样,即使是您可以自己实现的最简单的技术,也通常具有:

  • 引擎/编译器,这里是TemplateCompiler
  • 包含模板的变量,这里是url
  • 代表上下文的变量,即要向引擎公开的一组变量,此处为data

将它们放在一起,要求引擎来完成它的工作,这里使用TemplateRuntime.execute(...)而您在输出中得到的是一个静态String。 不再使用模板说明,而是应用了模板定义的所有逻辑,并最终从上下文中获取了一些附加的输入值。

一个例子

我希望我的解释足够简单,但是可能有一个例子是表达该概念的最佳方法。

让我们使用JBoss Fuse default.profile包含的jetty.xml ,它是JBoss Fuse不会作为任何特殊文件处理的静态资源,因此它不提供任何替代功能。

我将在这里展示MVEL集成的两个方面:从上下文变量中读取一些值,并展示如何使用编程逻辑(这里只是2个整数的和):

<Property name="jetty.port" default="@{  Integer.valueOf( profile.configurations['org.ops4j.pax.web']['org.osgi.service.http.port'] ) + 10  }"/>

我们正在修改Jetty端口的默认值,其初始值来自“配置文件”上下文变量,该变量是可识别结构的对象,可以访问其余配置:

profile.configurations['org.ops4j.pax.web']['org.osgi.service.http.port']

我们将其从String显式转换为Integer:

Integer.valueOf( ... )

并将静态值10添加到返回值中:

.. + 10

让我们保存文件,停止我们的fuse实例。 重新启动它并重新创建测试结构:

# in Fuse CLI shell
shutdown -f# in bash shell
rm -rf data instancesbin/fuse# in Fuse CLI shell
fabric:create --wait-for-provisioning

只需等待并监视日志,然后…… 哦,哦。 一个错误! 发生了什么?

这是错误:

2015-10-05 12:00:10,005 | ERROR | pool-7-thread-1  | Activator                        | 102 - org.ops4j.pax.web.pax-web-runtime - 3.2.5 | Unable to start pax web server: Exception while starting Jetty
java.lang.RuntimeException: Exception while starting Jetty
at org.ops4j.pax.web.service.jetty.internal.JettyServerImpl.start(JettyServerImpl.java:143)[103:org.ops4j.pax.web.pax-web-jetty:3.2.5]
…
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)[:1.7.0_76]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)[:1.7.0_76]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)[:1.7.0_76]
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)[:1.7.0_76]
at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.set(XmlConfiguration.java:572)[96:org.eclipse.jetty.aggregate.jetty-all-server:8.1.17.v20150415]
at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.configure(XmlConfiguration.java:396)[96:org.eclipse.jetty.aggregate.jetty-all-server:8.1.17.v20150415]
…
Caused by: java.lang.NumberFormatException: For input string: “@{profile.configurations[’org.ops4j.pax.web'][‘org.osgi.service.http.port’] + 1}”
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)[:1.7.0_76]
at java.lang.Integer.parseInt(Integer.java:492)[:1.7.0_76]
at java.lang.Integer.<init>(Integer.java:677)[:1.7.0_76]
… 29 more

如果您注意到该错误消息,则说明我们的模板片段无法转换为Number

为什么我们的模板代码片段会在第一个实例中显示? 模板引擎应该完成其工作的一部分,并给我们返回一个静态String,而无需任何对模板指令的引用!

我已经故意向您显示此错误,以坚持我上面描述的概念,但是在初审中可能不会被理解。

Fabric中的MVEL支持被实现为url处理程序。

到目前为止, 我们只是修改了静态资源文件的内容,但没有向Fabric提供任何提示,表明我们希望将该文件作为mvel模板进行处理。

怎么做?

使用正确的uri引用同一文件只是一个问题。

因此,修改文件default.profile/org.ops4j.pax.web.properties ,该文件位于默认Fabric Profile中,您可以在其中定义哪个静态文件包含Jetty配置:

# change it from org.ops4j.pax.web.config.url=profile:jetty.xml to
org.ops4j.pax.web.config.url=mvel:profile:jetty.xml

现在,再次停止实例,删除Fabric配置文件,重新创建Fabric,并注意您的Jetty实例如何正确运行。

我们可以通过以下方式进行检查:

JBossFuse:karaf@root> config:list | grep org.osgi.service.http.portorg.osgi.service.http.port = 8181

从浏览器中,您可以验证是否可以通过端口8191访问部署在Jetty顶部的Hawtio(JBoss Fuse Web控制台): http:// localhost:8191 / hawtio

翻译自: https://www.javacodegeeks.com/2015/10/jboss-fuse-turn-your-static-config-into-dynamic-templates-with-mvel.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在linux中dns不安装coching,ubuntu 8.04下openldap的安装和使用

ubuntu 8.04上openldap的安装和使用1、安装openldap。$ sudo apt-get install slapd ldap-utils2、配置openldap。$ sudo /etc/ldap/slapd.conf需要修改的有以下4处。# The base of your directory in database #1# 域名前缀suffix "dcpeercoaching,dccn"# …

linux 拿shell,linux下备份拿shell[渗透必备]

关于php包含Apache日志的利用,其实也就是利用提交的网址里有php语句&#xff0c;然后再被Apache服务器的日志记录&#xff0c;然后php再去包含执行&#xff0c;从而包含了去执行。当然&#xff0c;这种办法最大的弊端是Apache日志肯定会过大&#xff0c;回应的时候当然会超时什…

信息系统开发内容

1.按照用于质量管理的能力成熟度模型&#xff08;CMM&#xff09;描述系统开发过程的动机。 2.区分系统生命周期和系统开发方法 3.描述系统开发的10个基本原理 4.定义问题、机会和指示——系统开发项目的能力 5.描述用于把问题、机会和指示进行分类的PIECES框架 6.描述系统开发…

jee neow_JEE7:展望新时代

jee neow计划于2012年下半年发布的Java EE 7预计的JSR都已启动并正在运行。 Java EE 7发行版是日期驱动的&#xff0c;它将反映该行业迁移到云中时不断变化的需求&#xff1a;任何未准备就绪的内容将推迟到Java EE 8中使用 。 这是Java EE 7平台中不同规范的关键功能的更新和摘…

Linux怎么更改声音板卡顺序,51CTO博客-专业IT技术博客创作平台-技术成就梦想

SUN M8000主机 IOU板卡硬件更换一、故障现象1.日志分析XSCF> showstatus*IOU#0 Status:Degraded;XSCF> showlogs -v errorDate: May 24 20:44:22 CST 2019 Code: 80002000-33010000-0167058a00000000Status: Alarm Occurred: May 24 20:44:20.367 C…

Class.getResource和ClassLoader.getResource的区别分析

原文&#xff1a;http://swiftlet.net/archives/868 在Java中获取资源的时候&#xff0c;经常用到Class.getResource和ClassLoader.getResource&#xff0c;本文给大家说一下这两者方法在获取资源文件的路径差异。Class.getResource(String path)path不以/开头时&#xff0c;默…

设计模式的Java 8 Lambda表达式–命令设计模式

在本博客中&#xff0c;我将说明如何使用Java 8 Lambda表达式以函数式编程方式实现命令模式 。 命令模式的目的是将请求封装为对象&#xff0c;从而为具有不同请求&#xff0c;队列或日志请求的客户端参数化&#xff0c;并支持相应的操作。 命令模式是一种编写通用代码的方法&a…

凝思linux系统显卡设置,TaiShan服务器安装凝思操作系统Linx6.0.90并设置独立显卡WX2100输出...

TaiShan服务器安装凝思操作系统Linx6.0.90并设置独立显卡WX2100输出环境准备&#xff1a;TaiShan 2280服务器&#xff0c;凝思操作系统Linx6.0.90 arm64&#xff0c;WX2100显卡&#xff0c;WX2100显卡固件和驱动安装包第1步&#xff0c;上电服务器&#xff0c;登录BMC输入用户名…

JMeter3.0_插件管理

JMeter Plugins 一直以来&#xff0c;JMeter Plugins为我们提供了很多高价值的JMeter插件&#xff0c;比如: 用于服务器性能监视的PerfMon Metrics Collector用于建立压力变化模型的Stepping Thread Group用于Json解析的JSON Path Extractor用于展示响应时间曲线的Response Tim…

linux update语句,关于Update语句的调整(5-1)

调整方法二&#xff1a;建立临时表&#xff0b;Merge(&#xff11;)1.调整方法二&#xff1a;建立临时表&#xff0b;Merge通过建立临时表保存中间结果并结合merge语句的方法对语句进行调整。背景知识简介l临时表简介数据库中的所有会话均可以访问临时表&#xff0c;但只有插入…

JavaWeb总结(四)

使用Servlet发送服务器端响应信息 Servlet API中定义一个专门的接口类javax.servlet.http.HttpServletResponse用于创建HTTP响应&#xff0c;包括HTTP协议的状态行、响应头以及消息体&#xff1b; HTTP响应示例 设置响应状态行 - 状态行分为HTTP协议、状态码和状态描述三个部分…

java ee开发环境_设置Java EE 6开发环境

java ee开发环境本教程简要说明了如何设置典型的环境来开发基于Java EE 6的应用程序。 除了可以正常工作的Windows XP客户端具有足够的CPU能力和内存外&#xff0c;本教程没有其他先决条件。 在教程中&#xff0c;我们将需要安装以下组件&#xff1a; Java 6 JDK更新26 适用于…

学生成绩管理系统简单c语言源代码,c语言学生成绩管理系统源代码

好用#include#include#includetypedef struct stu{char sz_Name[20]; char sz_ID[11]; char sz_Class[10]; float r_Score[3];}student;#define STU_MAXSIZE 60int i_stuSize;student stu[STU_MAXSIZE];/*显示主菜单*/void Dis_Main_Menu(){printf("\n 学生成绩管理系统 \…

JavaWeb前端:HTML5 简介

简单了解HTML5知识转载于:https://www.cnblogs.com/vivian-test/p/5949773.html

c语言程序运行结果怎么看,帮忙看看我这个C语言程序有什么错误,运行结果不正确...

C语言的最大特点是&#xff1a;功能强、使用方便灵活。C编译的程序对语法检查并不象其它高级语言那么严格&#xff0c;这就给编程人员留下“灵活的余地”&#xff0c;但还是由于这个灵活给程序的调试带来了许多不便&#xff0c;尤其对初学C语言的人来说&#xff0c;经常会出一些…

JSF 2.2在30秒内创建一个自定义Hello World组件

让我们直接跳到很酷的东西上&#xff0c;说在JSF 2.0中&#xff0c;通过在Facelet标记库&#xff08; *taglib.xml &#xff09;中对其进行配置&#xff0c;使页面作者可以使用自定义组件。 此外&#xff0c;当将组件映射到JAR中时&#xff0c;需要在web.xml一个特殊条目以指向…

[ACM训练] ACM中巧用文件的输入输出来改写acm程序的输入输出 + ACM中八大输入输出格式...

ACM中巧用文件的输入输出来改写acm程序的输入输出 经常有见大神们使用文件来代替ACM程序中的IO&#xff0c;尤其是当程序IO比较复杂时&#xff0c;可以使自己能够更专注于代码的测试&#xff0c;而不是怎样敲输入。 C/C代码中&#xff1a; 使用 stdio.h 中包含的另一个函…

中断按键c语言程序设计,单片机C语言代码:外部中断,按下中断按键LED不亮,LED1正常亮...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼* 名称&#xff1a;外部中断* 日期&#xff1a;2013-9-10* 晶振:11.0592MHZ******************************************************************/#include //包含头文件&#xff0c;对IO进行定义&#xff0c;可以选中后右击&…

状态机复合状态 怎么写代码_状态不属于代码

状态机复合状态 怎么写代码Web应用程序中的“状态”是什么&#xff1f; 它是要存储的数据&#xff08;与目的地无关—内存&#xff0c;数据库&#xff0c;文件系统&#xff09;。 应用程序本身不得在代码中存储任何状态。 这意味着您的类应该只包含带有无状态对象的字段。 换句…

c语言均值滤波程序,均值滤波C语言代码实现的一种简单方式

计算均值滤波时&#xff0c;需要每次求数组的和&#xff0c;再求均值&#xff0c;一般先放入一个数组&#xff0c;循环移出最后一个旧的值循环移入新的值一般原来的做法/******************************************************************************//*** param[in] data[…