我的网络应用程序已开始在PUT请求中返回403错误。但是,我没有在日志中看到此请求的任何调试消息,因此我对如何进一步调试这一点感到难过。
此代码曾用于工作,但最近有一些变化: 客户是Sencha JS:
Ext.Ajax.request({
url : '/RestWAR/personal/trailSegment/' + trailSegment.id + '.json',
method : 'PUT',
headers : {'Content-Type': 'application/json'},
jsonData : segmentDto
});
容器是Apache Tomcat 6.0。 在转到Spring 3.0.5之前,请求转到Spring Security 3.0.0.RC1。
@Controller
@RequestMapping("/personal")
public class PersonalController {
@RequestMapping(value = "trailSegment/{trailSegmentId}", method=RequestMethod.PUT)
public void updateTrailSegment(@PathVariable long trailSegmentId, @RequestBody PersonalTrailSegmentDTO trailSegmentDto) {
//...
}
}
最近的变化: Spring在3.0.0.M4上,json库是net.sf.json-lib 1.0.2。 Spring现在是3.0.5,json库现在是Jackson Mapper ASL 1.4.2(即Spring建议的那样)。
GET和POST工作正常。这只是失败的PUT。
如果涉及Spring Security,那么我会看到来自Spring Security的调试消息,但我什么也看不见。似乎Tomcat正在停止请求。
提前感谢您的帮助 - 尤其是在调试方面。
答案 0 :(得分:1)
我很想知道是否有 解决这个问题,我们达到了同样的目标 与Tomcat 6.0.x和Spring有关 3.0.1使用PUT& @RequestParam(我想我们也试过了@RequestBody),PUT 与Jetty合作但不是 与Tomcat,除非你添加 url的参数为?someParam = value。 我们选择只使用它来解决它 而是POST。
我刚刚发布了几分钟之前的评论,现在当我们点击这个时我回想起来,我记得我发现this线程(参数从PUT 中消失)当时问题。阅读它,似乎Tomcat开发人员解释HTTP规范意味着PUT不应该支持参数:
嗯,你确定PUT请求吗? 实际上承认“参数”? http://www.ietf.org/rfc/rfc2616.txt, 第9.6节
PUT请求请求 附属实体(在要求机构中) 存储在指示的位置 URI。但我没有看到提及 参数在这里。
-
这些方面还有足够的余地 段落,以证明这一事实 Tomcat开发人员可能已经 有理由不实施任何 处理PUT的“参数” 要求;而其他的开发者 servlet引擎可能已经感觉到了 有理由提供这种处理。 我想说的是 如果你创建一个应用程序 取决于正在处理的参数 在PUT请求中,您可能会创建 一个不便携的应用程序 到所有servlet引擎或HTTP 服务器。但那当然是你的 选择。
所有这些都引发了一个问题: 在之前的帖子中,你提到了这一点 该请求在POST时工作正常。为什么 然后你坚持把它作为PUT发送 ?
答案 1 :(得分:1)
问题是从updateTrailSegment()
方法返回null。这会导致Spring尝试使用InternalResourceView
将请求映射到请求中的内容 - 即/RestWAR/personal/trailSegment/1761
。 InternalResourceView
表示它尝试将该URL解析为应用程序中的路径。由于没有 - 它失败了。
修复程序用作返回类型:
@ResponseBody ExtResponse
ExtResponse只是一个返回响应代码的简单POJO。
完整的方法现在是:
@RequestMapping(value = "trailSegment/{trailSegmentId}", method=RequestMethod.PUT)
public @ResponseBody ExtResponse updateTrailSegment(@PathVariable long trailSegmentId, @RequestBody PersonalTrailSegmentDTO trailSegmentDto) {
trailSegmentDto.setId(trailSegmentId);
PersonalTrailSegment trailSegment = trailSegmentAssembler.assembleDomain(trailSegmentDto);
trailSegmentDataGateway.update(trailSegment);
return new ExtResponse("true", "");
}