<input type="text" name="user.name"/>
String name = request.getParameter("user.name"); User user = new User(); user.setName(name);
User u = getModel(User.class);
getModel方法是繼承自Controller,注入的具體實如今ModelInjector類中 html
/** * Get model from http request. */ public <T> T getModel(Class<T> modelClass) { return (T)ModelInjector.inject(modelClass, request, false); }
2.ModelInjector 表單數據注入的具體實現類 java
經過傳入的 model.class 獲得 model類的全部方法,而後找到屬性所對應的set方法,將request取到的值轉換爲對應的數據類型,最後把值賦給model類 app
final class ModelInjector { public static <T> T inject(Class<?> modelClass, HttpServletRequest request, boolean skipConvertError) { String modelName = modelClass.getSimpleName(); return inject(modelClass, StringKit.firstCharToLowerCase(modelName), request, skipConvertError); } @SuppressWarnings({ "rawtypes", "unchecked" }) public static final <T> T inject(Class<?> modelClass, String modelName, HttpServletRequest request, boolean skipConvertError) { Object model = null; try { model = modelClass.newInstance();//採用反射建立一個model的實例 } catch (Exception e) { throw new RuntimeException(e); } if (model instanceof Model) injectActiveRecordModel((Model)model, modelName, request, skipConvertError);//繼承Model類注入表單數據的實現 else injectCommonModel(model, modelName, request, modelClass, skipConvertError);//普通Moedl類注入表單數據的實現 return (T)model; } private static final void injectCommonModel(Object model, String modelName, HttpServletRequest request, Class<?> modelClass, boolean skipConvertError) { Method[] methods = modelClass.getMethods();//得到Model類的全部方法 for (Method method : methods) { String methodName = method.getName();//方法名 //只有實現了屬性對應的set方法而且傳入的參數爲一個的時候才能把form裏的數據注入到對應的model屬性上 if (methodName.startsWith("set") == false) // only setter method continue; Class<?>[] types = method.getParameterTypes(); if (types.length != 1) // only one parameter continue; String attrName = methodName.substring(3); String value = request.getParameter(modelName + "." + StringKit.firstCharToLowerCase(attrName));//拼接出model.屬性(JFinal默認form裏數據名必須是類名.屬性)這樣才能用request取到對應的值 if (value != null) { try { method.invoke(model, TypeConverter.convert(types[0], value));//TypeConverter將value值轉換成類屬性對應的數據類型,執行model的method方法將value set到model的屬性上 } catch (Exception e) { if (skipConvertError == false) throw new RuntimeException(e); } } } } @SuppressWarnings("rawtypes") private static final void injectActiveRecordModel(Model<?> model, String modelName, HttpServletRequest request, boolean skipConvertError) { TableInfo tableInfo = TableInfoMapping.me().getTableInfo(model.getClass());//TableInfo保存有Model類的全部屬性,至關於一個Model實例 String modelNameAndDot = modelName + "."; Map<String, String[]> parasMap = request.getParameterMap(); for (Entry<String, String[]> e : parasMap.entrySet()) {//request中的數據是以key-value的方式保存的,遍歷提交來form的全部數據 String paraKey = e.getKey(); if (paraKey.startsWith(modelNameAndDot)) {//知足「類.屬性」格式的的數據才能被識別保存到model中 String paraName = paraKey.substring(modelNameAndDot.length()); Class colType = tableInfo.getColType(paraName);//從tableInfo中查找 屬性對應的type if (colType == null) throw new ActiveRecordException("The model attribute " + paraKey + " is not exists."); String[] paraValue = e.getValue();//取數據 try { // Object value = Converter.convert(colType, paraValue != null ? paraValue[0] : null); Object value = paraValue[0] != null ? TypeConverter.convert(colType, paraValue[0]) : null;//將數據轉換爲正確類型 model.set(paraName, value);//保存數據到model裏 } catch (Exception ex) { if (skipConvertError == false) throw new RuntimeException("Can not convert parameter: " + modelNameAndDot + paraName, ex); } } } } }