第 3 部分 · 应用开发实战
Web 服务器基础
Web 服务器基础
使用 Racket 的内置 Web 服务器框架构建 HTTP 服务。
启动最简单的服务器
Racket 自带了 web-server 库,无需额外安装:
#lang racket (require web-server/servlet web-server/servlet-env) ;; 定义请求处理器 (define (start req) (response/xexpr `(html (head (title "Hello Racket Web")) (body (h1 "Hello, Web!") (p "这是我的第一个 Racket Web 应用。"))))) ;; 启动服务器 (serve/servlet start #:launch-browser? #t #:port 8080 #:servlet-path "/")
运行这段代码,Racket 会启动一个 Web 服务器并在浏览器中打开 http://localhost:8080。
路由处理
使用 dispatch/servlet 实现 URL 路由:
#lang racket (require web-server/servlet web-server/servlet-env web-server/dispatch) ;; 路由处理器 (define (home-page req) (response/xexpr `(html (head (title "首页")) (body (h1 "欢迎来到首页"))))) (define (about-page req) (response/xexpr `(html (head (title "关于")) (body (h1 "关于我们"))))) (define (user-page req username) (response/xexpr `(html (head (title ,(format "用户: ~a" username))) (body (h1 ,(format "你好, ~a!" username)))))) ;; 定义路由 (define-values (dispatch url) (dispatch-rules [(("about")) about-page] [(("user") (string-arg)) user-page] [else home-page])) ;; 启动 (serve/servlet dispatch #:port 8080 #:servlet-regexp #rx"")
处理 GET 请求参数
(require web-server/request) (define (search-page req) (define binds (request-bindings/raw req)) (define query (bindings-assq #"q" binds)) (response/xexpr `(html (head (title "搜索结果")) (body (h1 "搜索") (p ,(if query (format "你搜索了: ~a" (bytes->string/utf-8 (binding:form-value query))) "请输入搜索关键词"))))))
处理 POST 请求
(define (handle-form req) (define binds (request-bindings/raw req)) (define name (bindings-assq #"name" binds)) (define email (bindings-assq #"email" binds)) (response/xexpr `(html (head (title "表单提交结果")) (body (h1 "提交成功") (p ,(format "姓名: ~a" (bytes->string/utf-8 (binding:form-value name)))) (p ,(format "邮箱: ~a" (bytes->string/utf-8 (binding:form-value email))))))))
JSON API
使用 json 库构建 RESTful API:
(require json) (define (api-users req) (response/json #hasheq((users . (#hasheq((id . 1) (name . "Alice")) #hasheq((id . 2) (name . "Bob"))))))) ;; 辅助函数:返回 JSON 响应 (define (response/json data) (response/full 200 #"OK" (current-seconds) APPLICATION/JSON-MIME-TYPE '() (list (jsexpr->bytes data))))
静态文件服务
(require web-server/dispatchers/dispatch-static) ;; 配置静态文件目录 (define static-dispatcher (static-files-path "/path/to/static/files"))
部署
Racket Web 应用可以通过多种方式部署:
| 方式 | 说明 |
|---|---|
| 独立运行 | racket app.rkt 直接启动 |
| Docker | 打包为容器镜像 |
| Systemd | 配置为系统服务 |
| 反向代理 | 配合 Nginx 使用 |
;; 生产环境配置 (serve/servlet app #:port (string->number (or (getenv "PORT") "8080")) #:listen-ip #f #:servlet-regexp #rx"")