![](/img/trans.png)
[英]Spring MVC: how to intercept 404 before returning error page/response?
[英]How to send response before actions in spring mvc
假设我的弹簧控制器功能接收到大量数据。 我想返回200 OK,因为数据结构正确, 之后我想执行处理,这可能需要一段时间。
据我所知,发送响应的唯一方法是使用return命令。 但我不想结束响应发送功能。
是否有其他方法可以在功能中间向客户端发送响应?
创建一个新的线程运行是显而易见的,但其他语言(JS)可以让你更优雅地处理它。
@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = RequestMethod.POST)
public ResponseEntity<String> doSomething(@RequestBody List<Message> messages) {
HttpStatus code = (messages!=null && !messages.isEmpty()) ? HttpStatus.OK
: HttpStatus.NOT_FOUND;
return new ResponseEntity<String>(res, code);
// how do I add code here??
}
您当然可以在发送响应后进行处理。 更通用的方法是使用HandlerInterceptor
的afterCompletion
方法。 通过建设,响应已发送到客户端后,它会被执行,但是它迫使你拆你的逻辑在2个组件在控制器部分之前 ,以及在拦截部分之后 。
另一种方法是忘记Spring MVC机制并在控制器中手动提交响应:
@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = RequestMethod.POST)
public void doSomething(@RequestBody List<Message> messages, HttpServletResponse response) {
int code = (messages!=null && !messages.isEmpty()) ? HttpServletResponse.SC_OK
: HttpServletResponse.SC_NOT_FOUND;
if (code != HttpServletResponse.SC_OK) {
response.sendError(code, res);
return;
}
java.io.PrintWriter wr = response.getWriter();
response.setStatus(code);
wr.print(res);
wr.flush();
wr.close();
// Now it it time to do the long processing
...
}
请注意void返回代码,以通知Spring响应已在控制器中提交。
作为一个优势,处理仍然发生在同一个线程中,因此您可以完全访问会话范围属性或Spring MVC或Spring Security使用的任何其他线程局部变量...
我想你们使用了Spring的异步机制。在servlet 3.0中引入了异步方法,Spring为它们提供了一些支持基本上......你提出了一个请求; 请求由服务器处理,然后,在后台,新线程管理请求数据这里一个有用的链接(至少我希望:)) http://spring.io/blog/2012/05/10/spring- MVC-3-2-预览决策-A-控制器方法的异步/
您应该使用HandlerInterceptor
。 但是代码比预期的要复杂得多。 所以,这里有一个代码建议,通过将整个解决方案放在一个类中来简化它:
@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method = RequestMethod.POST)
public ResponseEntity<String> doSomething(@RequestBody List<Message> messages) {
HttpStatus code = (messages!=null && !messages.isEmpty()) ? HttpStatus.OK
: HttpStatus.NOT_FOUND;
result.set(res); // Save the object to be used after response
return new ResponseEntity<String>(res, code);
}
private static final ThreadLocal<String> result = new ThreadLocal<String>();
@Bean
public HandlerInterceptor interceptor() {
return new HandlerInterceptor() {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// Get the saved object and clean for the next request
String res = result.get();
result.set(null);
// TODO Your code to be executed after response.
}
};
}
您可以使用@Async
@RequestMapping(value = Connectors.CONNECTOR_HEARTBEAT, method =
RequestMethod.POST)
public ResponseEntity<String> doSomething(@RequestBody List<Message>
messages) {
do();
HttpStatus code = (messages!=null && !messages.isEmpty()) ? HttpStatus.OK
: HttpStatus.NOT_FOUND;
return new ResponseEntity<String>(res, code);
}
@Async
void do(){
//your code
}
这项工作在java 8中
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.