我希望组合器解析器
,(http://debasishg.blogspot.com/2008/04/external-dsls-made-easy-with-scala.html),将致力于设计来处理使用 Scalatra 实现的 REST 服务的路由规则,(http://tutorialbin.com/tutorials/80408/infoq-scalatra-a-sinatra-like-web-framework-for-scala)。
此 REST 服务将充当代理,以便外部应用程序可以访问防火墙内的服务,因为它将具有额外的安全层,可以根据每个 REST 服务的业务需求进行自定义。
因此,如果一个人想要访问他们的课程表,那么安全性会比你想查看某人的成绩单要低。
我想要 DSL 中关于去哪里实际获取信息、如何返回信息以及需要什么安全性的规则。
但是,第一个问题是如何动态更改基于 DSL 的 REST 服务的路由规则,因为我正在尝试创建一个不需要大量重新编译来添加新规则的框架,而只需编写适当的内容脚本并让它被处理。
那么,可以使用 Scala 中的组合器解析器来实现 DSL,从而允许 JAX-RS (http://download.oracle.com/javaee/6/tutorial/doc/giepu.html) 动态更改路由?
更新:
我还没有设计这种语言,但这就是我正在尝试做的:
route /transcript using action GET to
http://inside.com/transcript/{firstparam}/2011/{secondparam}
return json encrypt with public key from /mnt/publickey.txt
for /education_cost using action GET combine http://combine.com/SOAP/costeducate with
http://combine.com/education_benefit/2010 with
http://combine.com/education_benefit/2011 return html
这是两种可能的想法,其中将成绩单请求的规则发送到不同的站点,例如在防火墙内,数据被加密并返回。
第二个会更复杂,因为 SOAP 和两个 REST 请求的结果将被组合,并且需要关于如何组合的附加命令,但想法是将所有这些放在可以解析的文件中在飞行中。
如果我使用 Groovy,那么可以为路由生成一些新类,这将消除一些性能影响,但我认为使用 Scala 将是最好的选择,即使我受到了性能影响。
我的希望是制作一个更易于维护的框架,这样新的路由规则就可以由不懂任何 OOP 或函数式语言的人编写,但规范可以使用 Specs
(http://code.google.com/p/specs/),以便功能方面可以确定定期测试他们的要求。
更新2:
当我开始设计时,我可能会直观地理解一些选项,但不知道为什么。今天我意识到 Groovy 可能是一个更好的解决方案,因为我可以使用元编程(http://www.justinspradlin.com/programming/groovy-metaprogramming-adding-behavior-dynamically/),那么我就可以使用 Scala 或 Groovy 动态使用路由被生成。我不确定如何让 Scala 生成这些类(如果它们尚不存在)。
在 Groovy 以及其他一些语言中,如下所示 (http://langexplr.blogspot.com/2008/02/handling-call-to-missing-method-in.html)如果缺少方法,您可以动态生成方法,并且它将从此存在,因此它会丢失一次。
看起来我应该将 Groovy 与 Java 混合起来才能完成这项工作,但结果可能是一些代码在 Scala 中,而另一些代码在 Java 中,用于 REST 服务的路由。
I am hoping that Combinator parsers
, (http://debasishg.blogspot.com/2008/04/external-dsls-made-easy-with-scala.html), will work for a design to process the routing rules for a REST service that is implemented with Scalatra
,(http://tutorialbin.com/tutorials/80408/infoq-scalatra-a-sinatra-like-web-framework-for-scala).
This REST service is to serve as a proxy so external applications can get access to services within the firewall, as it will have additional layers of security that can be customized for the business requirements of each REST service.
So, if a person wants to access their class schedule there will be less security than if you want to look at the transcript of someone.
I would like the rules for where to go to actually get the information, and how to return it, as well as what security is needed, in a DSL.
But, the first problem is how to dynamically change the routing rules for the REST service based on a DSL, as I am trying to create a framework that doesn't require a great deal of recompiling to add new rules, but just write the appropriate scripts and just let it be processed.
So, can a DSL be implemented using the Combinator Parser, in Scala, that will allow JAX-RS (http://download.oracle.com/javaee/6/tutorial/doc/giepu.html) to have dynamically changed routing?
UPDATE:
I haven't designed the language yet, but this is what I am trying to do:
route /transcript using action GET to
http://inside.com/transcript/{firstparam}/2011/{secondparam}
return json encrypt with public key from /mnt/publickey.txt
for /education_cost using action GET combine http://combine.com/SOAP/costeducate with
http://combine.com/education_benefit/2010 with
http://combine.com/education_benefit/2011 return html
These are two possible ideas where rules for a request for a transcript is sent to a different site, such as within a firewall, and the data is encrypted and returned.
The second would be more complicated in that the results of a SOAP and two REST requests will be combined, and there would need to be additional commands on how this is combined, but the idea is to put all of this in files that can be parsed on the fly.
If I used Groovy then some new classes could be generated for the routing, which would remove some performance hits, but I think using Scala would be the best bet, even if I took a performance hit.
My hope is to make a framework that is more maintainable so new routing rules can be written by people that don't know any OOP or functional languages, but the specifications could be written using Specs
(http://code.google.com/p/specs/) so that the functional side could be certain that their requirements are tested on a regular basis.
UPDATE 2:
When I start working on a design I may intuitively understand some options, but not know why. Today I realized that the reason that Groovy may be a better fix for this is that I could then generate the classes for routing, using the metaprogramming (http://www.justinspradlin.com/programming/groovy-metaprogramming-adding-behavior-dynamically/), then I would be able to use Scala or Groovy to dynamically use the routing that was generated. I am not certain how to get Scala to generate the classes if they don't already exist.
In Groovy, as well as some other languages, as shown here (http://langexplr.blogspot.com/2008/02/handling-call-to-missing-method-in.html) if a method is missing you can dynamically generate the method and it will henceforth exist, so it will be missing one time.
It almost seems that I should be mixing Groovy with Java to make this work, but then the result may be that some of the code is in Scala and some in Java, for the routing of REST services.
发布评论
评论(1)
将问题分为两部分:
是的。有些事情无法使用组合器解析器甚至其他类型的解析器来实现。例如,Perl 本身无法被解析(必须对其求值)。组合器解析器对于复杂语言(例如 Scala - 它的编译器不是基于组合器解析器),或者如果您需要顶级性能(例如用于编译数十万行代码的编译器)也不是特别好。
但是,如果您打算走这样的极端,那么选择解析器就不是您的主要问题。对于中等复杂度的 DSL,它们就可以了。
好吧,我不知道 JAX-RS,但如果可以用它来完成动态更改的路由,那么组合器解析器将能够提供所需的任何输入。
编辑
看到你的例子,我认为解析器组合器当然足够了。从他们的结果来看,我希望您可以动态创建 BlueEyes 活页夹——我没有使用过 BlueEyes,所以我不确定它们的动态程度如何。
另一种选择是使用 Lift。 Lift 的绑定器是部分函数,它们可以用所有常用的方式进行组合——
f1 orElse f2
、f1 andThen f2
等。我一开始并不建议这样做因为它最常与会话一起使用,但它有一个 RESTful 模型,我认为是无状态的。我不了解Scalatra,所以我不知道它是否可以适应这一点。
Splitting the question in two parts:
Yes. There are things that cannot be implemented using a combinator parser, or even other kinds of parser. For instance, Perl itself cannot be parsed (it must be evaluated). And combinator parsers are also not particularly good for complex languages (such as Scala -- its compiler is not based on combinator parsers), or if you demand top performance (such as the compilers used to compile hundreds of thousands of lines of code).
If, however, you plan to go to such extremes, choosing the parser is not going to be your main problem. For DSLs of average complexity, they'll do just fine.
Well, I don't know JAX-RS, but if dynamically changed routing can be done with it, then combinators parsers will be able to provide whatever input is needed.
EDIT
Seeing your example, I think parser combinators are certainly enough. From their results, I expect you could dynamically create BlueEyes binders -- I haven't used BlueEyes, so I'm not sure how dynamic they are.
Another alternative would be go with Lift. Lift's binders are partial functions, and they can be combined in all the usual ways --
f1 orElse f2
,f1 andThen f2
, etc. I didn't suggest it at first because it is most often used with sessions, but it has a RESTful model which, I think, is stateless.I don't know Scalatra, so I don't know if it would be adaptable to this or not.