我有一個控制器方法,添加了@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,這個坑千萬注意不要踩。