项目中使用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 中,建议看一看