我修改了框架中getBean的实现
写一个ApiController继承Controller并且重写getBean方法
public class ApiController extends Controller { protected void get() { renderJson(Constant.method404); } protected void post() { renderJson(Constant.method404); } protected void delete() { renderJson(Constant.method404); } protected void put() { renderJson(Constant.method404); } @Before(Tx.class) public void index() throws Exception { String method = getRequest().getMethod(); if (Constant.POST.equalsIgnoreCase(method)) { post(); } else if (Constant.GET.equalsIgnoreCase(method)) { get(); } else if (Constant.DELETE.equalsIgnoreCase(method)) { delete(); } else if (Constant.PUT.equalsIgnoreCase(method)) { put(); } else { renderJson(Constant.method404); } } /** * 重写getBean方法 * @param beanClass * @param beanName * @param <T> * @return */ @Override public <T> T getBean(Class<T> beanClass, String beanName) { return (T) InjectorCore.injectBean(beanClass, beanName, this.getRequest(), false); } }
新建一个InjectorCore并实现一个injectBean方法
public class InjectorCore { private static <T> T createInstance(Class<T> objClass) { try { return objClass.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") public static final <T> T injectBean(Class<T> beanClass, String beanName, HttpServletRequest request, boolean skipConvertError) { Object bean = createInstance(beanClass); TypeConverterCore converter = TypeConverterCore.me(); Map<String, String[]> parasMap = request.getParameterMap(); injectBean(bean, beanClass, parasMap, beanName, converter, request, skipConvertError); return (T) bean; } private static boolean injectBean(Object bean, Class<?> beanClass, Map<String, String[]> parasMap, String beanName, TypeConverterCore converter, HttpServletRequest request, boolean skipConvertError) { String modelNameAndDot = StrKit.notBlank(beanName) ? beanName + "[%s]" : null;//产生用于获取参数值的前缀 Method[] methods = beanClass.getMethods();//获取要塞入参数的class内的方法 boolean isEmpty = true;//true表示这个bean里面没有内容,false表示有内容 for (Method method : methods) { String methodName = method.getName(); if (methodName.startsWith("set") == false || methodName.length() <= 3) { // only setter method continue; } Class<?>[] types = method.getParameterTypes();//获取方法返回值类型 if (types.length != 1) { continue; } //获取方法名,去掉set String attrName = StrKit.firstCharToLowerCase(methodName.substring(3)); String paraName = modelNameAndDot != null ? String.format(modelNameAndDot, attrName) : attrName; Class<?> type = types[0]; if (!converter.isExistence(type) && type != String.class) {//如果返回类型不是普通类型,则进行单独处理 Object newbean = null; if (type == List.class) { newbean = injectListBean(beanClass, parasMap, attrName, paraName, converter, request, skipConvertError); } else { newbean = createInstance(type); injectBean(newbean, type, parasMap, paraName, converter, request, skipConvertError); } try { method.invoke(bean, newbean); } catch (Exception e) { if (skipConvertError == false) { throw new RuntimeException(e); } } continue; } //如果不是特殊类型和自定义类型则从request中获取参数放入bean中 if (parasMap.containsKey(paraName)) { try { String paraValue = request.getParameter(paraName); if (!StringUtils.isNotNull(paraValue)) { continue; } Object value = paraValue != null ? converter.convert(type, paraValue) : null; method.invoke(bean, value); isEmpty = false; } catch (Exception e) { if (skipConvertError == false) { throw new RuntimeException(e); } } } } return isEmpty; } private static List<Object> injectListBean(Class<?> type, Map<String, String[]> parasMap, String attrName, String paraName, TypeConverterCore converter, HttpServletRequest request, boolean skipConvertError) { Field[] fields = type.getDeclaredFields(); List<Object> list = new ArrayList<>(); for (Field f : fields) { Class fieldClazz = f.getType(); if (fieldClazz.isAssignableFrom(List.class) && f.getName().equals(attrName)) {//如果是list类型并且与要查询的参数名相同 Type fc = f.getGenericType(); ParameterizedType pt = (ParameterizedType) fc; Class<?> genericClazz = (Class) pt.getActualTypeArguments()[0];//获取到list中的泛型 if (converter.isExistence(genericClazz) || genericClazz == String.class) { boolean isEmpty = false; while (!isEmpty) { String keyName = paraName + "[]"; String[] vals = parasMap.get(keyName); if (vals != null) { for (String v : vals) { Object vvalue = null; try { vvalue = v != null ? converter.convert(genericClazz, v) : null; } catch (ParseException e) { e.printStackTrace(); } list.add(vvalue); } } isEmpty = true; } break; } if (fc instanceof ParameterizedType) {//如果是泛型参数的类型 //开始走获取列表中泛型数据的流程 boolean isEmpty = false; int i = 0; while (!isEmpty) { Object beanListT = createInstance(genericClazz); String keyName = paraName + "[" + i + "]"; isEmpty = injectBean(beanListT, genericClazz, parasMap, keyName, converter, request, skipConvertError); if (isEmpty) { break; } list.add(beanListT); i++; } } break; } } return list; } }
新建一个TypeConverterCore用来保存和处理不同类型参数的判断与转换(我看到新的代码里对应的com.jfinal.core.converter.TypeConverter中新增的几种类型可以使用新的替换掉private TypeConverterCore()部分)
public class TypeConverterCore{ private final Map<Class<?>, IConverter<?>> converterMap = new HashMap<Class<?>, IConverter<?>>(); private static TypeConverterCore me = new TypeConverterCore(); private TypeConverterCore() { regist(Integer.class, new Converters.IntegerConverter()); regist(int.class, new Converters.IntegerConverter()); regist(Long.class, new Converters.LongConverter()); regist(long.class, new Converters.LongConverter()); regist(Double.class, new Converters.DoubleConverter()); regist(double.class, new Converters.DoubleConverter()); regist(Float.class, new Converters.FloatConverter()); regist(float.class, new Converters.FloatConverter()); regist(Boolean.class, new Converters.BooleanConverter()); regist(boolean.class, new Converters.BooleanConverter()); regist(java.util.Date.class, new Converters.DateConverter()); regist(java.sql.Date.class, new Converters.SqlDateConverter()); regist(java.sql.Time.class, new Converters.TimeConverter()); regist(java.sql.Timestamp.class, new Converters.TimestampConverter()); regist(java.math.BigDecimal.class, new Converters.BigDecimalConverter()); regist(java.math.BigInteger.class, new Converters.BigIntegerConverter()); } public static TypeConverterCore me() { return me; } public <T> void regist(Class<T> type, IConverter<T> converter) { converterMap.put(type, converter); } /** * 将 String 数据转换为指定的类型 * @param type 需要转换成为的数据类型 * @param s 被转换的 String 类型数据,注意: s 参数不接受 null 值,否则会抛出异常 * @return 转换成功的数据 */ public final Object convert(Class<?> type, String s) throws ParseException { // mysql type: varchar, char, enum, set, text, tinytext, mediumtext, longtext if (type == String.class) { return ("".equals(s) ? null : s); // 用户在表单域中没有输入内容时将提交过来 "", 因为没有输入,所以要转成 null. } s = s.trim(); if ("".equals(s)) { // 前面的 String跳过以后,所有的空字符串全都转成 null, 这是合理的 return null; } // 以上两种情况无需转换,直接返回, 注意, 本方法不接受null为 s 参数(经测试永远不可能传来null, 因为无输入传来的也是"") //String.class提前处理 // -------- IConverter<?> converter = converterMap.get(type); if (converter != null) { return converter.convert(s); } if (JFinal.me().getConstants().getDevMode()) { throw new RuntimeException("Please add code in " + TypeConverter.class + ". The type can't be converted: " + type.getName()); } else { throw new RuntimeException(type.getName() + " can not be converted, please use other type of attributes in your model!"); } } /** * 通过传入的type来判断是否是需要通过转化的类型 * @param type 需要转换成为的数据类型 * @return 是否存在 */ public boolean isExistence(Class<?> type){ boolean b=converterMap.containsKey(type); return b; } }
一下是测试代码
Entityone.java
public class Entityone implements Serializable { private static final long serialVersionUID = -8438235889469075812L; private String entityname; private int a; private boolean b; private List<Entitythree> list; private Entitytwo entitytwo; public List<Entitythree> getList() { return list; } public void setList(List<Entitythree> list) { this.list = list; } public String getEntityname() { return entityname; } public void setEntityname(String entityname) { this.entityname = entityname; } public int getA() { return a; } public void setA(int a) { this.a = a; } public boolean isB() { return b; } public void setB(boolean b) { this.b = b; } public Entitytwo getEntitytwo() { return entitytwo; } public void setEntitytwo(Entitytwo entitytwo) { this.entitytwo = entitytwo; } }
Entitytwo.java
public class Entitytwo implements Serializable { private static final long serialVersionUID = 6211438465654735844L; private String nametow; private List<Entitythree> list; private List<String> lists; public List<String> getLists() { return lists; } public void setLists(List<String> lists) { this.lists = lists; } public String getNametow() { return nametow; } public void setNametow(String nametow) { this.nametow = nametow; } public List<Entitythree> getList() { return list; } public void setList(List<Entitythree> list) { this.list = list; } }
Entitythree.java
public class Entitythree implements Serializable { private static final long serialVersionUID = 7135457012628287367L; private String ccc; private int a; public String getCcc() { return ccc; } public void setCcc(String ccc) { this.ccc = ccc; } public int getA() { return a; } public void setA(int a) { this.a = a; } }
TestController.java
public class TestController extends ApiController { public void ajax2() { Entityone entityone = getBean(Entityone.class, ""); renderJson(entityone.getList()); } }
ajax:
$.ajax({ type: "post", url: "/test/ajax2", data: { "a": 1, "b": false, "entitytwo": { "list": [{"a": 33, "ccc": "ccccc"}, {"a": 33, "ccc": "ccccc"}], "nametow": "2222", "lists": ["aaaa", "bbbb"] }, "list": [{"a": 33, "ccc": "ccccc"}, {"a": 33, "ccc": "ccccc"}] }, dataType: "json", success: function (data) { console.log(data); } })
最终效果:
发送数据:
接受数据并打印
大家可以看下是否能用在实际应用场景中
前几天还有人问题这个功能呢,好像是 @山东小木 问的这个需求,看看这个是否满足 @山东小木 需求