项目中使用springboot2.x + enjoy4.2 渲染界面时发现 由于 实体首字母小写,生成的getter,setter方法问题 导致在页面上取值为空的情况。
如:实体类
package com.jfinal.template;
public class Proceeding {
private String fName ;
private String fDepartmentId ;
public String getfName() {
return fName;
}
public void setfName(String fName) {
this.fName = fName;
}
public String getfDepartmentId() {
return fDepartmentId;
}
public void setfDepartmentId(String fDepartmentId) {
this.fDepartmentId = fDepartmentId;
}
} |
外部使用enjoy
package com.jfinal.template;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
public class PrintTest {
@Test public void query() {
Proceeding proceeding = new Proceeding();
proceeding.setfName("固定资产投资项目节能审查");
proceeding.setfDepartmentId("ACCF99B7-ACBD-AC92-47D9-CE6698469C58");
Map<String, Object> data = new HashMap<String, Object>();
data.put("proceeding", proceeding);
Engine engine = Engine.create("myEngine2");
engine.setDevMode(true);
engine.setToClassPathSourceFactory();
Template template = engine.getTemplate("p.txt");
String wxAppMsg = template.renderToString(data);
System.out.println(wxAppMsg);
}
} |
页面:
#(proceeding) <tr> <td>事项名称<span>*</span></td> <td><span>#(proceeding.fName??"暂无")</span></td> <td>事项编码</td> <td>#(proceeding.fDepartmentId??"暂无")</td> </tr> |
渲染结果:
com.jfinal.template.Proceeding@4b952a2d <tr> <td>事项名称<span>*</span></td> <td><span>暂无</span></td> <td>事项编码</td> <td>暂无</td> </tr> |
跟踪源码发现enjoy在取值时通过 get + 表达式字段组装出(首字母做大大写转换)“get方法名” 去匹配 实体中的getter方法来取值。
public FieldGetter takeOver(Class<?> targetClass, String fieldName) {
if (MethodKit.isForbiddenClass(targetClass)) {
throw new RuntimeException("Forbidden class: " + targetClass.getName());
}
String getterName = "get" + StrKit.firstCharToUpperCase(fieldName);
java.lang.reflect.Method[] methodArray = targetClass.getMethods();
for (java.lang.reflect.Method method : methodArray) {
if (method.getName().equals(getterName) && method.getParameterTypes().length == 0) {
// if (MethodKit.isForbiddenMethod(getterName)) {
// throw new RuntimeException("Forbidden method: " + getterName);
// }
return new GetterMethodFieldGetter(method);
}
}
return null;
} |
其中:
String getterName = "get" + StrKit.firstCharToUpperCase(fieldName);
如我的实体中 enjoy 组装出来的 get方法分别为 getFName 而实体中生成的为 getfName 这样就匹配不上了,值也就取不到了。
虽然在返回页面前先把实体转map可以解决问题,但本人涉及的项目实体较多都是这种情况。是否有其他的解决办法嗯?
另外尝试过修改enjoy源码为下所示,能够取值,波总这种方式是否可行嗯?
public FieldGetter takeOver(Class<?> targetClass, String fieldName) {
if (MethodKit.isForbiddenClass(targetClass)) {
throw new RuntimeException("Forbidden class: " + targetClass.getName());
}
String getterName = "get" + StrKit.firstCharToUpperCase(fieldName);
java.lang.reflect.Method[] methodArray = targetClass.getMethods();
for (java.lang.reflect.Method method : methodArray) {
if ((method.getName().equals(getterName) && method.getParameterTypes().length == 0)
|| (method.getName().equals("get"+fieldName) && method.getParameterTypes().length == 0)) {
// if (MethodKit.isForbiddenMethod(getterName)) {
// throw new RuntimeException("Forbidden method: " + getterName);
// }
return new GetterMethodFieldGetter(method);
}
}
return null;
}
public class MyFieldGetter extends FieldGetters.GetterMethodFieldGetter {
...
}
然后在里头填上你自己改进过的 takeOver 方法,最后配置一下:
Engine.addFieldGetter(1, new MyFieldGetter());
注意添加的时候,第一个参数很重要,这个关系到优先级,你的 MyFieldGetter 优先级要高于 GetterMethodFieldGetter,对于 jfinal 4.2 来说传入 1 即可,因为优先级最高的 0 为:RealFieldGetter
你的这个 MyFieldGetter 要配置在 RealFieldGetter 之后最合适,相关源码在 : com.jfinal.template.expr.ast.FieldGetters.java 中,建议看一看