我有一个控制器方法,添加了@ResponseBody注解
@GetMapping(value = "/users") @ResponseBody public Map<String, Object> modelAttribute(Model model) { return model.asMap(); }
访问该方法始终返回404,断点发现方法有执行。返回错误如下:
看到Message 提示是/WEB-INF/views/model/users.jsp 找不到。原来404 是这个,但是很奇怪不是已经添加了@ResponseBody注解吗?
为什么还会尝试去寻找一个jsp视图呢?
为此我断点DispatcherServlet并一步步跟踪,其原因是在 HandlerMethodReturnValueHandlerComposite的 调用selectHandler
寻找 返回值处理器(HandlerMethodReturnValueHandler)时
private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) { boolean isAsyncValue = isAsyncReturnValue(value, returnType); for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) { if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) { continue; } if (handler.supportsReturnType(returnType)) { return handler; } } return null; }
调用 handler.supportsReturnType(returnType) 这一方法通过返回值来匹配对应的handler,优先匹配到的是 ModelMethodProcessor,
为何是 ModelMethodProcessor, 查看其supportsReturnType方法:
public boolean supportsReturnType(MethodParameter returnType) { return Model.class.isAssignableFrom(returnType.getParameterType()); }
其就是通过检查返回值类型是否Model 接口类型,而ModelMethodProcessor 值处理器 又是跳转视图的,所以即使加了@ResponseBody注解依然会
去寻找视图。不知道这算不算是一个bug,这个坑千万注意不要踩。