Spring 4.3.0.RELEASE 不向@Controller注入Model和Request
Spring 4.3.0.RELEASE does not inject Model and Request to @Controller
下面的代码在 Spring 4.2.6.REALESE 上运行良好。现在,迁移后发生了一些变化,我开始在我的@Controller 中得到空值这是一个错误吗?
@Controller
@RequestMapping("/client")
public class ClientController {
@RequestMapping(value = "test", method = RequestMethod.GET)
public String test(Model model) {
// model is null at this point
return "client/test";
}
}
我分享了模型对象为空的经验。下面的代码在 4.3.0-RELEASE 之前运行良好。也许我们缺少一些新配置?
@Controller
@RequestMapping("/admin/pricelists")
public class PriceListsController {
@RequestMapping(value = "/")
public String index(final Model model) {
// Model is null in 4.3.0-RELEASE.
...
}
}
简答:4.3.0.RELEASE 需要 Servlet 3.0+
更长的证明:
模型为空,因为一种为 org.springframework.ui.Model
找到合适的 ArgumentResolver
的方法找到了列表中的第一个 org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
而不是 org.springframework.web.method.annotation.ModelMethodProcessor
这是代码形式 HandlerMethodArgumentResolverComposite 的无效部分
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
if (logger.isTraceEnabled()) {
logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
parameter.getGenericParameterType() + "]");
}
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
RequestParamMethodArgumentResolver 在列表中排在第一位,它的
RequestParamMethodArgumentResolver.supportsParameter(MethodParameter parameter)
returns 是因为这一行:
if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
return true;
}
然后在 MultipartResolutionDelegate
:
public static boolean isMultipartArgument(MethodParameter parameter) {
Class<?> paramType = parameter.getNestedParameterType();
return (MultipartFile.class == paramType || isMultipartFileCollection(parameter) ||
isMultipartFileArray(parameter) || servletPartClass == paramType ||
isPartCollection(parameter) || isPartArray(parameter));
}
isPartCollection returns true 因为这个奇怪的比较等式的两边都是空值!!
private static boolean isPartCollection(MethodParameter methodParam) {
return (servletPartClass == getCollectionParameterType(methodParam));
}
servletPartClass 为空,因为
private static Class<?> servletPartClass = null;
static {
try {
servletPartClass = ClassUtils.forName("javax.servlet.http.Part",
MultipartResolutionDelegate.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Servlet 3.0 javax.servlet.http.Part type not available -
// Part references simply not supported then.
}
}
这个 is fixed 在 4.3.1
Spring Framework / SPR-14358
Failure to resolve @RequestMapping method arguments in Servlet 2.5 environments
下面的代码在 Spring 4.2.6.REALESE 上运行良好。现在,迁移后发生了一些变化,我开始在我的@Controller 中得到空值这是一个错误吗?
@Controller
@RequestMapping("/client")
public class ClientController {
@RequestMapping(value = "test", method = RequestMethod.GET)
public String test(Model model) {
// model is null at this point
return "client/test";
}
}
我分享了模型对象为空的经验。下面的代码在 4.3.0-RELEASE 之前运行良好。也许我们缺少一些新配置?
@Controller
@RequestMapping("/admin/pricelists")
public class PriceListsController {
@RequestMapping(value = "/")
public String index(final Model model) {
// Model is null in 4.3.0-RELEASE.
...
}
}
简答:4.3.0.RELEASE 需要 Servlet 3.0+
更长的证明:
模型为空,因为一种为 org.springframework.ui.Model
找到合适的 ArgumentResolver
的方法找到了列表中的第一个 org.springframework.web.method.annotation.RequestParamMethodArgumentResolver
而不是 org.springframework.web.method.annotation.ModelMethodProcessor
这是代码形式 HandlerMethodArgumentResolverComposite 的无效部分
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
if (result == null) {
for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) {
if (logger.isTraceEnabled()) {
logger.trace("Testing if argument resolver [" + methodArgumentResolver + "] supports [" +
parameter.getGenericParameterType() + "]");
}
if (methodArgumentResolver.supportsParameter(parameter)) {
result = methodArgumentResolver;
this.argumentResolverCache.put(parameter, result);
break;
}
}
}
return result;
}
RequestParamMethodArgumentResolver 在列表中排在第一位,它的
RequestParamMethodArgumentResolver.supportsParameter(MethodParameter parameter)
returns 是因为这一行:
if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
return true;
}
然后在 MultipartResolutionDelegate
:
public static boolean isMultipartArgument(MethodParameter parameter) {
Class<?> paramType = parameter.getNestedParameterType();
return (MultipartFile.class == paramType || isMultipartFileCollection(parameter) ||
isMultipartFileArray(parameter) || servletPartClass == paramType ||
isPartCollection(parameter) || isPartArray(parameter));
}
isPartCollection returns true 因为这个奇怪的比较等式的两边都是空值!!
private static boolean isPartCollection(MethodParameter methodParam) {
return (servletPartClass == getCollectionParameterType(methodParam));
}
servletPartClass 为空,因为
private static Class<?> servletPartClass = null;
static {
try {
servletPartClass = ClassUtils.forName("javax.servlet.http.Part",
MultipartResolutionDelegate.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Servlet 3.0 javax.servlet.http.Part type not available -
// Part references simply not supported then.
}
}
这个 is fixed 在 4.3.1
Spring Framework / SPR-14358
Failure to resolve @RequestMapping method arguments in Servlet 2.5 environments