赞
踩
下面这段代码大家应该都搜到过了:
- /**
- * 动态修改Excel标题
- * @param clzz
- * @param filedName
- * @param valueArr
- */
- public static void setHeadValue(Class clzz, String filedName, String[] valueArr ) {
- try {
- //获取field
- Field filed = clzz.getDeclaredField(filedName);
- filed.setAccessible(true);
- //获取注解
- ExcelProperty annotation = filed.getAnnotation(ExcelProperty.class);
- InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
- Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
- memberValues.setAccessible(true);
- Map<String, Object> map = (Map<String, Object>) memberValues.get(invocationHandler);
- map.put("value", valueArr);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
但是大家可能发现最后在写excel时,实体xxxVo.class中还是之前的值。
哈哈哈我也遇到了这个问题,已经解决了,现在将原因和方法告诉大家。
实际上,反射修改的只是CLASS对象,并没有修改相应类的字节码。因此下面引入Javassist技术,修改类的字节码。
使用Javassist动态重新加载CLASS,需开启JDWP(-agentlib:jdwp),注意new HotSwapper()会建立长链接占用设置的端口(8000),如果是多次重新加载CLASS,HotSwapper只需实例化一次,所以设计成单例模式。
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000
- import com.alibaba.excel.annotation.ExcelProperty;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.ClassClassPath;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.ClassPool;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.CtClass;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.CtField;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.bytecode.AnnotationsAttribute;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.bytecode.ConstPool;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.bytecode.FieldInfo;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.bytecode.annotation.Annotation;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.bytecode.annotation.ArrayMemberValue;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.bytecode.annotation.MemberValue;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.bytecode.annotation.StringMemberValue;
- import com.alibaba.ttl.threadpool.agent.internal.javassist.util.HotSwapper;
-
- import java.util.List;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentMap;
-
-
- public class JavassistUtils {
-
- public static ConcurrentMap<String, HotSwapper> hotSwapperMap = new ConcurrentHashMap<>();
-
- public static HotSwapper getHotSwapper() {
- HotSwapper hotSwapper = hotSwapperMap.get("HotSwapper");
- try {
- if (hotSwapper == null) {
- hotSwapper = new HotSwapper(8000);
- hotSwapperMap.put("HotSwapper",hotSwapper);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return hotSwapper;
- }
-
-
- /**
- * 重新加载class
- * @param clzz
- */
- public static Class reLoadClass(Class clzz) {
- try {
- // //file:/home/ipm-starter/ipm-starter.jar!/BOOT-INF/classes!/
- // ///E:/idea project/ipd-ShuiXing/ipd-ipm/ipm-starter/target/classes/
- // Resource resourceObj = ResourceUtil.getResourceObj(".");
- // String classPath = URLDecoder.decode(resourceObj.getUrl().getPath(), "UTF-8").replaceAll("file:", "").replaceAll("ipm-starter.jar!/BOOT-INF/classes!/", "");
-
- ClassPool pool = ClassPool.getDefault();
- pool.insertClassPath(new ClassClassPath(clzz));
- CtClass ct = pool.get(clzz.getName());
- byte[] bytes = ct.toBytecode();
- // ct.writeFile(classPath);
- ct.detach();
-
- //如果在同一个ClassLoader加载两次Class抛出异常
- // Class<?> aClass = ct.toClass();
-
- //反射拿到的是代理类,所以拿不到对应的注解。在根据反射机制拿取类里对应的属性时,这个类要看有没被做过代理。
- // URLClassLoader loader = new URLClassLoader(new URL[]{new URL("file://" + classPath)});
- // clzz = loader.loadClass(clzz.getName());
-
- // Loader cl = new Loader(pool);
- // clzz = cl.loadClass(clzz.getName());
-
- // HotSwapper hotSwapper = JavassistUtils.getHotSwapper();
- // hotSwapper.reload(clzz.getName(), bytes);
-
-
- // //使用Instrumentation和Javassist修改web应用字节码 https://blog.csdn.net/helowken2/article/details/103110368
- // // 通过读入的class数据输入流实例化类定义对象
- // ClassDefinition reporterDef = new ClassDefinition(Class.forName(clzz.getName()), ct.toBytecode());
- // // 使用jvm监视对象重新定义类
- // instrumentation.redefineClasses(reporterDef);
-
- return clzz;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
-
- /**
- * 动态修改ExcelProperty注解属性
- * @param clzz
- * @param filedName
- * @param value
- */
- public static void setHeadValue(Class clzz, String filedName, String value) {
- try {
- Map<String, List<String>> map = ReflectUtils.getFieldInfoWithExcelProperty(clzz);
- ClassPool pool = ClassPool.getDefault();
- pool.insertClassPath(new ClassClassPath(clzz));
- CtClass ct = pool.get(clzz.getName());
- CtField ctField = ct.getDeclaredField(filedName);
- if (map.keySet().contains(ctField.getName())) {
- FieldInfo methodInfo = ctField.getFieldInfo();
- ConstPool cPool = methodInfo.getConstPool();
- AnnotationsAttribute attribute = (AnnotationsAttribute) methodInfo.getAttribute(AnnotationsAttribute.visibleTag);
- Annotation anno = attribute.getAnnotation(ExcelProperty.class.getName());
- ArrayMemberValue arrayMemberValue = new ArrayMemberValue(cPool);
- MemberValue[] memberValues = new StringMemberValue[]{new StringMemberValue(value, cPool)};
- arrayMemberValue.setValue(memberValues);
- anno.addMemberValue("value", arrayMemberValue);
- attribute.addAnnotation(anno);
- methodInfo.addAttribute(attribute);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- // try {
- // //获取field
- // Field filed = clzz.getDeclaredField(filedName);
- // filed.setAccessible(true);
- // //获取注解
- // ExcelProperty annotation = filed.getAnnotation(ExcelProperty.class);
- // InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
- // Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
- // memberValues.setAccessible(true);
- // Map<String, Object> map = (Map<String, Object>) memberValues.get(invocationHandler);
- // map.put("value", new String[]{value});
- // } catch (Exception e) {
- // e.printStackTrace();
- // }
-
- }
-
-
-
-
-
- }
提供另外一种写法:
EasyExcel多sheet导出,反射动态设置表头_writesheet设置表头_Milo(xiu)的博客-CSDN博客
有兴趣的可以看看下面博主的说法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。