现在jfinal里面获取post有点麻烦,特别是要整个写入model的时候,都要用get
这边目标是使用注解定义controller里面的方法的参数,然后根据注解和参数的类型自动传值,同时解决getFile及访问后删除文件的问题
例如
public void aaa(@ModelPara User user, @PostPara String username, @PostPara String phone)
1.初始化操作
//缓存model字段名称及其数据类型,用于@ModelPara
public static final Map<Class, Map<String, Class>> fieldClassMap = new HashMap();
//定义model类所在位置
public static final String modelPackage = "com.xx.common.model";
public static final String baseModelPackage = "com.xx.common.model.base";
static {
//加载model字段名称及其数据类型
Set<Class<?>> classSet = ClassUtil.scanPackage(baseModelPackage);
for (Class<?> aClass : classSet) {
Method[] methods = aClass.getDeclaredMethods();
LinkedList<Method> getMethodList = new LinkedList<>();
for (Method method : methods) {
if (method.getName().matches("get[A-Z]\\w*")) {
getMethodList.add(method);
}
}
Map<String, Class> map = new HashMap<>(getMethodList.size());
for (Method method : getMethodList) {
String name = method.getName().substring(3);
name = ((char) (name.charAt(0) + 32)) + name.substring(1);
map.put(name, method.getReturnType());
}
try {
fieldClassMap.put(Class.forName(aClass.getTypeName().replace(
baseModelPackage + ".Base", modelPackage + "."
)), map);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// System.out.println(fieldClassMap);
}2.定义拦截函数
@SneakyThrows //忽略抛出异常
@Override
public void intercept(Invocation invocation) {
try {
JSONObject json = null;
if ("POST".equals(invocation.getController().getRequest().getMethod())) {
//获取文件
if (invocation.getController().getRequest().getContentType() != null &&
invocation.getController().getRequest().getContentType().contains("multipart/form-data")) {
invocation.getController().getFiles();
}
//获取post body中的json
if (StrUtil.equals(invocation.getController().getRequest().getContentType(), "application/json")) {
String jsonString = HttpKit.readData(invocation.getController().getRequest());
if (StrUtil.isNotBlank(jsonString)) {
json = JSONObject.parseObject(jsonString);
for (Map.Entry<String, Object> entry : json.entrySet()) {
invocation.getController().setAttr(entry.getKey(), entry.getValue());
}
}
invocation.getController().setAttr("postJson", jsonString);
}
}
if (json == null) {
json = new JSONObject();
}
//获取form-data和get参数
for (Map.Entry<String, String[]> entry : invocation.getController().getParaMap().entrySet()) {
if (entry.getValue() != null && entry.getValue().length > 0) {
json.put(entry.getKey(), entry.getValue()[0]);
}
}
//设置注解
setAnnotation(invocation, json);
invocation.invoke();
} catch (CustomException e1) {
throw e1;
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e2) {
e2.printStackTrace();
throw new Exception("POST映射错误:" + e2.getMessage());
}
//删除上传的文件
try {
if (invocation.getController().getRequest().getContentType().contains("multipart/form-data")) {
for (UploadFile uploadFile : invocation.getController().getFiles()) {
uploadFile.getFile().delete();
}
}
} catch (Exception e) {
}
}3.定义根据注解传参的函数
private void setAnnotation(Invocation invocation, JSONObject json) throws CustomException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
for (int index = 0; index < invocation.getMethod().getParameters().length; index++) {
Parameter parameter = invocation.getMethod().getParameters()[index];
if (parameter.getAnnotation(ModelPara.class) != null) {
//ModelPara类型的注解
Object instance = parameter.getType().getDeclaredConstructor().newInstance();
Method setParaMethod = parameter.getType().getMethod("set", String.class, Object.class);
for (Map.Entry<String, Object> entry : json.entrySet()) {
Object o = entry.getValue();
Class c = fieldClassMap.get(parameter.getType()).get(entry.getKey());
if (c != null) {
//参数类型转化
o = BaseDataConvertUtil.convert(o, c);
try {
setParaMethod.invoke(instance, entry.getKey(), o);
} catch (InvocationTargetException e) {
if (e.getCause() == null || e.getCause().getMessage() == null || !e.getCause().getMessage().contains("The attribute name does not exist")) {
throw e;
}
}
}
}
invocation.setArg(index, instance);
} else if (parameter.getAnnotation(PostPara.class) != null) {
//PostPara类型的注解
Object o = json.get(parameter.getName());
if (o != null) {
if (parameter.getType().isAssignableFrom(o.getClass())) {
invocation.setArg(index, o);
} else {
//参数类型转化
if (!BaseDataConvertUtil.inConvertType(o)) {
o = o.toString();
}
o = BaseDataConvertUtil.convert(o, parameter.getType());
if (o != null) {
if (parameter.getType().isAssignableFrom(o.getClass())) {
invocation.setArg(index, o);
} else {
//字段类型错误:%s,应为%s或其子类
throw new CustomException(ErrorCodeConstant.B1002, parameter.getName(),
parameter.getType().getSimpleName());
}
}
}
}
} else {
// invocation.setArg(index, null);
}
}
}4.基本参数自动转化(复杂的参数就直接是jsonobject或jsonarray了)
public class BaseDataConvertUtil {
public static Set<Class> classSet = new HashSet<>();
static {
classSet.add(String.class);
classSet.add(Double.class);
classSet.add(Integer.class);
classSet.add(BigDecimal.class);
classSet.add(Long.class);
classSet.add(Boolean.class);
classSet.add(Date.class);
}
//是否是可转化的类型
public static boolean inConvertType(Object object) {
return object == null ||
classSet.contains(object.getClass());
}
//自动转化
public static Object convert(Object object, Class<?> c) {
if (object == null)
return null;
else if (object.getClass().equals(c)) {
return object;
} else if (c == String.class) {
if (object instanceof Date)
return DateUtil.formatDateTime((Date) object);
return object.toString();
} else if (c == Double.class) {
if (object instanceof Integer)
return ((Integer) object).doubleValue();
if (object instanceof Double)
return object;
if (object instanceof Long)
return ((Long) object).doubleValue();
if (object instanceof BigDecimal)
return ((BigDecimal) object).doubleValue();
if (object instanceof Boolean)
return (Boolean) object ? 1.0D : 0.0D;
if (object instanceof Date)
return (double) ((Date) object).getTime();
try {
return Double.valueOf(object.toString());
} catch (Exception e) {
return null;
}
} else if (c == Integer.class) {
if (object instanceof Integer)
return object;
if (object instanceof Double)
return ((Double) object).intValue();
if (object instanceof Long)
return ((Long) object).intValue();
if (object instanceof BigDecimal)
return ((BigDecimal) object).intValue();
if (object instanceof Boolean)
return (Boolean) object ? 1 : 0;
if (object instanceof Date)
return (int) ((Date) object).getTime();
try {
return Integer.valueOf(object.toString());
} catch (Exception e) {
return null;
}
} else if (c == Long.class) {
if (object instanceof Integer)
return ((Integer) object).longValue();
if (object instanceof Double)
return ((Double) object).longValue();
if (object instanceof Long)
return object;
if (object instanceof BigDecimal)
return ((BigDecimal) object).longValue();
if (object instanceof Boolean)
return (Boolean) object ? 1L : 0L;
if (object instanceof Date)
return ((Date) object).getTime();
try {
return Long.valueOf(object.toString());
} catch (Exception e) {
return null;
}
} else if (c == Boolean.class) {
if (object instanceof Integer)
return !object.equals(0);
if (object instanceof Double)
return !object.equals(0D);
if (object instanceof Long)
return !object.equals(0L);
if (object instanceof BigDecimal)
return ((BigDecimal) object).intValue() != 1;
if (object instanceof Boolean)
return object;
if (object instanceof Date)
return object != null;
try {
return "true".equals(object.toString()) || "1".equals(object.toString());
} catch (Exception e) {
return null;
}
} else if (c == Date.class) {
if (object instanceof Integer)
return new Date((Integer) object);
if (object instanceof Double)
return new Date(((Double) object).longValue());
if (object instanceof Long)
return new Date((Long) object);
if (object instanceof BigDecimal)
return new Date(((BigDecimal) object).longValue());
if (object instanceof Boolean)
return (Boolean) object ? new Date() : null;
if (object instanceof Date)
return object;
try {
return DateUtil.parse(object.toString());
} catch (Exception e) {
return null;
}
}
return object;
}
public static Integer convertToInteger(Object object) {
return (Integer) convert(object, Integer.class);
}
public static Double convertToDouble(Object object) {
return (Double) convert(object, Double.class);
}
public static String convertToString(Object object) {
return (String) convert(object, String.class);
}
public static Long convertToLong(Object object) {
return (Long) convert(object, Long.class);
}
public static void main(String[] args) {
Object object = convert(1.0, Integer.class);
System.out.println(object);
System.out.println(object.getClass());
}
}拦截器完整类
package com.xx.interceptor;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.xx.annotation.ModelPara;
import com.xx.annotation.PostPara;
import com.xx.constant.ErrorCodeConstant;
import com.xx.exception.CustomException;
import com.xx.util.BaseDataConvertUtil;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.HttpKit;
import com.jfinal.upload.UploadFile;
import lombok.SneakyThrows;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
public class PostParaInterceptor implements Interceptor {
/**
* 缓存model字段名称及其数据类型,用于@ModelPara
*/
public static final Map<Class, Map<String, Class>> fieldClassMap = new HashMap();
/**
* 定义model类所在位置
*/
public static final String modelPackage = "com.xx.common.model";
public static final String baseModelPackage = "com.xx.common.model.base";
static {
//加载model字段名称及其数据类型
Set<Class<?>> classSet = ClassUtil.scanPackage(baseModelPackage);
for (Class<?> aClass : classSet) {
Method[] methods = aClass.getDeclaredMethods();
LinkedList<Method> getMethodList = new LinkedList<>();
for (Method method : methods) {
if (method.getName().matches("get[A-Z]\\w*")) {
getMethodList.add(method);
}
}
Map<String, Class> map = new HashMap<>(getMethodList.size());
for (Method method : getMethodList) {
String name = method.getName().substring(3);
name = ((char) (name.charAt(0) + 32)) + name.substring(1);
map.put(name, method.getReturnType());
}
try {
fieldClassMap.put(Class.forName(aClass.getTypeName().replace(
baseModelPackage + ".Base", modelPackage + "."
)), map);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// System.out.println(fieldClassMap);
}
@SneakyThrows //忽略抛出异常
@Override
public void intercept(Invocation invocation) {
try {
JSONObject json = null;
if ("POST".equals(invocation.getController().getRequest().getMethod())) {
//获取文件
if (invocation.getController().getRequest().getContentType() != null &&
invocation.getController().getRequest().getContentType().contains("multipart/form-data")) {
invocation.getController().getFiles();
}
//获取post body中的json
if (StrUtil.equals(invocation.getController().getRequest().getContentType(), "application/json")) {
String jsonString = HttpKit.readData(invocation.getController().getRequest());
if (StrUtil.isNotBlank(jsonString)) {
json = JSONObject.parseObject(jsonString);
for (Map.Entry<String, Object> entry : json.entrySet()) {
invocation.getController().setAttr(entry.getKey(), entry.getValue());
}
}
invocation.getController().setAttr("postJson", jsonString);
}
}
if (json == null) {
json = new JSONObject();
}
//获取form-data和get参数
for (Map.Entry<String, String[]> entry : invocation.getController().getParaMap().entrySet()) {
if (entry.getValue() != null && entry.getValue().length > 0) {
json.put(entry.getKey(), entry.getValue()[0]);
}
}
//设置注解
setAnnotation(invocation, json);
invocation.invoke();
} catch (CustomException e1) {
throw e1;
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e2) {
e2.printStackTrace();
throw new Exception("POST映射错误:" + e2.getMessage());
}
//删除上传的文件
try {
if (invocation.getController().getRequest().getContentType().contains("multipart/form-data")) {
for (UploadFile uploadFile : invocation.getController().getFiles()) {
uploadFile.getFile().delete();
}
}
} catch (Exception e) {
}
}
private void setAnnotation(Invocation invocation, JSONObject json) throws CustomException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
for (int index = 0; index < invocation.getMethod().getParameters().length; index++) {
Parameter parameter = invocation.getMethod().getParameters()[index];
if (parameter.getAnnotation(ModelPara.class) != null) {
//ModelPara类型的注解
Object instance = parameter.getType().getDeclaredConstructor().newInstance();
Method setParaMethod = parameter.getType().getMethod("set", String.class, Object.class);
for (Map.Entry<String, Object> entry : json.entrySet()) {
Object o = entry.getValue();
Class c = fieldClassMap.get(parameter.getType()).get(entry.getKey());
if (c != null) {
//参数类型转化
o = BaseDataConvertUtil.convert(o, c);
try {
setParaMethod.invoke(instance, entry.getKey(), o);
} catch (InvocationTargetException e) {
if (e.getCause() == null || e.getCause().getMessage() == null || !e.getCause().getMessage().contains("The attribute name does not exist")) {
throw e;
}
}
}
}
invocation.setArg(index, instance);
} else if (parameter.getAnnotation(PostPara.class) != null) {
//PostPara类型的注解
Object o = json.get(parameter.getName());
if (o != null) {
if (parameter.getType().isAssignableFrom(o.getClass())) {
invocation.setArg(index, o);
} else {
//参数类型转化
if (!BaseDataConvertUtil.inConvertType(o)) {
o = o.toString();
}
o = BaseDataConvertUtil.convert(o, parameter.getType());
if (o != null) {
if (parameter.getType().isAssignableFrom(o.getClass())) {
invocation.setArg(index, o);
} else {
//字段类型错误:%s,应为%s或其子类
throw new CustomException(ErrorCodeConstant.B1002, parameter.getName(),
parameter.getType().getSimpleName());
}
}
}
}
} else {
// invocation.setArg(index, null);
}
}
}
}ModelPara类
package com.xx.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface ModelPara {
}PostPara类
package com.xx.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface PostPara {
}