如何防止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 Found”,没有正文内容和这些标题:

 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应用程序中, @Controller可以在@RequestMapping方法中接收HttpServletResponse (或ServletResponse )作为参数 。

HandlerInterceptor作为DispatcherServlet的请求处理生命周期的一部分接收它三次。

任何已注册的Servlet Filter实例也可以在Spring的DispatcherServlet之前(和之后)访问ServletResponse ,因为filter在servlet之前起作用。

Spring试图将所有这些依赖项隐藏到Servlet API,以使编程Web服务器更容易。 因此,它提供了导致重定向的其他方法。 这些主要取决于支持的处理程序方法返回类型 。 更具体地说,我们关心StringViewModelAndViewResponseEntity

以下是所有默认情况:

返回String ,Spring将使用ViewResolver根据String值解析View ,该值标识视图的名称。 Spring的UrlBasedViewResolver将在String视图名称中检测redirect:前缀 ,并将其视为发送重定向响应的指示。 它将创建一个RedirectView (其中一部分实际上是在ViewNameMethodReturnValueHandler完成的,但是UrlBasedViewResolver创建了View ),它将负责使用HttpServletResponse进行重定向。

这是一个实现细节,但Spring的大多数默认ViewResolver类都是这样做的。

使用View ,您可以自己创建并返回RedirectView 。 您还可以实现自己的View类,它将执行相同的操作。 Spring将使用适当的HandlerMethodReturnValueHandler来处理它。

使用ModelAndView ,它是前两个选项的混合,因为您可以提供视图名称或View本身。

使用ResponseEntity ,因为您控制整个ResponseEntity它会变得更有趣。 也就是说,您可以设置状态代码,标题,正文,一切。 因此,您需要做的就是将状态代码设置为302,并将带有URL的Location标头重定向到。

最后,您在@ExceptionHandler方法中具有类似的行为(具有类似的返回类型),您也可以与@ResponseStatus混合并手动修改标头。

这些都是基本情况,但由于Spring MVC几乎完全可以自定义,因此还有其他组件需要注意。 这些是HandlerMethodArgumentResolverHandlerMethodReturnValueHandlerHandlerAdapterHandlerExceptionResolverExceptionHandler等等。 请注意,你很少会玩这些,而Spring附带的那些几乎可以完成整个工作。

所以,

我拿了你的代码并用它创建了一个应用程序,尝试使用浏览器插件POSTMAN发送一个PUT请求并获得响应但没有重定向。 看看这是否有效。 我附上完整的类,你可以复制并直接在你的应用程序中使用它。

以下是网络标头:

 Remote Address:::1:8080 Request URL:http://localhost:8080/test/api/testrun/hello Request Method:PUT Status Code:200 OK **Request Headers** Accept:*/* Accept-Encoding:gzip,deflate,sdch Accept-Language:en-GB,en-US;q=0.8,en;q=0.6,pl;q=0.4 Authorization:Basic ZWFzeWwtbWFpbi1pbnQ6cHJnc3VzZXI= Cache-Control:no-cache Connection:keep-alive Content-Length:0 Content-Type:application/json Host:localhost:8080 Origin:chrome-extension://fdmmgilgnpjigdojojpjoooidkmcomcm User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36 **Response Headers** Cache-Control:private Content-Length:5 Content-Type:text/plain;charset=ISO-8859-1 Date:Tue, 10 Jun 2014 10:58:50 GMT Expires:Thu, 01 Jan 1970 05:30:00 IST Server:Apache-Coyote/1.1 ConsoleSearchEmulationRendering 

这是代码: 启动弹簧的配置

 @Configuration @EnableWebMvc @Profile("production") @ComponentScan(basePackages = "com", excludeFilters = { @ComponentScan.Filter(Configuration.class) }) public class WebConfig extends WebMvcConfigurationSupport { @Override protected void configureContentNegotiation( ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false).favorParameter(true) .parameterName("mediaType").ignoreAcceptHeader(true) .useJaf(false).defaultContentType(MediaType.APPLICATION_JSON) .mediaType("xml", MediaType.APPLICATION_XML) .mediaType("json", MediaType.APPLICATION_JSON); } @Bean(name = "viewResolver") public InternalResourceViewResolver viewResolver() throws Exception { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/jsp/"); viewResolver.setSuffix(".jsp"); return viewResolver; } } 

调节器

 @Controller public class TestController { @RequestMapping(value = "/api/testrun/{testrunId}", method = RequestMethod.PUT, consumes = "application/json") @ResponseBody public String updateOverview(@PathVariable("testrunId") final String testrunId) { System.out.println(testrunId); return "hello"; } } 

web.xml中

   test  contextClass  org.springframework.web.context.support.AnnotationConfigWebApplicationContext    contextConfigLocation com.WebConfig   spring.profiles.active production   org.springframework.web.context.ContextLoaderListener   ui  org.springframework.web.servlet.DispatcherServlet   contextClass  org.springframework.web.context.support.AnnotationConfigWebApplicationContext   1   ui /   

Spring建议使用重定向后模式,但默认情况下id不会执行任何操作。 在我的控制器中,我必须通过return "redirect:/url";来彻底结束处理post的方法return "redirect:/url";

我怀疑重定向是在testrunService.updateOverview(testrunId, body); 呼叫。

编辑:实际上, testrunService.updateOverview(testrunId, body);没有任何内容testrunService.updateOverview(testrunId, body); 由于@ResponseBody注释,可能导致重定向。 使用这样的代码,只有拦截器或filter可以进行重定向。