RESTful服务框架:Restlet与Django的应用实践
在后端开发中,构建RESTful服务是一项重要的任务,而Restlet和Django这两个框架为我们提供了强大的支持。下面将详细介绍它们在构建社交书签服务中的应用。
Restlet框架
Restlet框架能够将传入的HTTP请求路由到特定的资源类及其方法,并根据客户端需求构建资源表示。客户端通过内容协商表达需求,Restlet会查看
Accept
头的值,确定最合适的“变体”表示。
以下是一个构建用户表示的示例代码:
@Override
public Representation getRepresentation(Variant variant) {
Representation result = null;
if (variant.getMediaType().equals(MediaType.TEXT_PLAIN)) {
// Creates a text representation
StringBuilder sb = new StringBuilder();
sb.append("------------\n");
sb.append("User details\n");
sb.append("------------\n\n");
sb.append("Name: ").append(this.user.getFullName()).append('\n');
sb.append("Email: ").append(this.user.getEmail()).append('\n');
result = new StringRepresentation(sb);
}
return result;
}
其他资源和
UserResource
的其他HTTP方法也以类似方式工作。例如,用户的
PUT
请求会路由到
UserResource.handlePut
。
编译、运行和测试
Application
类实现了运行社交书签服务的HTTP服务器,需要包含以下JAR文件的类路径:
-
org.restlet.jar
-
com.noelios.restlet.jar
-
com.noelios.restlet.ext.net.jar
-
org.simpleframework_3.1/org.simpleframework.jar
-
com.noelios.restlet.ext.simple_3.1.jar
-
com.db4o_6.1/com.db4o.jar
编译所有示例文件后,运行
org.restlet.example.book.rest.ch7.Application
作为服务器端点。
ApplicationTest
类提供了服务的客户端接口,可通过HTTP的统一接口添加和删除用户及书签。运行
ApplicationTest.class
时,根据参数数量有不同的使用方式:
- 删除用户:
userName, password
- 删除书签:
userName, password, URI
- 添加新用户:
userName, password, "full name", email
- 添加新书签:
userName, password, URI, shortDescription, longDescription, restrict[true / false]
完成上述操作后,可在标准Web浏览器中访问相应的URI,查看用户书签的HTML表示。
Restlet项目在2007年初发布了最终的1.0版本,目前1.0版本处于维护阶段,新的1.1分支已经启动。未来计划包括将Restlet API提交给Java社区进程(JCP)进行标准化。
Django框架
Django是一个用于在Python中开发Web应用程序和Web服务的框架,其设计与Rails相似,但简化假设较少。下面将展示如何在Django中实现社交书签服务。
创建数据模型
大多数Django开发者从设计数据模型开始,这对应于通用ROA过程的第一步“确定数据集”。模型通常使用Django的对象关系映射(ORM)工具存储在关系数据库中。以下是一个Django模型的示例:
from datetime import datetime
from django.db import models
from django.contrib.auth.models import User
class Tag(models.Model):
name = models.SlugField(maxlength=100, primary_key=True)
class Bookmark(models.Model):
user = models.ForeignKey(User)
url = models.URLField(db_index=True)
short_description = models.CharField(maxlength=255)
long_description = models.TextField(blank=True)
timestamp = models.DateTimeField(default=datetime.now)
public = models.BooleanField()
tags = models.ManyToManyField(Tag)
这段代码有一些微妙之处和强大的功能:
- 使用内置的Django用户模型,它能处理大部分身份验证和授权。
- Django没有与Rails的
acts_as_taggable
插件直接对应的功能,因此在
Bookmark
定义的最后一行定义了
Bookmark
和
Tag
之间的多对多关系。
- 将标签名称定义为
SlugField
,可自动限制标签名称为可出现在URI中的名称。
- 大多数在Rails模式中显式创建的数据库索引由Django自动添加,但需要在
url
字段上显式指定
db_index=True
。
定义资源并分配URI
社交书签应用的Rails实现暴露了11个资源,这里仅实现其中4个:
- 单个书签
- 用户的书签列表
- 用户用特定标签标记的书签列表
- 用户使用的标签列表
Django要求从一开始就设计URI,其哲学是URI是Web应用程序用户界面的重要组成部分,不应自动生成。以下是修改后的URI结构:
- 所有URI以斜杠结尾,符合Django开发者的习惯。
- 使用更紧凑的
/users/{username}/{URL}/
来表示书签。
- 使用
/users/{username}/
来暴露“书签列表”资源。
- 通过向
/users/{username}/{URI}/
发送
PUT
请求来创建新书签。
使用Django的URI配置文件
urls.py
将这些URI映射到资源:
from django.conf.urls.defaults import *
from bookmarks.views import *
urlpatterns = patterns('',
(r'^users/([\w-]+)/$', bookmark_list),
(r'^users/([\w-]+)/tags/$', tag_list),
(r'^users/([\w-]+)/tags/([\w-]+)/', tag_detail),
(r'^users/([\w-]+)/(.*)', BookmarkDetail()),
)
urls.py
将传入的URI(表示为正则表达式)映射到处理请求的函数。
实现资源为Django视图
Django对模型 - 视图 - 控制器模式的解释与Rails不同,在Django中,实现资源行为的代码放在视图中。
以下是“书签列表”视图的示例代码:
from bookmarks.models import Bookmark
from django.contrib.auth.models import User
from django.core import serializers
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
def bookmark_list(request, username):
u = get_object_or_404(User, username=username)
marks = Bookmark.objects.filter(user=u, public=True)
json = serializers.serialize("json", marks)
return HttpResponse(json, mimetype="application/json")
这个实现比较简单,但会返回用户的所有书签,消耗数据库资源和带宽。改进后的实现支持条件
GET
:
import datetime
from bookmarks.models import Bookmark
from django.contrib.auth.models import User
from django.core import serializers
from django.http import *
from django.shortcuts import get_object_or_404
import dateutil.parser
from dateutil.tz import tzlocal, tzutc
def bookmark_list(request, username):
u = get_object_or_404(User, username=username)
lookup = dict(user=u, public=True)
lm = request.META.get("HTTP_IF_MODIFIED_SINCE", None)
if lm:
try:
lm = dateutil.parser.parse(lm)
except ValueError:
lm = None
else:
lookup['timestamp__gt'] = lm.astimezone(tzlocal())
marks = Bookmark.objects.filter(**lookup)
if lm and marks.count() == 0:
return HttpResponseNotModified()
json = serializers.serialize("json", marks)
response = HttpResponse(json, mimetype="application/json")
now = datetime.datetime.now(tzutc())
response["Last-Modified"] = now.strftime("%a, %d %b %Y %H:%M:%S GMT")
return response
“书签”资源需要处理
GET
、
PUT
和
DELETE
三种HTTP方法。以下是
BookmarkDetail
类的实现:
class BookmarkDetail:
def __call__(self, request, username, bookmark_url):
self.request = request
self.bookmark_url = bookmark_url
self.user = get_object_or_404(User, username=username)
try:
callback = getattr(self, "do_%s" % request.method)
except AttributeError:
allowed_methods = [m.lstrip("do_") for m in dir(self) if m.startswith("do_")]
return HttpResponseNotAllowed(allowed_methods)
self.authenticate()
return callback()
def authenticate(self):
auth_info = self.request.META.get("HTTP_AUTHORIZATION", None)
if auth_info and auth_info.startswith("Basic "):
basic_info = auth_info.lstrip("Basic ")
u, p = auth_info.decode("base64").split(":")
self.authenticated_user = authenticate(username=u, password=p)
else:
self.authenticated_user = None
def forbidden(self):
response = HttpResponseForbidden()
response["WWW-Authenticate"] = 'Basic realm="Bookmarks"'
return response
def do_GET(self):
bookmark = get_object_or_404(Bookmark, user=self.user, url=self.bookmark_url)
if bookmark.public == False and self.user != self.authenticated_user:
return self.forbidden()
json = serializers.serialize("json", [bookmark])
return HttpResponse(json, mimetype="application/json")
def do_PUT(self):
if self.user != self.authenticated_user:
return self.forbidden()
try:
deserialized = serializers.deserialize("json", self.request.raw_post_data)
put_bookmark = list(deserialized)[0].object
except (ValueError, TypeError, IndexError):
response = HttpResponse()
response.status_code = 400
return response
bookmark, created = Bookmark.objects.get_or_create(user=self.user, url=self.bookmark_url)
for field in ["short_description", "long_description", "public", "timestamp"]:
new_val = getattr(put_bookmark, field, None)
if new_val:
setattr(bookmark, field, new_val)
bookmark.save()
json = serializers.serialize("json", [bookmark])
response = HttpResponse(json, mimetype="application/json")
if created:
response.status_code = 201
response["Location"] = "/users/%s/%s" % (self.user.username, bookmark.url)
return response
def do_DELETE(self):
if self.user != self.authenticated_user:
return self.forbidden()
bookmark = get_object_or_404(Bookmark, user=self.user, url=self.bookmark_url)
bookmark.delete()
response = HttpResponse()
response.status_code = 200
return response
综上所述,Restlet和Django在构建RESTful服务方面都有各自的优势。Restlet提供了强大的请求路由和资源表示构建功能,而Django则在数据模型设计和URI自定义方面表现出色。开发者可根据具体需求选择合适的框架。
RESTful服务框架:Restlet与Django的应用实践
框架对比分析
为了更清晰地了解Restlet和Django在构建RESTful服务时的差异,下面通过表格进行对比:
| 对比项 | Restlet | Django |
| — | — | — |
| 语言 | Java | Python |
| 数据存储 | 使用db4o对象数据库 | 通常使用关系数据库,通过ORM工具操作 |
| URI设计 | 未特别强调,路由功能实现请求到资源类和方法的映射 | 强调URI设计,认为是Web应用用户界面重要部分,需手动设计 |
| 资源表示 | 通过
getRepresentation
等方法构建,支持内容协商 | 使用序列化API将数据库行转换为JSON或XML等表示 |
| 身份验证 | 未详细提及示例中的身份验证方式 | 提供内置用户模型处理身份验证和授权,可实现HTTP基本身份验证 |
从这个表格可以看出,Restlet更侧重于Java环境下的请求处理和资源表示,而Django则在Python环境中,对数据模型和URI设计有更深入的要求。
实际应用场景选择
在实际开发中,选择Restlet还是Django取决于多个因素,下面通过一个mermaid流程图来展示选择的决策过程:
graph LR
A[项目需求] --> B{使用语言偏好}
B -->|Java| C{对数据库类型要求}
C -->|对象数据库| D[选择Restlet]
C -->|关系数据库| E{对URI设计的重视程度}
E -->|需精细设计| F{是否熟悉Python}
F -->|是| G[选择Django]
F -->|否| D
E -->|自动生成或简单设计| D
B -->|Python| G
-
项目规模和复杂度
:
- 如果是小型项目,且团队对Java比较熟悉,Restlet的简洁性和快速搭建能力可能更合适。例如,开发一个简单的内部API服务,使用Restlet可以快速实现功能。
- 对于大型项目,尤其是涉及复杂数据模型和多样化URI设计的项目,Django的强大功能和灵活性更能满足需求。比如开发一个大型的社交网站,需要处理大量用户数据和复杂的资源关系,Django的ORM和URI设计能力可以更好地应对。
-
团队技术栈
:
- 若团队主要使用Java技术栈,Restlet的无缝集成可以减少学习成本。
- 而团队熟悉Python,Django则是更自然的选择,其丰富的库和生态系统可以提高开发效率。
未来发展趋势
Restlet和Django都有着良好的发展前景:
- Restlet :计划将API提交给JCP进行标准化,这意味着未来Restlet可能会成为Java领域RESTful服务开发的标准之一。同时,随着JSR 311等更高层次API的发展,Restlet可以与之互补,为开发者提供更便捷的开发体验。
- Django :作为Python领域的优秀框架,其社区活跃,不断有新的功能和改进推出。随着Python在数据科学、机器学习等领域的广泛应用,Django也可以在这些领域的Web服务开发中发挥重要作用。
总结
Restlet和Django都是构建RESTful服务的优秀框架,它们各自有着独特的优势和适用场景。Restlet在Java环境中提供了强大的请求路由和资源表示能力,而Django则在Python环境中强调数据模型设计和URI的手动定制。开发者在选择时,应根据项目需求、团队技术栈和未来发展规划等因素综合考虑,以选择最适合的框架来构建高效、稳定的RESTful服务。
希望通过本文的介绍,能帮助开发者更好地理解Restlet和Django,在实际开发中做出更明智的选择。
超级会员免费看
334

被折叠的 条评论
为什么被折叠?



