0

我正在使用球衣版本 1.17.1 + tomcat 7.0.39 + Spring MVC 3.2.1。

问题是当我扩展 GET 处理程序的 @Path 时,我无法弄清楚为什么我的 PUT 处理程序停止工作?

我的 Spring MVC 控制器中的以下配置/匹配按预期工作:

 @GET
 @Path("/{id}")   // <--- WORKS!
 [...]

 @PUT
 @Path("/{id}")   // <--- WORKS!  
 [...]      

但是每当我扩展 GET处理程序的匹配以便不仅能够处理

/anyId    

请求,但也请求表格

/anyId/
/anyId/anyfile.ext

然后没有触及PUT 匹配停止工作

 @GET
 @Path("/{id:.*[^/]}{fileName:.*}")   // <--- WORKS!
 [...]

 @PUT
 @Path("/{id}")                       // <--- Not working any longer: 
                                      //      "405 Method Not Allowed" 
 [...]

将 GET 路径的匹配更改为上述 PUT 请求的匹配后,将获得“405 Method Not Allowed”状态代码。

当我像第一种情况一样简化 GET 路径时,PUT 处理程序再次开始工作。

是泽西岛的虫子还是什么?

4

2 回答 2

1

405 表示没有与该资源请求中的方法匹配的方法。这将表明某物(或若干物)具有匹配的@Path注解,但该(Java)方法没有正确的方法。(如果可以的话,在查看正在发生的事情时打开详细调试;它会有所帮助。完成后将其关闭;它对于通常保持打开状态来说太冗长了。)

现在,它有助于理解@Path映射到与请求中的路径匹配的正则表达式,并且如果您没有另外指定,路径模板部分(the {id})将由正则表达式有效匹配[^?/;]+,即尽可能多的字符,而无需进入路径的下一部分、查询部分或任何矩阵参数。(不知道什么是矩阵参数?你可能不想知道!)

为了匹配所有这些形式:

/anyId    
/anyId/
/anyId/anyfile.ext

每个 HTTP 方法最好使用两个 Java 方法:

@GET @Path("{id}")
…
@GET @Path("{id}/{file:.*}")
…

这有效,但它很冗长。


相反,返回一个表示资源并在其上定义了操作的对象可能更容易:

class MyResource {
    private String id, file;
    MyResource(String id, String file) {
        this.id = id; this.file = file;
    }
    // Can't remember if @Path is needed on these; "/" is a special case IIRC
    @GET @Path("/") @Produces(…)
    public String get() { … }
    @PUT @Path("/") @Produces(…) @Consumes(…)
    public String put(String message) { … }
}
@Path("{id}")
public MyResource getNoPath(@PathParam("id") String id) {
    return new MyResource(id, null);
}
@Path("{id}/{file:.*}")
public MyResource getNoPath(@PathParam("id") String id, @PathParam("file") String file) {
    return new MyResource(id, file);
}

像这样,您将解析路径的代码与提供正确方法的代码分开。我用 CXF(另一个 JAX-RS 实现)来做这件事,而且效果很好。

于 2013-07-25T13:40:10.080 回答
0

405 通常意味着找不到合适的方法。仅凭您提供的小片段很难分辨,但您需要确保@Consumes您的方法上有适当的注释PUT

您也可以尝试将您的更改@Path为类似的东西@Path("{id: [^/]+}/{fileName: .+}"),看看是否有帮助。如果没有,请提供您的完整控制器。

于 2013-07-23T15:49:50.003 回答