package org.springframework.web.servlet.mvc; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.annotation.WebParam; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.ServletRequestUtils; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerMethod; import org.springframework.web.servlet.handler.metadata.UrlAnnotationHandlerMapping; /** * Adapter that supports handler methods that use the {@link WebParam} annotation. Supports methods with the following * signature: * <pre> * void handleRequest(@WebParam(value = "id", required = true)int param); * </pre> * or * <pre> * ModelAndView handleOtherRequest(@WebParam("id")int id, @WebParam("name")String name); * </pre> * I.e. methods that return either <code>void</code> or a {@link ModelAndView}, and have parameters annotated with * {@link WebParam} that specify the request parameter that should be bound to that parameter. The parameter can be of * the following types: * <ul> * <li><code>boolean</code>, or {@link Boolean}</li> * <li><code>double</code>, or {@link Double}</li> * <li><code>float</code>, or {@link Float}</li> * <li><code>int</code>, or {@link Integer}</li> * <li><code>long</code>, or {@link Long}</li> * <li>{@link String}</li> * </ul> * <p/> * This handler adpater is typically combined with the {@link UrlAnnotationHandlerMapping}. * * @author Arjen Poutsma */ public class WebParamHandlerMethodAdapter extends AbstractHandlerMethodAdapter { protected boolean supportsInternal(Method method) { if (!(ModelAndView.class.isAssignableFrom(method.getReturnType()) || Void.TYPE.equals(method.getReturnType()))) { return false; } Class<?>[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { if (getWebParamAnnotation(method, i) == null || !isSuportedType(parameterTypes[i])) { return false; } } return true; } private WebParam getWebParamAnnotation(Method method, int paramIdx) { Annotation[][] paramAnnotations = method.getParameterAnnotations(); for (int annIdx = 0; annIdx < paramAnnotations[paramIdx].length; annIdx++) { if (paramAnnotations[paramIdx][annIdx].annotationType().equals(WebParam.class)) { return (WebParam) paramAnnotations[paramIdx][annIdx]; } } return null; } private boolean isSuportedType(Class<?> clazz) { return Boolean.class.isAssignableFrom(clazz) || Boolean.TYPE.isAssignableFrom(clazz) || Double.class.isAssignableFrom(clazz) || Double.TYPE.isAssignableFrom(clazz) || Float.class.isAssignableFrom(clazz) || Float.TYPE.isAssignableFrom(clazz) || Integer.class.isAssignableFrom(clazz) || Integer.TYPE.isAssignableFrom(clazz) || Long.class.isAssignableFrom(clazz) || Long.TYPE.isAssignableFrom(clazz) || String.class.isAssignableFrom(clazz); } protected ModelAndView handlerInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { Object[] args = getMethodArguments(request, handlerMethod.getMethod()); Object result = handlerMethod.invoke(args); if (result != null && result instanceof ModelAndView) { return (ModelAndView) result; } else { return null; } } private Object[] getMethodArguments(HttpServletRequest request, Method method) throws ServletRequestBindingException { Class[] parameterTypes = method.getParameterTypes(); Object[] args = new Object[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { WebParam webParam = getWebParamAnnotation(method, i); if (Boolean.class.isAssignableFrom(parameterTypes[i]) || Boolean.TYPE.isAssignableFrom(parameterTypes[i])) { if (webParam.required()) { args[i] = ServletRequestUtils.getRequiredBooleanParameter(request, webParam.value()); } else { args[i] = ServletRequestUtils.getBooleanParameter(request, webParam.value()); } } else if (Double.class.isAssignableFrom(parameterTypes[i]) || Double.TYPE.isAssignableFrom(parameterTypes[i])) { if (webParam.required()) { args[i] = ServletRequestUtils.getRequiredDoubleParameter(request, webParam.value()); } else { args[i] = ServletRequestUtils.getDoubleParameter(request, webParam.value()); } } else if (Float.class.isAssignableFrom(parameterTypes[i]) || Float.TYPE.isAssignableFrom(parameterTypes[i])) { if (webParam.required()) { args[i] = ServletRequestUtils.getRequiredFloatParameter(request, webParam.value()); } else { args[i] = ServletRequestUtils.getFloatParameter(request, webParam.value()); } } else if (Integer.class.isAssignableFrom(parameterTypes[i]) || Integer.TYPE.isAssignableFrom(parameterTypes[i])) { if (webParam.required()) { args[i] = ServletRequestUtils.getRequiredIntParameter(request, webParam.value()); } else { args[i] = ServletRequestUtils.getIntParameter(request, webParam.value()); } } else if (Long.class.isAssignableFrom(parameterTypes[i]) || Long.TYPE.isAssignableFrom(parameterTypes[i])) { if (webParam.required()) { args[i] = ServletRequestUtils.getRequiredLongParameter(request, webParam.value()); } else { args[i] = ServletRequestUtils.getLongParameter(request, webParam.value()); } } else if (String.class.isAssignableFrom(parameterTypes[i])) { if (webParam.required()) { args[i] = ServletRequestUtils.getRequiredStringParameter(request, webParam.value()); } else { args[i] = ServletRequestUtils.getStringParameter(request, webParam.value()); } } } return args; } }