Java 根据自定义注解修改@Excel注解的值

Java 根据自定义注解修改@Excel注解的值

        在使用easyexcel导出excel文件的时候,在实体类字段上使用@Excel定义表头、顺序、宽度,很方便;但是同一个字段在不同的场景中导出的表头不一样的时候,导出的表头需要根据具体参数变化;找了一下这个框架好像没有封装这种场景的方法
        然后我自己定义了一个注解,在导出的时候动态将字段上面的@Excel参数修改掉,来实现在根据不同的参数导出不同表头的效果

注解
/**
 * 解决同一个实体类 导出的excel表头不一样的问题
 * 添加该注解必须要同时添加  cn.afterturn.easypoi.excel.annotation.Excel 注解
 * 配合 ExcelUtils 工具类中 modifyExcelAnnotation 方法来使用
 * 该注解中 所有数据都配置多个,默认以英文逗号(,)隔开,没有的要加空格;单个没必要用到这个注解
 * 属性配置多个的时候,各属性的下标要一致
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelData {

	/**
	 * 表头
	 * @return
	 */
	public String names();
	
	/**
	 * 列序号,从0开始
	 * 默认以英文逗号(,)隔开
	 * 
	 * @return
	 */
	public String orderNums() default "0";
}
/**
 * 处理 ExcelData 注解中对应index的表头信息 塞到 Excel 注解中
 * @author YHSJ
 *
 */
@Target({METHOD})
@Retention(RUNTIME)
public @interface ExcelHeaderAnnotation {

	/**
	 * 要处理的实体类全限名
	 * @return
	 */
	public String clazzName();
	
	/**
	 * 分隔符
	 * @return
	 */
	public String separate() default ",";
}
AOP类
@Aspect
@Component
public class ExcelHeaderAspect {

	@Before("@annotation(com.aop.ExcelHeaderAnnotation)")
	public void before(JoinPoint point) throws Exception {
//		String methodName = point.getSignature().getName();
	   MethodSignature methodSignature = (MethodSignature)point.getSignature();
       Method method = methodSignature.getMethod();
       // 获取注解 ExcelHeaderAnnotation 
       ExcelHeaderAnnotation annotation = method.getAnnotation(ExcelHeaderAnnotation.class);
       // 获取注解 ExcelHeaderAnnotation 的参数的值
       String clazzName = annotation.clazzName();
       String separate = annotation.separate();
       
       // 获取切点方法入参列表
       Object[] objArray = point.getArgs();
       // 下面代码根据具体入参类型进行修改
       Integer index = 0;
       for (Object obj: objArray) {
           if(obj instanceof Integer){
           	index = (Integer) obj;
           }
       }
       // 获取实体类的字段
       Class<?> clazz = Class.forName(clazzName);
       Field[] fields = clazz.getDeclaredFields();
	   for (Field field : fields) {
	   		// 判断注解是否存在
	   		boolean isData = field.isAnnotationPresent(ExcelData.class);
	   		boolean is = field.isAnnotationPresent(Excel.class);
	   		if(!is || !isData) continue;
	   		// 获取 ExcelData 对应 index 的属性值
	   		ExcelData excelDataInterface = field.getAnnotation(ExcelData.class);
	   		String[] names =  excelDataInterface.names().split(StringUtils.isNotBlank(separate) ? separate : ",");
	   		String[] orderNums =  excelDataInterface.orderNums().split(StringUtils.isNotBlank(separate) ? separate : ",");
	   		String name = (names != null && names.length > index) ? names[index] : names[0];
	   		String orderNum = (orderNums != null && orderNums.length > index) ? orderNums[index] : orderNums[0];
	   		
	   		// 将 ExcelData 中对应的属性值 塞到 Excel注解中
	   		Excel excelInterface = field.getAnnotation(Excel.class);
	   		InvocationHandler h = Proxy.getInvocationHandler(excelInterface);
	   		// 获取 AnnotationInvocationHandler 的 memberValues 字段
	   		Field hField = h.getClass().getDeclaredField("memberValues");
	   		// 因为字段是 private 修饰,所以要打开权限
	   		hField.setAccessible(true);
	   		// 获取 memberValues
	   		Map<String, Object> memberValues = (Map<String, Object>) hField.get(h);
	   		memberValues.put("name", StringUtils.isNotBlank(name) ? name : "");
	   		memberValues.put("orderNum", StringUtils.isNotBlank(orderNum) ? orderNum : "");
	   	}
   	}
}
实体类
public class DemoTest {
	@Excel(name = "")
	@ExcelData(names = "参数0,参数01,参数02", orderNums = "0")
	private String parame1;
	@Excel(name = "")
	@ExcelData(names = "参数1,参数11,参数12", orderNums = "1")
	private String parame2;
	@Excel(name = "")
	@ExcelData(names = "参数2,参数21,参数22", orderNums = "2")
	private String parame3;
	@Excel(name = "")
	@ExcelData(names = "参数3,参数31,参数32", orderNums = "3")
	private String parame4;
	@Excel(name = "")
	@ExcelData(names = "参数4,参数41,参数42", orderNums = "4")
	private String parame5;
}
调用
@ExcelHeaderAnnotation(clazzName = "com.model.DemoTest")
public void export(Integer index, HttpServletResponse response) {
	// 导出代码 
}

