1.源码讨论
@Before(BlogValidator.class)
public void save() {
getModel(Blog.class).save();
redirect("/blog");
}
2.@Before(BlogValidator.class)
这段代码是在方法执行前会调用BlogValidator拦截器
public class BlogValidator extends Validator {
protected void validate(Controller controller) {
validateRequiredString("blog.title", "titleMsg", "请输入Blog标题!");
validateRequiredString("blog.content", "contentMsg", "请输入Blog内容!");
}
protected void handleError(Controller controller) {
controller.keepModel(Blog.class);
String actionKey = getActionKey();
if (actionKey.equals("/blog/save"))
controller.render("add.html");
else if (actionKey.equals("/blog/update"))
controller.render("edit.html");
}
}
3.会调用Validator中的intercept方法
Validator validator = null;
try {validator = getClass().newInstance();}
catch (Exception e) {throw new RuntimeException(e);}
validator.controller = invocation.getController();
validator.invocation = invocation;
try {validator.validate(validator.controller);}
catch (ValidateException e) {/* should not be throw */} // short circuit validate need this
if (validator.invalid)
validator.handleError(validator.controller);
else
invocation.invoke();
4. validator.validate(validator.controller)这段代码是关键
validateRequiredString("blog.title", "titleMsg", "请输入Blog标题!");
validateRequiredString("blog.content", "contentMsg", "请输入Blog内容!");
5.validateRequiredString,这个代码非常简单就是request获取参数值,如果为空,放到request中去
/**
* Validate required string.
*/
protected void validateRequiredString(String field, String errorKey, String errorMessage) {
String value = controller.getPara(field);
if (value == null || "".equals(value.trim()))
addError(errorKey, errorMessage);
}
6.当我们这个字段保存填为空的时候,我们就会执行如下代码啦
protected void handleError(Controller controller) {
controller.keepModel(Blog.class);
String actionKey = getActionKey();
if (actionKey.equals("/blog/save"))
controller.render("add.html");
else if (actionKey.equals("/blog/update"))
controller.render("edit.html");
}
7.controller.keepModel(Blog.class);
public Controller keepModel(Class modelClass) {
String modelName = StringKit.firstCharToLowerCase(modelClass.getSimpleName());
keepModel(modelClass, modelName);
return this;
}
8.StringKit.firstCharToLowerCase(modelClass.getSimpleName()) 其实就是首字母小写
9.keepModel(modelClass, modelName);这行代码很简单啦
public Controller keepModel(Class modelClass, String modelName) {
Object model = ModelInjector.inject(modelClass, modelName, request, true);
request.setAttribute(modelName, model);
return this;
}
10.Object model = ModelInjector.inject(modelClass, modelName, request, true);
这段代码就是运用反射给变量注入值
@SuppressWarnings({ "rawtypes", "unchecked" })
public static final <T> T inject(Class<?> modelClass, String modelName, HttpServletRequest request, boolean skipConvertError) {
Object model = null;
try {
model = modelClass.newInstance();
} catch (Exception e) {
throw new ModelInjectException(e);
}
if (model instanceof Model)
injectActiveRecordModel((Model)model, modelName, request, skipConvertError);
else
injectCommonModel(model, modelName, request, modelClass, skipConvertError);
return (T)model;
}
11.上面的代码会执行下面这个方法的代码,下面代码的核心意义就根据数据库表的字段和类型将值放入到Model的Map中
@SuppressWarnings("rawtypes")
private static final void injectActiveRecordModel(Model<?> model, String modelName, HttpServletRequest request, boolean skipConvertError) {
TableInfo tableInfo = TableInfoMapping.me().getTableInfo(model.getClass());
String modelNameAndDot = modelName + ".";
Map<String, String[]> parasMap = request.getParameterMap();
for (Entry<String, String[]> e : parasMap.entrySet()) {
String paraKey = e.getKey();
if (paraKey.startsWith(modelNameAndDot)) {
String paraName = paraKey.substring(modelNameAndDot.length());
Class colType = tableInfo.getColType(paraName);
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);
} catch (Exception ex) {
if (skipConvertError == false)
throw new ModelInjectException("Can not convert parameter: " + modelNameAndDot + paraName, ex);
}
}
}
}