Clojure“DSL”编程

发布于 2024-12-08 21:55:26 字数 1172 浏览 4 评论 0原文

我正在使用 Clojure 和 RESTEasy 设计 JAX-RS REST 服务器。

据我了解,用 Lisp 系列语言编写的应用程序比用“传统”命令式语言编写的应用程序更多地构建为“特定于领域的语言”。应用程序从下到上设计为越来越“精致”的功能,直到在“顶层”级别,应用程序变成一系列对非常高级函数的函数调用。

我正在尝试为我的 REST 服务器执行此操作,从服务 URL 请求(GET、POST、PUT、DELETE)的资源类开始。

这是我的第一个资源:

(ns com.example.server.resources.buildtime
  (:import [javax.ws.rs CookieParam GET Produces Path]
           [javax.ws.rs.core Context Cookie NewCookie Response UriInfo]
           [org.jboss.resteasy.annotations.providers.jaxb Formatted]))

(definterface BuildTime
  (getBuildTime [^javax.ws.rs.core.UriInfo info
                 ^javax.ws.rs.core.Cookie security-cookie]))

(deftype
  ^{Formatted true}
  BuildTimeResource []
  BuildTime
  (^{GET true
     Path "/buildtime"
     Produces ["application/json"]}
    getBuildTime
    [this info security-cookie]
    (.. (Response/ok "20111009") build)))

当使用 GET http 方法在 URL“/buildtime”调用时,该资源以字符串形式返回服务器构建时间(包含在 JSON 包中)。

我将编写更多这样的资源类和封闭方法(大多数类将有多个方法),每个类都有一个 definterface 和一个 deftype。这似乎是宏的完美用途。

我正在征求有关如何将其作为 DSL 来完成的建议。人们如何从 DSL 角度进行思考?

I am designing a JAX-RS REST Server using Clojure and RESTEasy.

It is my understanding that applications written in Lisp-family languages are, more than those in "traditional" imperative languages, built up as "domain-specific languages". The application is designed from the bottom-up as more and more "refined" functions until, at the "top" level, the application becomes a series of function calls to very high-level functions.

I am trying to do this for my REST server, starting with the resource classes that service URL requests (GET, POST, PUT, DELETE).

Here is my first resource:

(ns com.example.server.resources.buildtime
  (:import [javax.ws.rs CookieParam GET Produces Path]
           [javax.ws.rs.core Context Cookie NewCookie Response UriInfo]
           [org.jboss.resteasy.annotations.providers.jaxb Formatted]))

(definterface BuildTime
  (getBuildTime [^javax.ws.rs.core.UriInfo info
                 ^javax.ws.rs.core.Cookie security-cookie]))

(deftype
  ^{Formatted true}
  BuildTimeResource []
  BuildTime
  (^{GET true
     Path "/buildtime"
     Produces ["application/json"]}
    getBuildTime
    [this info security-cookie]
    (.. (Response/ok "20111009") build)))

This resource returns the server build time as a String (enclosed in a JSON package) when called at the URL "/buildtime" with the GET http method.

I will be writing many more of the these resource classes and enclosed methods (most classes will have more than one method), each with a definterface and a deftype. This seems like a perfect use for macros.

I am soliciting suggestions for how this might be done as a DSL. How does one go about thinking in terms of DSLs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

英雄似剑 2024-12-15 21:55:26

如果我要这样做,我想我会从为 RESTEasy 创建一个环形适配器开始。完成此操作后,Compojure 将知道如何以与 RESTEasy 配合使用的方式处理和响应 http 请求。以下是一些可帮助您入门的信息。

Ring 是一个 clojure 库,它以标准方式表示 http 请求和响应。 此处详细介绍了该标准。

它的工作原理是从各种库(即 jetty、netty、finagle)接收 http 请求并将其转换为标准表示形式。然后它将请求交给请求处理程序(通常是使用 Compojure 定义的)。然后处理程序返回一个响应(也在上述规范中定义)。这个响应被ring back翻译成jetty、netty等可以理解的形式。

该转换由环适配器完成。 此处列出了一些,ring 附带了一个用于 jetty 的适配器也许您可以使用其中之一作为创建 RESTEasy 适配器的模板。完成后,您可以以标准方式使用 compojure。

Ring 和 compojure 是如何创建 DSL 的很好的例子。与所有优秀的 DSL 一样,它简化了在其问题域(本例中为 HTTP 服务器)中创建解决方案的过程。它们是如何根据 DSL 进行思考的绝佳示例。如果您研究它们,您将能够顺利地从 DSL 角度进行思考。

If I were undertaking this, I think I would start by creating a ring adapter for RESTEasy. After this is done, Compojure will know how to handle and respond to http requests in a way that works with RESTEasy. Here's some information to help you get started.

Ring is a clojure library that represents http requests and responses in a standard way. This standard is detailed here.

It works by receiving an http request from any of a variety of libraries (ie. jetty, netty, finagle) and translating it into the standard representation. It then hands the request off to a request handler (often this is defined using Compojure). The handler then returns a response (also defined in the above spec). This response is translated by ring back into a form that jetty, netty, etc. can understand.

This translation is done by ring adapters. There are a few listed here, and ring comes with an adapter for jetty built in. Maybe you can use one of them as a template for creating a RESTEasy adapter. After you've done that you can use compojure in the standard way.

Ring and compojure are great examples of how to create a DSL. Like all good DSLs, it simplifies creating solutions in its problem domain (HTTP servers in this case). They are great examples of how to think in terms of DSLs. If you study them, you'll be well on your way towards thinking in terms of DSLs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文