我想处理更新实体的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;
}
});
}
答案 0 :(得分:13)
Spring MVC构建于Servlet API之上。因此,任何有权访问HttpServletResponse
的组件理论上都可以将其用于sendRedirect(String)
或手动设置响应代码。 (我说理论上因为在进行这些调用时,响应必须尚未提交。)
通常,在Spring MVC应用程序中,@Controller
可以HttpServletResponse
方式接收ServletResponse
(或@RequestMapping
}作为argument。
作为DispatcherServlet
请求处理生命周期的一部分,HandlerInterceptor
会收到它三次。
任何已注册的Servlet Filter
实例也可以在Spring DispatcherServlet
之前(及之后)访问ServletResponse
,因为过滤器在servlet之前起作用。
Spring尝试将所有这些依赖项隐藏到Servlet API,以使编程Web服务器更容易。因此,它提供了导致重定向的其他方法。这些主要取决于supported handler method return types。更具体地说,我们关心String
,View
,ModelAndView
和ResponseEntity
。
以下是所有默认情况:
当您返回String
时,Spring将使用ViewResolver
根据String
值解析View
,该值标识视图的名称。 Spring的UrlBasedViewResolver
将检测String
视图名称中的a redirect:
prefix,并将其视为发送重定向响应的指示。它会创建一个RedirectView
(其中一部分实际上是在ViewNameMethodReturnValueHandler
中完成的,但是UrlBasedViewResolver
会创建View
),它将负责使用{{进行重定向1}}。
这是一个实现细节,但Spring的大多数默认HttpServletResponse
类都是这样做的。
使用View
,您可以自行创建并返回ViewResolver
。您还可以实现自己的RedirectView
类,它将执行相同的操作。 Spring将使用适当的HandlerMethodReturnValueHandler
来处理它。
使用View
,它是前两个选项的混合,因为您可以提供视图名称或ModelAndView
本身。
使用ResponseEntity
,因为您控制整个响应,它会变得更有趣。也就是说,您可以设置状态代码,标题,正文,一切。因此,您需要做的就是将状态代码设置为302并将View
标头与URL重定向到。
最后,您在@ExceptionHandler
methods(具有类似的返回类型)中也有类似的行为,您也可以将其与@ResponseStatus
混合并手动修改标题。
这些都是基本情况,但由于Spring MVC几乎可以完全自定义,因此还需要注意其他组件。这些是HandlerMethodArgumentResolver
,Location
,HandlerAdapter
,HandlerExceptionResolver
和ExceptionHandler
等等。请注意,你很少会玩这些,而Spring附带的那些几乎可以完成整个工作。
答案 1 :(得分:3)
所以,
我拿了你的代码并用它创建了一个应用程序,尝试使用浏览器插件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 强>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>test</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.WebConfig</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>production</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>ui</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ui</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
答案 2 :(得分:1)
Spring建议使用重定向后模式,但默认情况下,id 不执行任何操作。
在我的控制器中,我必须通过return "redirect:/url";
我怀疑重定向是在testrunService.updateOverview(testrunId, body);
电话中完成的。
编辑:实际上,由于testrunService.updateOverview(testrunId, body);
注释,@ResponseBody
中的任何内容都无法导致重定向。使用这样的代码,只有拦截器或过滤器可以进行重定向。