当前,我们正在为系统开发API,并且某些资源可能具有不同的标识符。例如,有一个名为的资源orders
,该资源可能具有唯一的订单号,也具有唯一的ID。目前,我们只有id的URL,这些URL是:
GET /api/orders/{id}
PUT /api/orders/{id}
DELETE /api/orders/{id}
Run Code Online (Sandbox Code Playgroud)
但是现在我们还需要使用订单号的可能性,通常会导致:
GET /api/orders/{orderNumber}
PUT /api/orders/{orderNumber}
DELETE /api/orders/{orderNumber}
Run Code Online (Sandbox Code Playgroud)
显然,这是行不通的,因为id和orderNumber都是数字。
我知道也有一些类似的问题,但是它们并不能帮助我,因为答案并不合适,或者他们的方法不是真正令人烦恼或难以理解的(对于我们以及使用API的开发人员而言)。此外,问题和答案的年龄部分超过7年。
仅举几例:
1.使用查询参数
一个建议使用查询参数,例如
GET /api/orders/?orderNumber={orderNumber}
Run Code Online (Sandbox Code Playgroud)
我认为有很多问题。首先,这是订单集合的过滤器,因此结果也应该是列表。但是,唯一的订单号只有一个订单,这有点令人困惑。其次,我们使用这种过滤器来搜索/过滤订单的子集。此外,查询参数是某种第二类参数,但在这种情况下应为第一类。如果我的对象不存在,这甚至是一个问题。通常GET /api/orders/?orderNumber=1234
,如果顺序1234不存在,则get将返回404(未找到),但是a 将为空数组。
2.使用前缀
一些公共API使用某种区分符来区分不同类型,例如:
GET /api/orders/id_1234
GET /api/orders/ordernumber_367652
Run Code Online (Sandbox Code Playgroud)
这对于他们的方法是有效的,因为id_1234
和ordernumber_367652
是它们的真正唯一标识符,其他资源也返回它们。但是,这将导致这样的响应对象:
{
"id": "id_1234",
"ordernumber": "ordernumber_367652"
//...
}
Run Code Online (Sandbox Code Playgroud)
这不是很干净,因为类型(标识或订单号)已建模两次。而且,除了更改所有标识符和响应对象的问题外,如果您想搜索所有大于67363的订单号(因此,还存在字符串/数字冲突),这将令人困惑。如果响应未将类型添加为前缀,则用户必须为某些请求添加此类型,这也将非常令人困惑(有时您必须添加此类型,有时不添加...)
3.使用动词
例如Twitter就是这样的:其URL以结尾show.json
,因此您可以像这样使用它:
GET /api/orders/show.json?id=1234
GET /api/orders/show.json?number=367652
Run Code Online (Sandbox Code Playgroud)
我认为,这是最糟糕的解决方案,因为它不会带来麻烦。此外,它还存在我在查询参数方法中提到的一些问题。
4.使用子资源
有人建议像子资源一样对此建模,例如:
GET /api/orders/1234
GET /api/orders/id/1234 //optional
GET /api/orders/ordernumber/367652
Run Code Online (Sandbox Code Playgroud)
我喜欢这种方法的可读性,但是我认为的意思/api/orders/ordernumber/367652
是“获取(仅)订单号367652”,而不是订单。最后,这打破了一些最佳做法,例如使用复数形式和仅使用实际资源。
所以最后,我的问题是:我们错过了什么吗?还有其他方法,因为我认为这不是一个罕见的问题吗?
尝试了很多不同的方法后,没有任何方法可以帮助我.
最相似的问题是这一个如何在angularjs中阅读pdf流
我有一个AngularJS应用程序,它向我的PHP文件发送请求以生成PDF文件.我的控制器具有以下功能,我通过ng-click从按钮调用:
$scope.print = function() {
$http({
method : "post",
url : '/pdf/print_processor.php',
data : printdata,
//responseType : 'arraybuffer',
headers : {
'Content-type' : 'application/json'
}
}).success(function(response, status, headers) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
});
}
Run Code Online (Sandbox Code Playgroud)
主要原因是我必须将更多数据发送到PHP文件.printdata变量包含一个超过12 KB的嵌套JSON对象.所以我无法使用普通的GET或通过普通链接传递此数据作为URL的一部分.
请求正在运行,因为我可以直接调用print_processor.php(这给了我PDF),并且我使用相同的方法来创建发送电子邮件.就像上面提到的问题一样,我的回复也包含了pdf本身:
%PDF-1.5
3 0 obj
<</Type /Page
/Parent 1 0 R
/Resources 2 0 R
/Group <</Type /Group /S /Transparency /CS /DeviceRGB>>
/Contents 4 0 R>>
endobj
4 0 obj
<</Filter /FlateDecode …
Run Code Online (Sandbox Code Playgroud) 在我的 git repo 中,应用程序位于根文件夹中,例如
.gitignore
pom.xml
data/
src/
README.md
...
Run Code Online (Sandbox Code Playgroud)
由于应用程序的重新设计(其中一部分是引入父 pom),我想将所有内容移动到一个子文件夹中,例如称为 system,然后创建第二个文件夹(例如称为 api):
system/
.gitignore
pom.xml
data/
src/
README.md
...
api/
src
...
...
Run Code Online (Sandbox Code Playgroud)
将所有内容移动到的最佳方式是什么system
?根目录中每个文件/目录的 git mv 是否足够?
我们在 Angular 10 项目中使用 ngZorro。现在我想打开抽屉(https://ng.ant.design/components/drawer/en)来显示表单。该场景是例如产品的列表,单击其中一个产品时,应在抽屉中打开它的表单。
我使用 NzDrawerService 创建抽屉,但无法设置任何页脚(称为 nzFooter)。
例如,有一个 ProductFormComponent,因此在我的 ProductService.ts 中我可以调用:
openForm(){
const drawerRef = this.drawerService.create({
nzTitle: 'My Title',
nzContent: ProductFormComponent
});
drawerRef.open()
}
Run Code Online (Sandbox Code Playgroud)
现在,还有一个预定义页脚 ( nzFooter?: string | TemplateRef<{}>
) 的选项,我想在其中添加保存和取消按钮。现在的问题是:我如何在这里获取 TemplateRef,因为该函数是在服务中而不是在组件中调用的?
我们有一个REST API,用于一些评论.目前,最有趣的URI是:
GET /products/1/comments // get all comments of product 1
GET /products/1/comments/5 // get the 5th comment of product 1
GET /products/1/comments/5/user // get the user of the 5th comment
GET /products/1/comments/latest // get the latest comment of product 1
GET /products/1/comments/latest/user // get the user of the latest comment
Run Code Online (Sandbox Code Playgroud)
此外,您还可以直接访问评论
GET /comments/987 // get the comment with id 987
GET /comments/987/user // get the user of comment with id 987
Run Code Online (Sandbox Code Playgroud)
所以,我们有两个@RestController
:
@RestController
@RequestMapping("/products/{productId}")
public class ProductsCommentsResource …
Run Code Online (Sandbox Code Playgroud) api-design ×2
json ×2
rest ×2
angular ×1
angularjs ×1
git ×1
http ×1
java ×1
javascript ×1
pdf ×1
php ×1
spring ×1
spring-mvc ×1
typescript ×1