动态编译Scala类以实现Web服务

时间:2014-04-22 12:50:17

标签: web-services scala rest on-the-fly

我正在努力学习如何动态添加一些web服务。我正在使用Scalatra作为Web服务框架。

我希望允许开发人员能够更改身份验证,例如,不要使用硬编码凭据,而是使用数据库或密码文件或他们需要的任何内容。

我还想让他们在servlet中添加新的webservices。

所以,我想要做的是在引导代码中加载它并重新编译该类然后使用该版本。

我看过这个,但我需要重新编译整个课程,而不是片段。

Generating a class from string and instantiating it in Scala 2.10

这是我尝试过的,但是我添加了一个“/ help”webservice,但是找不到它,所以新类还没有被使用。

class ScalatraBootstrap extends LifeCycle {

  override def init(context: ServletContext) {

    val sourceDir = new java.io.File("C:/Temp/MyServlet.scala")
    val sse = ScalaScriptEngine.onChangeRefresh(sourceDir)
    sse.refresh
    println("*** - " + sse.compilationStatus.startTime + "  " + sse.compilationStatus.stopTime)

    context.mount(sse.get[MyServlet]("test.proj.MyServlet"), "/*")

我目前正在使用scalascriptengine(https://code.google.com/p/scalascriptengine/)。

那么,当它可能在同一个文件中有案例类,注释和对象类时,如何动态地重新编译web服务的类文件?

我想知道我是否需要在Groovy中使用web服务,但我希望保持其功能。

更新

我首先考虑过插件,但遇到了如何以这种方式添加新的web服务的问题,可能是Scalatra不是正确的选择,我可能需要更改我的REST服务框架

最终,我希望能够在不必重新启动应用程序的情况下即时更改Web服务,并且重新编译源代码将允许这样做。

2 个答案:

答案 0 :(得分:1)

实现插件的可供性并不是太难,至少在相当简单的情况下。基本要素是:

  • 定义插件实现义务的特征或抽象类。
  • 一种将插件代码放到类路径上的方法。或者,如果您熟悉使用类加载器,则可以动态执行。我对此没有多少经验。
  • 一旦有了java.lang.Class[P <: PlugInType]的实例,只要你不需要构造函数参数就可以获得一个实例。
  • 插件特征中的协议,允许插件例如保留顶级URL路径段,从中获取涵盖所有这些路径的Scalatra路径。然后,您通过插件实例分派与该主要路径段匹配的请求。您所要做的就是确保不要让两个插件声明相同的路径,或者如果您有其他方法可以解决它们。

答案 1 :(得分:0)

感谢@RandallSchultz,我找到了一个有效的解决方案。

override def init(context: ServletContext) {

    val sourceDir = new java.io.File("C:/Temp/HelpServlet.scala")
    val sse = ScalaScriptEngine.onChangeRefresh(sourceDir)
    sse.refresh
    println("*** - " + sse.compilationStatus.startTime + "  " + sse.compilationStatus.stopTime)

    context.mount(new MyServlet, "/*")
    context.mount(sse.get("org.myproject.rest.HelpServlet"), "/help/*")

所以当我去&#34; / help / help&#34;我按预期获得了帮助页面,因此添加了新的Web服务。

通过从文件中读取它,我可以在应用程序运行时添加它。