不用aop注解也可以在调用导出代码前执行一下下面的工具方法

工具方法
/**
  * 
  * @param clazz 实体类class对象
  * @param index  @ExcelData 注解中第 index 个表头信息
  * @param separate @ExcelData 注解中表头信息中间的 分隔符
  * @throws NoSuchFieldException
  * @throws IllegalAccessException
  */
public static void modifyExcelAnnotation(Class<?> clazz, int index, String separate) throws NoSuchFieldException, IllegalAccessException {
    // 获取实体类的字段
   	Field[] fields = clazz.getDeclaredFields();
   	for (Field field : fields) {
   		// 判断注解是否存在
   		boolean isData = field.isAnnotationPresent(ExcelData.class);
   		boolean is = field.isAnnotationPresent(Excel.class);
   		if(!is || !isData) continue;
   		// 获取 ExcelData 对应 index 的属性值
   		ExcelData excelDataInterface = field.getAnnotation(ExcelData.class);
   		String[] names =  excelDataInterface.names().split(StringUtils.isNotBlank(separate) ? separate : ",");
   		String[] orderNums =  excelDataInterface.orderNums().split(StringUtils.isNotBlank(separate) ? separate : ",");
   		String name = (names != null && names.length > index) ? names[index] : names[0];
   		String orderNum = (orderNums != null && orderNums.length > index) ? orderNums[index] : orderNums[0];
   		
   		// 将 ExcelData 中对应的属性值 塞到 Excel注解中
   		Excel excelInterface = field.getAnnotation(Excel.class);
   		InvocationHandler h = Proxy.getInvocationHandler(excelInterface);
   		// 获取 AnnotationInvocationHandler 的 memberValues 字段
   		Field hField = h.getClass().getDeclaredField("memberValues");
   		// 因为字段是 private 修饰,所以要打开权限
   		hField.setAccessible(true);
   		// 获取 memberValues
   		Map<String, Object> memberValues = (Map<String, Object>) hField.get(h);
   		memberValues.put("name", StringUtils.isNotBlank(name) ? name : "");
   		memberValues.put("orderNum", StringUtils.isNotBlank(orderNum) ? orderNum : "");
   	}
}
调用
public void export(Integer index, HttpServletResponse response) {
	modifyExcelAnnotation(DemoTest.class, index, "");
	
	// 导出代码 
}

参考博客

https://www.jb51.net/article/217449.htm
https://blog.csdn.net/qq_39309348/article/details/118551620

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值