版本:Spring3.0 、java 1.6
@RequestMapping(/get)
public Map<Long, List<Item>> getPrepareTradeItemMap(UserKey key, Long[] ids) throws Exception {}
上面的方法没有使用@responseBody注解去转json格式,项目自定义了一个ReturnHandler实现
HandlerMethodReturnValueHandler,来对所有controller层返回的结果进行处理
代码如下:
public class FeReturnValueHandler implements HandlerMethodReturnValueHandler {
@Override
public boolean supportsReturnType(MethodParameter methodParameter) {
Annotation annotations = methodParameter.getDeclaringClass().getAnnotation(FeAnnotations.class);
return annotations != null;
}
@Override
public void handleReturnValue(Object object, MethodParameter parameter, ModelAndViewContainer container, NativeWebRequest webRequest) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
boolean isRedirect = false;
if (object instanceof String) {
String viewName = (String) object;
if (viewName.startsWith("redirect:")) {
isRedirect = true;
container.setViewName(viewName);
container.setRedirectModelScenario(true);
}
}
if (!isRedirect) {
JsonResponse jsonResponse = new JsonResponse();
jsonResponse.setData(object);
HttpUtil.write(request, response, jsonResponse);
}
}
}
但是吧、这个 Map<Long, List<Item>> 的返回类型,好巧不巧,被MapMethodProcessor先拦截了,然后进入到了MapMethodProcessor的实现类里面
下图是实现HandlerMethodReturnValueHandler接口的一些方法:
然后我们去看看MapMethodProcessor的实现类:
public class MapMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
public MapMethodProcessor() {
}
public boolean supportsParameter(MethodParameter parameter) {
return Map.class.isAssignableFrom(parameter.getParameterType());
}
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return mavContainer.getModel();
}
public boolean supportsReturnType(MethodParameter returnType) {
return Map.class.isAssignableFrom(returnType.getParameterType());
}
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
if (returnValue != null) {
if (returnValue instanceof Map) {
mavContainer.addAllAttributes((Map)returnValue);
} else {
throw new UnsupportedOperationException("Unexpected return type: " + returnType.getParameterType().getName() + " in method: " + returnType.getMethod());
}
}
}
}
在这里我们找到凶手了,凶手就是红色框框框出来的Map类型,在
mavContainer.addAllAttributes((Map)returnValue);方法中,指定了returnValue的接受类型:<String,?>,而我们从controller返回的是Map<Long, List<Item>> 类型,所以就发生的castException异常, Long to String
这里有一点要说明:是否进去handleReturnValue()方法是根据supportsReturnType()的boolean结果来决定的