1. 程式人生 > >springmvc為請求處理器的目標引數賦值的過程

springmvc為請求處理器的目標引數賦值的過程

↓在invokeHandlerMethod()方法中呼叫resolveHandlerArguments()方法↓

Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);

↓在resolveHandlerArguments()方法中↓

1. 建立 WebDataBinder 物件

WebDataBinder binder = resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler
);

↓進入resolveModelAttribute()方法↓

(1). 確定 objectName 屬性: 若傳入的 attrName 屬性值為 “”, 則 objectName 為類名第一個字母小寫

    注意: attrName. 若目標方法的 POJO 屬性使用了 @ModelAttribute 來修飾, 則 attrName 值即為 @ModelAttribute的 value 屬性值 
// Bind request parameter onto object...
String name = attrName;
if ("".equals(name)) {
    name =
Conventions.getVariableNameForParameter(methodParam); }

(2). 確定 target 屬性

1> 在 implicitModel 中查詢 attrName 對應的屬性值. 若存在, ok

Object bindObject;
if (implicitModel.containsKey(name)) {
    bindObject = implicitModel.get(name);
}

2> 若不存在: 則驗證當前 Handler 是否使用了 @SessionAttributes 進行修飾, 若使用了, 則嘗試從 Session 中獲取 attrName 所對應的屬性值. 若 session 中沒有對應的屬性值, 則丟擲了異常.

else if (this.methodResolver.isSessionAttribute(name, paramType)) {
    bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
    if (bindObject == null) {
        raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
    }
}

3> 若 Handler 沒有使用 @SessionAttributes 進行修飾, 或 @SessionAttributes 中沒有使用 value 值指定的 key和 attrName 相匹配, 則通過反射建立了 POJO 物件

else {
    bindObject = BeanUtils.instantiateClass(paramType);
}

(3). 建立WebDataBinder 物件

WebDataBinder binder = createBinder(webRequest, bindObject, name);

返回一個WebDataBinder 物件

initBinder(handler, name, binder, webRequest);
return binder;

↓返回到resolveHandlerArguments()方法中↓

2. SpringMVC 把表單的請求引數賦給了 WebDataBinder 的 target 對應的屬性

if (binder.getTarget() != null) {
    doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
}

3.從WebDataBinder中取出target

args[i] = binder.getTarget();

4. SpringMVC 會把 WebDataBinder 的 attrName 和 target 給到 implicitModel,進而傳到 request 域物件中

implicitModel.putAll(binder.getBindingResult().getModel());

↓返回到invokeHandlerMethod()方法中↓

5. 把 WebDataBinder 的 target 即resolveHandlerArguments()方法返回的引數args傳遞給目標方法的入參

Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
handlerMethodToInvoke.invoke(handler, args);