提交 1e1964a0 编写于 作者: J Juergen Hoeller

reintroduced createBinder template method in Servlet/Portlet...

reintroduced createBinder template method in Servlet/Portlet AnnotationMethodHandlerAdapter (SPR-6534)
上级 2ce5090d
......@@ -70,6 +70,7 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -87,6 +88,7 @@ import org.springframework.web.context.request.RequestScope;
import org.springframework.web.portlet.HandlerAdapter;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.bind.MissingPortletRequestParameterException;
import org.springframework.web.portlet.bind.PortletRequestDataBinder;
import org.springframework.web.portlet.bind.annotation.ActionMapping;
import org.springframework.web.portlet.bind.annotation.EventMapping;
import org.springframework.web.portlet.bind.annotation.RenderMapping;
......@@ -212,7 +214,7 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
}
/**
* Set a custom WebArgumentResolvers to use for special method parameter types.
* Set a custom WebArgumentResolver to use for special method parameter types.
* Such a custom WebArgumentResolver will kick in first, having a chance to
* resolve an argument value before the standard argument handling kicks in.
*/
......@@ -379,6 +381,26 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
}
/**
* Template method for creating a new PortletRequestDataBinder instance.
* <p>The default implementation creates a standard PortletRequestDataBinder.
* This can be overridden for custom PortletRequestDataBinder subclasses.
* @param request current portlet request
* @param target the target object to bind onto (or <code>null</code>
* if the binder is just used to convert a plain parameter value)
* @param objectName the objectName of the target object
* @return the PortletRequestDataBinder instance to use
* @throws Exception in case of invalid state or arguments
* @see PortletRequestDataBinder#bind(javax.portlet.PortletRequest)
* @see PortletRequestDataBinder#convertIfNecessary(Object, Class, MethodParameter)
*/
protected PortletRequestDataBinder createBinder(
PortletRequest request, Object target, String objectName) throws Exception {
return new PortletRequestDataBinder(target, objectName);
}
/**
* Portlet-specific subclass of {@link HandlerMethodResolver}.
*/
......@@ -507,6 +529,20 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
throw new PortletSessionRequiredException(message);
}
@Override
protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
throws Exception {
return AnnotationMethodHandlerAdapter.this.createBinder(
(PortletRequest) webRequest.getNativeRequest(), target, objectName);
}
@Override
protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
PortletRequestDataBinder portletBinder = (PortletRequestDataBinder) binder;
portletBinder.bind((PortletRequest) webRequest.getNativeRequest());
}
@Override
protected Object resolveDefaultValue(String value) {
if (beanFactory == null) {
......@@ -610,8 +646,8 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
// Invoke custom resolvers if present...
if (customModelAndViewResolvers != null) {
for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) {
org.springframework.web.servlet.ModelAndView smav = mavResolver
.resolveModelAndView(handlerMethod, handlerType, returnValue, implicitModel, webRequest);
org.springframework.web.servlet.ModelAndView smav =
mavResolver.resolveModelAndView(handlerMethod, handlerType, returnValue, implicitModel, webRequest);
if (smav != ModelAndViewResolver.UNRESOLVED) {
return (smav.isReference() ?
new ModelAndView(smav.getViewName(), smav.getModelMap()) :
......
......@@ -80,6 +80,8 @@ import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.HttpSessionRequiredException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -434,6 +436,26 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
}
/**
* Template method for creating a new ServletRequestDataBinder instance.
* <p>The default implementation creates a standard ServletRequestDataBinder.
* This can be overridden for custom ServletRequestDataBinder subclasses.
* @param request current HTTP request
* @param target the target object to bind onto (or <code>null</code>
* if the binder is just used to convert a plain parameter value)
* @param objectName the objectName of the target object
* @return the ServletRequestDataBinder instance to use
* @throws Exception in case of invalid state or arguments
* @see ServletRequestDataBinder#bind(javax.servlet.ServletRequest)
* @see ServletRequestDataBinder#convertIfNecessary(Object, Class, MethodParameter)
*/
protected ServletRequestDataBinder createBinder(
HttpServletRequest request, Object target, String objectName) throws Exception {
return new ServletRequestDataBinder(target, objectName);
}
/**
* Servlet-specific subclass of {@link HandlerMethodResolver}.
*/
......@@ -554,7 +576,6 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
/**
* Determines the matched pattern for the given methodLevelPattern and path.
*
* <p>Uses the following algorithm: <ol> <li>If there is a type-level mapping with path information, it is {@linkplain
* PathMatcher#combine(String, String) combined} with the method-level pattern. <li>If there is a {@linkplain
* HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best matching pattern} in the request, it is combined with the
......@@ -661,6 +682,26 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
throw new HttpSessionRequiredException(message);
}
@Override
protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
throws Exception {
return AnnotationMethodHandlerAdapter.this.createBinder(
(HttpServletRequest) webRequest.getNativeRequest(), target, objectName);
}
@Override
protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
servletBinder.bind((ServletRequest) webRequest.getNativeRequest());
}
@Override
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
HttpServletRequest servletRequest = (HttpServletRequest) webRequest.getNativeRequest();
return new ServletServerHttpRequest(servletRequest);
}
@Override
protected Object resolveDefaultValue(String value) {
if (beanFactory == null) {
......@@ -674,12 +715,6 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator
return exprResolver.evaluate(placeholdersResolved, expressionContext);
}
@Override
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
HttpServletRequest servletRequest = (HttpServletRequest) webRequest.getNativeRequest();
return new ServletServerHttpRequest(servletRequest);
}
@Override
protected Object resolveCookieValue(String cookieName, Class paramType, NativeWebRequest webRequest)
throws Exception {
......
......@@ -51,6 +51,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.HttpMediaTypeNotSupportedException;
......@@ -287,7 +288,7 @@ public class HandlerMethodInvoker {
args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
}
else if (attrName != null) {
WebRequestDataBinder binder =
WebDataBinder binder =
resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
if (binder.getTarget() != null) {
......@@ -433,7 +434,7 @@ public class HandlerMethodInvoker {
}
paramValue = checkValue(paramName, paramValue, paramType);
}
WebRequestDataBinder binder = new WebRequestDataBinder(null, paramName);
WebDataBinder binder = createBinder(webRequest, null, paramName);
initBinder(handlerForInitBinderCall, paramName, binder, webRequest);
return binder.convertIfNecessary(paramValue, paramType, methodParam);
}
......@@ -486,7 +487,7 @@ public class HandlerMethodInvoker {
}
headerValue = checkValue(headerName, headerValue, paramType);
}
WebRequestDataBinder binder = new WebRequestDataBinder(null, headerName);
WebDataBinder binder = createBinder(webRequest, null, headerName);
initBinder(handlerForInitBinderCall, headerName, binder, webRequest);
return binder.convertIfNecessary(headerValue, paramType, methodParam);
}
......@@ -551,20 +552,9 @@ public class HandlerMethodInvoker {
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
}
/**
* Return a {@link HttpInputMessage} for the given {@link NativeWebRequest}.
* <p>Throws an UnsupportedOperationException by default.
*/
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
throw new UnsupportedOperationException("@RequestBody not supported");
}
private Object resolveCookieValue(String cookieName,
boolean required,
String defaultValue,
MethodParameter methodParam,
NativeWebRequest webRequest,
Object handlerForInitBinderCall) throws Exception {
private Object resolveCookieValue(String cookieName, boolean required, String defaultValue,
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
throws Exception {
Class<?> paramType = methodParam.getParameterType();
if (cookieName.length() == 0) {
......@@ -580,7 +570,7 @@ public class HandlerMethodInvoker {
}
cookieValue = checkValue(cookieName, cookieValue, paramType);
}
WebRequestDataBinder binder = new WebRequestDataBinder(null, cookieName);
WebDataBinder binder = createBinder(webRequest, null, cookieName);
initBinder(handlerForInitBinderCall, cookieName, binder, webRequest);
return binder.convertIfNecessary(cookieValue, paramType, methodParam);
}
......@@ -595,17 +585,15 @@ public class HandlerMethodInvoker {
throw new UnsupportedOperationException("@CookieValue not supported");
}
private Object resolvePathVariable(String pathVarName,
MethodParameter methodParam,
NativeWebRequest webRequest,
Object handlerForInitBinderCall) throws Exception {
private Object resolvePathVariable(String pathVarName, MethodParameter methodParam,
NativeWebRequest webRequest, Object handlerForInitBinderCall) throws Exception {
Class<?> paramType = methodParam.getParameterType();
if (pathVarName.length() == 0) {
pathVarName = getRequiredParameterName(methodParam);
}
String pathVarValue = resolvePathVariable(pathVarName, paramType, webRequest);
WebRequestDataBinder binder = new WebRequestDataBinder(null, pathVarName);
WebDataBinder binder = createBinder(webRequest, null, pathVarName);
initBinder(handlerForInitBinderCall, pathVarName, binder, webRequest);
return binder.convertIfNecessary(pathVarValue, paramType, methodParam);
}
......@@ -644,7 +632,7 @@ public class HandlerMethodInvoker {
return value;
}
private WebRequestDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
// Bind request parameter onto object...
......@@ -666,7 +654,7 @@ public class HandlerMethodInvoker {
else {
bindObject = BeanUtils.instantiateClass(paramType);
}
WebRequestDataBinder binder = new WebRequestDataBinder(bindObject, name);
WebDataBinder binder = createBinder(webRequest, bindObject, name);
initBinder(handler, name, binder, webRequest);
return binder;
}
......@@ -695,7 +683,7 @@ public class HandlerMethodInvoker {
(isSessionAttr || isBindingCandidate(attrValue))) {
String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName;
if (mavModel != null && !model.containsKey(bindingResultKey)) {
WebRequestDataBinder binder = new WebRequestDataBinder(attrValue, attrName);
WebDataBinder binder = createBinder(webRequest, attrValue, attrName);
initBinder(handler, attrName, binder, webRequest);
mavModel.put(bindingResultKey, binder.getBindingResult());
}
......@@ -740,18 +728,36 @@ public class HandlerMethodInvoker {
throw new IllegalStateException(message);
}
protected void doBind(WebRequestDataBinder binder, NativeWebRequest webRequest, boolean validate,
boolean failOnErrors) throws Exception {
protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
throws Exception {
return new WebRequestDataBinder(target, objectName);
}
binder.bind(webRequest);
private void doBind(WebDataBinder binder, NativeWebRequest webRequest, boolean validate, boolean failOnErrors)
throws Exception {
doBind(binder, webRequest);
if (validate) {
binder.validate();
}
if (failOnErrors) {
binder.closeNoCatch();
if (failOnErrors && binder.getBindingResult().hasErrors()) {
throw new BindException(binder.getBindingResult());
}
}
protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
((WebRequestDataBinder) binder).bind(webRequest);
}
/**
* Return a {@link HttpInputMessage} for the given {@link NativeWebRequest}.
* <p>Throws an UnsupportedOperationException by default.
*/
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
throw new UnsupportedOperationException("@RequestBody not supported");
}
protected Object resolveDefaultValue(String value) {
return value;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册