我修改了框架中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);
}
})最终效果:
发送数据:

接受数据并打印

大家可以看下是否能用在实际应用场景中
前几天还有人问题这个功能呢,好像是 @山东小木 问的这个需求,看看这个是否满足 @山东小木 需求