SpingMVC源码探究 之 解析HttpServletRequest参数

来源:互联网 发布:安多数据库工程师招聘 编辑:程序博客网 时间:2024/05/23 16:54

我们来探究SpingMVC是如何解析方法入参的。

首先设置的handler如下:在执行方法处、及DispatherServlet的doDispath()方法设置断点开始执行方法

@Controllerpublic class TestHandler {@RequestMapping("/testParam1")public String testParam1(String username){System.out.println("输出username:"+username);return "success";}}

地址栏输入如下:
http://localhost/SpringMVC_02_RequestParam/testParam1?username=admin


如之前所说,SpringMVC的程序执行过程是在DispatherServlet.doDispath()方法中进行。
// 真正执行目标方法// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());


真正执行目标方法会调用AnnotationMethodHandlerAdapter的handle方法

AnnotationMethodHandlerAdapter@Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {...return invokeHandlerMethod(request, response, handler);}


调用本类的invokeHandlerMethod方法
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {//根据handler获取方法的解析器ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);//通过解析器返回需要执行的方法的完整签名Method handlerMethod = methodResolver.resolveHandlerMethod(request);//根据方法解析器拿到方法的执行者ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver);//将原生的request、response包装成他们自己使用的ServletWebRequestServletWebRequest webRequest = new ServletWebRequest(request, response);ExtendedModelMap implicitModel = new BindingAwareModelMap();//使用方法执行者执行目标方法Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);ModelAndView mav =methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);return mav;}

方法执行者HandlerMethodInvoker执行目标方法invokeHandlerMethod
HandlerMethodInvoker
public final Object invokeHandlerMethod(Method handlerMethod, Object handler,NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {//获取方法的完整签名Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);try {boolean debug = logger.isDebugEnabled();//解析session域中的属性for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);if (attrValue != null) {implicitModel.addAttribute(attrName, attrValue);}}//解析执行被ModelAttribute注解标注的方法for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);if (debug) {logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);}String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {continue;}ReflectionUtils.makeAccessible(attributeMethodToInvoke);Object attrValue = attributeMethodToInvoke.invoke(handler, args);if ("".equals(attrName)) {Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);}if (!implicitModel.containsAttribute(attrName)) {implicitModel.addAttribute(attrName, attrValue);}}//解析处理器目标方法的参数Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);if (debug) {logger.debug("Invoking request handler method: " + handlerMethodToInvoke);}ReflectionUtils.makeAccessible(handlerMethodToInvoke);return handlerMethodToInvoke.invoke(handler, args);}catch (IllegalStateException ex) {// Internal assertion failed (e.g. invalid signature):// throw exception with full handler method context...throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);}catch (InvocationTargetException ex) {// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...ReflectionUtils.rethrowException(ex.getTargetException());return null;}}



解析处理器目标方法的参数调用本类的resolveHandlerArguments方法
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {Class<?>[] paramTypes = handlerMethod.getParameterTypes();Object[] args = new Object[paramTypes.length];for (int i = 0; i < args.length; i++) {MethodParameter methodParam = new MethodParameter(handlerMethod, i);methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());String paramName = null;String headerName = null;boolean requestBodyFound = false;String cookieName = null;String pathVarName = null;String attrName = null;boolean required = false;String defaultValue = null;boolean validate = false;Object[] validationHints = null;int annotationsFound = 0;//参数是否带注解Annotation[] paramAnns = methodParam.getParameterAnnotations();for (Annotation paramAnn : paramAnns) {if (RequestParam.class.isInstance(paramAnn)) {RequestParam requestParam = (RequestParam) paramAnn;paramName = requestParam.value();required = requestParam.required();defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());annotationsFound++;}else if (RequestHeader.class.isInstance(paramAnn)) {RequestHeader requestHeader = (RequestHeader) paramAnn;headerName = requestHeader.value();required = requestHeader.required();defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());annotationsFound++;}else if (RequestBody.class.isInstance(paramAnn)) {requestBodyFound = true;annotationsFound++;}else if (CookieValue.class.isInstance(paramAnn)) {CookieValue cookieValue = (CookieValue) paramAnn;cookieName = cookieValue.value();required = cookieValue.required();defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());annotationsFound++;}else if (PathVariable.class.isInstance(paramAnn)) {PathVariable pathVar = (PathVariable) paramAnn;pathVarName = pathVar.value();annotationsFound++;}else if (ModelAttribute.class.isInstance(paramAnn)) {ModelAttribute attr = (ModelAttribute) paramAnn;attrName = attr.value();annotationsFound++;}else if (Value.class.isInstance(paramAnn)) {defaultValue = ((Value) paramAnn).value();}else if (paramAnn.annotationType().getSimpleName().startsWith("Valid")) {validate = true;Object value = AnnotationUtils.getValue(paramAnn);validationHints = (value instanceof Object[] ? (Object[]) value : new Object[] {value});}}if (annotationsFound > 1) {throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +"do not specify more than one such annotation on the same parameter: " + handlerMethod);}if (annotationsFound == 0) {//解析普通参数,返回值为ObjectObject argValue = resolveCommonArgument(methodParam, webRequest);if (argValue != WebArgumentResolver.UNRESOLVED) {args[i] = argValue;}else if (defaultValue != null) {args[i] = resolveDefaultValue(defaultValue);}else {Class<?> paramType = methodParam.getParameterType();if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {if (!paramType.isAssignableFrom(implicitModel.getClass())) {throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " +"Model or Map but is not assignable from the actual model. You may need to switch " +"newer MVC infrastructure classes to use this argument.");}args[i] = implicitModel;}else if (SessionStatus.class.isAssignableFrom(paramType)) {args[i] = this.sessionStatus;}else if (HttpEntity.class.isAssignableFrom(paramType)) {args[i] = resolveHttpEntityRequest(methodParam, webRequest);}else if (Errors.class.isAssignableFrom(paramType)) {throw new IllegalStateException("Errors/BindingResult argument declared " +"without preceding model attribute. Check your handler method signature!");}//是一个普通参数else if (BeanUtils.isSimpleProperty(paramType)) {paramName = "";}else {attrName = "";}}}if (paramName != null) {//解析参数、判断出这是一个普通的参数args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);}else if (headerName != null) {args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);}else if (requestBodyFound) {args[i] = resolveRequestBody(methodParam, webRequest, handler);}else if (cookieName != null) {args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);}else if (pathVarName != null) {args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);}else if (attrName != null) {WebDataBinder binder =resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));if (binder.getTarget() != null) {doBind(binder, webRequest, validate, validationHints, !assignBindingResult);}args[i] = binder.getTarget();if (assignBindingResult) {args[i + 1] = binder.getBindingResult();i++;}implicitModel.putAll(binder.getBindingResult().getModel());}}return args;}



解析参数,调用本类的resolveRequestParam方法
//解析参数private Object resolveRequestParam(String paramName, boolean required, String defaultValue,MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)throws Exception {Class<?> paramType = methodParam.getParameterType();if (Map.class.isAssignableFrom(paramType) && paramName.length() == 0) {return resolveRequestParamMap((Class<? extends Map<?, ?>>) paramType, webRequest);}if (paramName.length() == 0) {//获取参数名paramName = getRequiredParameterName(methodParam);}Object paramValue = null;MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);if (multipartRequest != null) {List<MultipartFile> files = multipartRequest.getFiles(paramName);if (!files.isEmpty()) {paramValue = (files.size() == 1 ? files.get(0) : files);}}if (paramValue == null) {//解析值String[] paramValues = webRequest.getParameterValues(paramName);if (paramValues != null) {paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);}}if (paramValue == null) {if (defaultValue != null) {paramValue = resolveDefaultValue(defaultValue);}else if (required) {raiseMissingParameterException(paramName, paramType);}paramValue = checkValue(paramName, paramValue, paramType);}WebDataBinder binder = createBinder(webRequest, null, paramName);initBinder(handlerForInitBinderCall, paramName, binder, webRequest);return binder.convertIfNecessary(paramValue, paramType, methodParam);}

解析值调用ServletWebRequest的getParameterValues方法
//解析值,就是使用request.getParameterValues()方法@Overridepublic String[] getParameterValues(String paramName) {return getRequest().getParameterValues(paramName);}


底层原理:
目标方法的参数没有标注任何注解,没有任何要特殊处理的类型,就是一个普通参数。
普通参数的值,直接从request域对象带来的参数中获取,也就是调用request.getParameterValues()方法。request中没有带这个参数就返回null。


原创粉丝点击