如何防止Spring MVC进行重定向?
问题内容:
我想处理一个更新实体的AJAX请求。我真的不需要它来返回任何东西。问题在于,Spring
MVC坚持将重定向发送到相同的URL(显然是在执行其重定向后获取的操作),浏览器会忠实地遵循该重定向。
如何才能使Spring MVC控制器方法完成并返回某些内容而无需发送重定向?在网络上搜索只会导致无数关于如何进行重定向的讨论,而不是如何避免重定向的讨论。
这是http://localhost:9090/pex/api/testrun/f0a80b46-84b1-462a-af47-d1eadd779f59e
带有以下标头的PUT请求:
Host: localhost:9090
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0
Accept: */*
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Length: 20
Content-Type: application/json
Referer: http://localhost:9090/pex/api/testrun/f0a80b46-84b1-462a-af47-d1eadd779f59e/visualizations/common-api?slas=lp,internal,external
X-Requested-With: XMLHttpRequest
Connection: keep-alive
Authorization: Basic xxxx
响应的状态码为“找到了302”,没有正文内容和以下标头:
Content-Language: "de"
Content-Length: "0"
Location: "http://localhost:9090/pex/api/testrun/f0a80b46-84b1-462a-af47-d1eadd779f59e"
Server: "Jetty(6.1.10)"
access-control-allow-origin: "*"
这是服务器端代码:
@RequestMapping(value = "/api/testrun/{testrunId}", method = RequestMethod.PUT, consumes = "application/json")
@ResponseBody
public Testrun updateOverview(@PathVariable("testrunId") final String testrunId, @RequestBody final String body) {
return testrunService.updateOverview(testrunId, body);
}
这是进行AJAX调用的Javascript代码:
$(document).ready(function() {
$("#update_name_form").submit(function (e) {
update_testrun($("#name"));
return false;
});
}
function update_testrun(element) {
var name = element.attr('name');
var new_value = element.val().trim();
var data = {};
data[name] = new_value;
$.ajax({url: config.urls.api.testrun + testrun.id,
type: "PUT",
contentType: "application/json",
data: JSON.stringify(data),
error: function(jqXHR, textStatus, errorThrown) {
alert(errorThrown);
},
success: function (data, textStatus, jqXHR) {
testrun.overview[name] = new_value;
}
});
}
问题答案:
Spring MVC建立在Servlet
API之上。因此,HttpServletResponse
理论上可以访问的任何组件都可以使用它sendRedirect(String)
手动设置或设置响应代码。(我说的是
理论上的 原因,因为在进行这些调用时还必须尚未做出响应。)
通常,在Spring MVC应用程序中,a
@Controller
可以将方法中的HttpServletResponse
(或ServletResponse
)@RequestMapping
作为参数接收。
HandlerInterceptor
在DispatcherServlet
的请求处理生命周期中,A
收到了三次。
任何已注册的Servlet Filter
实例都可以访问ServletResponse
Spring的(之前和之后),DispatcherServlet
因为过滤器在Servlet之前起作用。
Spring尝试将所有这些依赖项隐藏到Servlet
API中,以简化Web服务器的编程。因此,它提供了导致重定向的其他方法。这些主要取决于支持的处理程序方法的返回类型。更具体地讲,我们关心的String
,View
,ModelAndView
,和ResponseEntity
。
以下是所有默认情况:
当返回a时String
,Spring将使用a
ViewResolver
来View
基于String
值解析a ,该值标识视图的名称。Spring
UrlBasedViewResolver
会在视图名称中检测到redirect:
前缀,String
并将其视为发送重定向响应的指示。它将创建一个RedirectView
(实际上是在其中完成了一部分ViewNameMethodReturnValueHandler
,但UrlBasedViewResolver
创建了View
),它将负责使用进行重定向HttpServletResponse
。
这是一个实现细节,但是大多数Spring的默认ViewResolver
类都这样做。
使用View
,您可以轻松创建并返回RedirectView
自己。您也可以实现自己的View
类,该类将执行相同的操作。Spring将使用适当的方式HandlerMethodReturnValueHandler
来处理它。
使用ModelAndView
,它是前两个选项的混合,因为您可以提供视图名称或View
本身。
有了ResponseEntity
它,您可以控制整个响应,因此变得更加有趣。也就是说,您可以设置状态代码,标题,正文等所有内容。因此,您所需要做的就是将状态代码设置为302,并放置一个Location
带有URL
的标头以重定向到。
最后,您在@ExceptionHandler
方法中具有相似的行为(具有相似的返回类型),也可以将它们与@ResponseStatus
手动混合并修改标头。
这些都是基本情况,但是由于Spring
MVC几乎可以完全自定义,因此还有其他组件需要注意。这是HandlerMethodArgumentResolver
,HandlerMethodReturnValueHandler
,HandlerAdapter
,HandlerExceptionResolver
和ExceptionHandler
等。请注意,您很少会使用这些功能,而Spring附带的功能几乎可以完成整个工作。