英文:
Jersey HTTP Delete,Put Response Status: 405 (Method Not Allowed)
问题
Day 1: 为删除操作添加了以下REST端点。
@Path("/company/v1/department")
@Component
public class ManageResource {
@DELETE
@Path("/{identifier}/{identifier_value}/employee")
public void delete(@PathParam("identifier") String identifier,
@PathParam("identifier_value") final String identifierValue,
@QueryParam("age") final String age) {
//删除操作
}
}
我可以使用以下请求在 Postman 中调用 DELETE 端点:
DELETE: http://localhost:8080/company/v1/department/name/baner/employee?age=50
Day 2: 在相同的资源中为更新操作添加了以下REST端点。
@Path("/company/v1/department")
@Component
public class ManageResource {
@DELETE
@Path("/{identifier}/{identifier_value}/employee")
public void delete(@PathParam("identifier") String identifier,
@PathParam("identifier_value") final String identifierValue,
@QueryParam("age") final String age) {
//删除操作
}
@PUT
@Path("/empid/{value}/employee")
@Consumes(MediaType.APPLICATION_JSON)
public void update(@PathParam("value") final String identifierValue,
@RequestBody final EmployeeUpdateRequest request) {
//更新操作
}
}
在添加了这个新端点后,我可以使用以下请求在 Postman 中调用 PUT:
PUT: http://localhost:8080/company/v1/department/empid/epid-123/employee
{
//Json 请求体
}
但是,当我尝试调用删除端点时,会出现 405(方法不允许)错误。
如果我注释掉新的 PUT 方法,那么删除方法就能正常工作。
另外,如果我将 PUT 方法的 Path 替换为 /{identifier}/{identifier_value}/employee
,那么删除和 PUT 方法都能正常工作。
我正在使用 Jersey 1.19 与 tomcat。
有人能帮我解决这个问题吗?
英文:
Day 1: Added below rest endpoint for delete operation.
@Path("/company/v1/department")
@Component
public class ManageResource {
@DELETE
@Path("/{identifier}/{identifier_value}/employee")
public void delete(@PathParam("identifier") String identifier,
@PathParam("identifier_value") final String identifierValue,
@QueryParam("age") final String age) {
//delete operation
}
}
I was able to invoke DELETE endpoint using postman with below request:
DELETE: http://localhost:8080/company/v1/department/name/baner/employee?age=50
Day 2: Added below rest endpoint for the update operation in the same resource.
@Path("/company/v1/department")
@Component
public class ManageResource {
@DELETE
@Path("/{identifier}/{identifier_value}/employee")
public void delete(@PathParam("identifier") String identifier,
@PathParam("identifier_value") final String identifierValue,
@QueryParam("age") final String age) {
//delete operation
}
@PUT
@Path("/empid/{value}/employee")
@Consumes(MediaType.APPLICATION_JSON)
public void update(@PathParam("value") final String identifierValue,
@RequestBody final EmployeeUpdateRequest request) {
//update operation
}
}
After adding this new endpoint, I am able to invoke PUT using postman with below request:
PUT: http://localhost:8080/company/v1/department/empid/epid-123/employee
{
//Json request body
}
But when I try to invoke Delete endpoint it is giving me 405 (Method Not Allowed) error.
If I comment my new Put method, then the Delete method works fine.
Also, if I replace Path for Put method to "/{identifier}/{identifier_value}/employee" then both Delete and Put method works fine.
I am using Jersey 1.19 with tomcat.
Can someone help me with this?
答案1
得分: 1
你们的路径存在冲突。让我尝试解释一下:
DELETE = /{identifier}/{identifier_value}/employee
PUT = /empid/{value}/employee
这意味着当我们从左到右评估路径时,我们可以有以下两种情况:
{identifier} 可以是任何内容,或者
"empid" 是一个固定的字符串
Jersey 总是尝试找到 REST 终端点的“最佳”匹配。它通过从左到右评估路径来实现这一点。
固定字符串始终优先于随机变量!
基本上这意味着当您想调用 DELETE 时,不能在变量"{identifier}"中使用值"empid",因为这样就已经超出了范围。
所以对于 DELETE 调用,
http://localhost:8080/company/v1/department/empid/empid-123/employee
将无法工作,因为 Jersey 必须做出决定,即请求中的"empid" 是否与"{identifier}" (DELETE) 或 "empid" (PUT) 匹配。并且正如我上面尝试解释的,固定字符串具有更高的优先级。
相反地,任何其他 DELETE 请求,例如:
http://localhost:8080/company/v1/department/{identifier}/empid-123/employee
并且
{identifier} != "empid"
将可以工作。
可能的解决方案:
使您的 REST 终端点面向资源
DELETE:
/employee/{employee-id}
PUT:
/employee/{employee-id}
请注意,这些终端点是相同的,因为除了大多数系统中的 ID 外,没有需要用于标识实体的其他信息。
英文:
Your Paths are in conflict with each other. Let me try to explain:
DELETE = /{identifier}/{identifier_value}/employee
PUT = /empid/{value}/employee
That means when we evaluate the path from left to right, we can either have
{identifier} which is anything or
"empid" which is a fixed string
Jersey always tries to find the "most perfect" match for a REST endpoint. It does so by evaluating the path from left to right.
Fixed strings always take precedence before random variables!
Basically that means when you want to call a DELETE, you cannot have the value "empid" for the variable "{identifier}" because then you are already out-of-scope
So the DELETE call to
http://localhost:8080/company/v1/department/empid/empid-123/employee
will not work as Jersey had to make a decision whether "empid" in the request matches "{identifier}" (DELETE) or "empid" (PUT). And as i tried to explain above, fixed strings take a higher priority.
In contrast, any other DELETE request where
http://localhost:8080/company/v1/department/{identifier}/empid-123/employee
and
{identifier} != "empid"
works.
Possible solution:
make your rest endpoints resource-oriented
DELETE:
/employee/{employee-id}
PUT:
/employee/{employee-id}
Notice how the endpoints are identical, since other than the ID in most systems, no information is needed to identify an entity.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论