【发布时间】:2016-07-15 21:12:02
【问题描述】:
我正在尝试使用 Spring 的 HandlerInterceptorAdapter 来处理应用程序计划维护以下休息端点的情况:/api/authentication
所以我通过扩展HandlerInterceptorAdapter创建了一个拦截器:
public class MigrationStateInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(someLogic) {
return true
}
response.reset();
response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value());
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
然后我把它添加到我的InterceptorRegistry:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MigrationStateInterceptor()).addPathPatterns("/api/authentication");
}
问题是,我没有在客户端收到503 (Service Unavailable) 错误,而是收到Failed to load resource: the server responded with a status of 406 (Not Acceptable)
从代码 sn-p 中可以看出,我尝试重置响应,但没有结果。
我还尝试修改 Accept 和 Content-Type 标头,但没有运气:
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.addHeader("Accept", "text/plain");
知道为什么会发生这种情况以及如何避免吗?
注意:我在客户端使用 Angular。从我看到的HttpServletResponse#sendError 将内容类型设置为text/html,使cookie 和其他标题保持不变。这会是个问题吗?
编辑:
我什至尝试抛出异常而不是使用HttpServletResponse#sendError,并单独处理,但最终结果是一样的。
例如:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (some logic) {
return true;
}
throw new MigrationStateException("Migration process is disabled");
}
@ExceptionHandler(MigrationStateException.class)
public ResponseEntity<String> migrationStateError(MigrationStateException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.SERVICE_UNAVAILABLE);
}
【问题讨论】:
-
你可以让调试器在 preHandle 中中断吗?
-
是的,我可以。您有兴趣了解什么?
-
你的客户真的期待
text/plain吗?那将是非常不寻常的。sendError不只是设置内容类型,它会发送一个错误页面。您想发送自己的回复。异常处理程序仅适用于控制器。 -
@zeroflagL 异常处理程序捕获了异常,即使它不在控制器中。从非控制器环境返回的响应是否存在问题?关于我在客户端的期望,我可以很容易地改变,但是在服务器端发生了一些事情,将 503 转换为 406。至少,这是我观察到的。您对此有什么建议吗?谢谢!
-
406 表示客户端期望服务器没有提供的东西。了解客户期望的媒体类型很重要。我假设服务器将
ResponseEntity<String>视为text/plain而客户端期望application/json。尝试返回Map。
标签: java spring spring-mvc spring-boot