SpringMVC——資料繫結流程
阿新 • • 發佈:2019-02-06
一、流程
Spring MVC 主框架將 ServletRequest • 物件及目標方法的入參例項傳遞給 WebDataBinderFactory 例項,以建立 DataBinder 例項物件2. DataBinder 呼叫裝配在 Spring MVC 上下文中的 ConversionService 元件進行資料型別轉換、資料格式化工作。將 Servlet 中的請求資訊填充到入參物件中3. 呼叫 Validator 元件對已經綁定了請求訊息的入參物件進行資料合法性校驗,並最終生成資料繫結結果BindingData 物件4. Spring MVC 抽取 BindingResult 中的入參物件和校驗錯誤物件,將它們賦給處理方法的響應入參
二、原始碼分析:
public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler { protected final Log logger = LogFactory.getLog(this.getClass()); private final boolean annotationNotRequired; public ModelAttributeMethodProcessor(boolean annotationNotRequired) { this.annotationNotRequired = annotationNotRequired; } public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(ModelAttribute.class) || this.annotationNotRequired && !BeanUtils.isSimpleProperty(parameter.getParameterType()); } public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { String name = ModelFactory.getNameForParameter(parameter); ModelAttribute ann = (ModelAttribute)parameter.getParameterAnnotation(ModelAttribute.class); if (ann != null) { mavContainer.setBinding(name, ann.binding()); } Object attribute = mavContainer.containsAttribute(name) ? mavContainer.getModel().get(name) : this.createAttribute(name, parameter, binderFactory, webRequest); WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name); if (binder.getTarget() != null) { if (!mavContainer.isBindingDisabled(name)) { this.bindRequestParameters(binder, webRequest); } this.validateIfApplicable(binder, parameter); if (binder.getBindingResult().hasErrors() && this.isBindExceptionRequired(binder, parameter)) { throw new BindException(binder.getBindingResult()); } }
Map<String, Object> bindingResultModel = binder.getBindingResult().getModel(); mavContainer.removeAttributes(bindingResultModel); mavContainer.addAllAttributes(bindingResultModel); return binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter); }