通过对Java注解(一):介绍,思想及优点学习了解,相信大家对Java注解有一定程度的了解,本篇文章将实战项目中的应用来加深对Java注解的了解。

本实例实现根据指定字段的JavaBean,生成对应列的报表。使用Java注解就是方便实现JavaBean与Excel或CSV列已一一映射。直观展现数据,不需要中间转换,Java注解可以很轻松实现。

下面先给出Java注解的定义:

import java.lang.annotation.*;

/**
* 类功能描述:列属性
*
* @author WangXueXing create at 18-10-29 下午4:40
* @version 1.0.0
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ColumnProperty {
/**
* 列序号
* @return
*/
int index(); /**
* 列表头名
* @return
*/
String name();
}

  本注解定义目的是使用在JavaBean的每个字段映射到Excel中的列序号及列表头名。这样对于开发者,我只需要定义好报表展示的列及相对位置,并组装JavaBean list.直观,不需要关心转换过程。

下面代码就是定义JavaBean及使用上面定义的注解:

import com.today.service.financereport.util.ColumnProperty

import scala.annotation.meta.field
import scala.beans.BeanProperty /**
* 类功能描述:营收明细
*
* @author WangXueXing create at 18-10-23 下午7:52
* @version 1.0.0
*/
case class IncomeDetail(/** 店号 */
@(ColumnProperty@field)(index = 0, name = "店号")
@BeanProperty
storeId: String, /** 店名 */
@(ColumnProperty@field)(index = 1, name = "店名")
@BeanProperty
storeName: String, /** 门店类型 */
@(ColumnProperty@field)(index = 2, name = "门店类型")
@BeanProperty
storeType: String, /** 营业日期 */
@(ColumnProperty@field)(index = 3, name = "营业日期")
@BeanProperty
businessDate: String, /** 交易时间 */
@(ColumnProperty@field)(index = 4, name = "交易时间")
@BeanProperty
payTime: String, /** 订单号 */
@(ColumnProperty@field)(index = 5, name = "订单号")
@BeanProperty
orderNo: String, /** 交易流水号 */
@(ColumnProperty@field)(index = 6, name = "交易流水号")
@BeanProperty
tradeNo: String, /** 金额 */
@(ColumnProperty@field)(index = 7, name = "金额")
@BeanProperty
tradeAmount: BigDecimal, /** 抹零金额 */
@(ColumnProperty@field)(index = 8, name = "抹零金额")
@BeanProperty
spotAmount: BigDecimal, /** 支付方式 */
@(ColumnProperty@field)(index = 9, name = "支付方式")
@BeanProperty
tradeType: String, /** POS机 */
@(ColumnProperty@field)(index = 10, name = "POS机")
@BeanProperty
posId: String, /** 收银员 */
@(ColumnProperty@field)(index = 11, name = "收银员")
@BeanProperty
cashierName: String, /** 订单类型 */
@(ColumnProperty@field)(index = 12, name = "订单类型")
@BeanProperty
payType: String, /** 第三方商户订单号 */
@(ColumnProperty@field)(index = 13, name = "第三方商户订单号")
@BeanProperty
thirdPartyPaymentNo: String
)

  其中@BeanProperty是Scala自带的一个注解,就是免去Java中对每个字段的getter()与setter()的定义。

以下是伪代码,从数据库中获取对应数据结构为IncomeDetail的数据列表:

def getReportData: List[IncomeDetail] = {
return jdbc.getIncomeDetailList()
}

  获取到数据后,将数据通过注解转换并填入报表:

val incomeDetailList = getReportData()
val file = File.createTempFile( "营收明细报表_" + MathUtils.getRandom(4), ".csv")
ScalaFunction.tryWithResources(new PrintWriter(file, "GBK")) { out =>
val dataObj =incomeDetailList.isInstanceOf[Seq[AnyRef@unchecked]] match {
case true => incomeDetailList.asInstanceOf[List[AnyRef@unchecked]]
case _ => List.empty
}
//根据注解顺序生成CSV数据列表
AnnotationUtil.getValueWithHead(dataObj).foreach(out.println(_))
}

  其中ScalaFunction.tryWithResources()仿照Java try with resources本人定义了一个Scala函数来处理流关闭,详情请参考我以前的博客:Scala实现Try with resources自动关闭IO

/**
* 类功能描述:Scala高级函数
*
* @author WangXueXing create at 18-11-22 下午5:29
* @version 1.0.0
*/
object ScalaFunction {
/**
* Scala实现Java7 try-with-resources
* @see https://www.cnblogs.com/barrywxx/p/10002422.html
*/
def tryWithResources[A <: {def close(): Unit }, B](a: A)(f: A => B): B = {
try {
f(a)
} finally {
if(a != null){
a.close()
}
}
}
}

  我们重点关注下AnnotationUtil.getValueWithHead(), 这个方法定义了通过注解将数据填入Excel或CSV报表的过程:

import java.lang.reflect.Field

import com.today.service.financereport.dto.IncomeDetail

/**
* 类功能描述:Scala注解工具类
*
* @author WangXueXing create at 18-10-30 下午3:35
* @version 1.0.0
*/
object AnnotationUtil {
/**
* 根据注解获取值列表
*/
def getValueWithHead(valList: List[_]): List[String] ={
var fields: Array[Field] = Array.empty
val dataList: List[String] = valList.zipWithIndex.map{ x=>
if(x._2 == 0){
fields = x._1.getClass.getDeclaredFields.sortBy(_.getAnnotations.apply(0).asInstanceOf[ColumnProperty].index())
} fields.map{f=>
f.setAccessible(true)
val value = f.get(x._1)
if(value == null){
""
} else {
value.toString
}
}.mkString(",")
}
fields.map(_.getAnnotation(classOf[ColumnProperty]).name()).mkString(",")+:dataList
} def main(args: Array[String]): Unit = {
val list = List(IncomeDetail("wew1","eerr1","wrw1",null,"1","1","1",BigDecimal(12.1),BigDecimal(12.1),"1","1","1"),
IncomeDetail("rer2","wrwrw2","wrw2","2","2","2","2",BigDecimal(12.1),BigDecimal(12.1),"2","2","2")) val objList = getValueWithHead(list)
objList.foreach(println(_))
}
}

  好了,到这里,这个实例已经完成。是不是以后就不需要关注怎样组装复杂报表数据结构,只需要将JavaBean定义好,按照这个JavaBean的数据结构组装数据就行了!

Java注解(二):实战 - 直接使用对象列表生成报表的更多相关文章

  1. java实现二维码的生成.

    目录 1.二维码概念  2.二维码发展历史  3.二维码分类  4.二维码优缺点  5.QR Code  1.二维码又称  二维条码 (2-dimensional bar code)是用某种特定的几何 ...

  2. 分享知识-快乐自己:全面解析 java注解实战指南

    请你在看这篇文章时,不要感到枯燥,从头到尾一行行看,代码一行行读,你一定会有所收获的. 问: 为什么学习注解? 学习注解有什么好处? 学完能做什么? 答: 1):能够读懂别人的代码,特别是框架相关的代 ...

  3. java实现二维码的生成与解析

    简单介绍下二维码:二维码其实就是一种编码技术,只是这种编码技术是用在图片上了,将给定的一些文字,数字转换为一张经过特定编码的图片,而解析二维码则相反,就是将一张经过编码的图片解析为数字或者文字. 当然 ...

  4. Java JDBC学习实战(二): 管理结果集

    在我的上一篇博客<Java JDBC学习实战(一): JDBC的基本操作>中,简要介绍了jdbc开发的基本流程,并详细介绍了Statement和PreparedStatement的使用:利 ...

  5. java版gRPC实战之二:服务发布和调用

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  7. java实现二维码生成的几个方法

    1: 使用SwetakeQRCode在Java项目中生成二维码 http://swetake.com/qr/ 下载地址 或着http://sourceforge.jp/projects/qrcode/ ...

  8. Java条形码/二维码生成和解析

    注意-本类依赖jar包文件:core.jar和zxing-javase.jar 下载jar文件,到本博客文件栏目下载. import com.google.zxing.BarcodeFormat; i ...

  9. java注解之二

    从JDK5开始,Java增加了Annotation(注解),Annotation是代码里的特殊标记,这些标记可以在编译.类加载.运行时被读取,并执行相应的处理.通过使用Annotation,开发人员可 ...

随机推荐

  1. currval of sequence "follow_id_seq" is not yet defined in this session

    postgresql上使用 select currval('follow_id_seq'); 报错: currval of sequence "follow_id_seq" is  ...

  2. MySQL的日志(二):事务日志

    本文目录:1.redo log 1.1 redo log和二进制日志的区别 1.2 redo log的基本概念 1.3 日志块(log block) 1.4 log group和redo log fi ...

  3. API管理平台XXL-API

    <API管理平台XXL-API> 一.简介 1.1 概述 XXL-API是一个简洁易用API管理平台,提供API的"管理"."文档"."M ...

  4. 安装RabbitMQ编译erlang时,checking for c compiler default output file name... configure:error:C compiler cannot create executables See 'config.log' for more details.

    checking for c compiler default output file name... configure:error:C compiler cannot create executa ...

  5. RabbitMQ Linux(Redhat6.5)安装(二 )

    一.安装erlang 由于RabbitMq的linux运行环境需要erlang环境,所以需要先安装erlang: 1.erlang下载: http://erlang.org/download/(我下载 ...

  6. SAP中的BRF+

    即便努力去尝试最小化SAP系统中的自定义内容,大量自定义业务逻辑通常还是无法避免的.在过去,这意味着需要在系统的各种地方引入自定义ABAP代码,包括user-exits,enhancement,BAd ...

  7. CSS弹性盒子的基本用法

    .container { width: 302px; height: 302px; border: 1px solid; display: flex } .item { width: 100px; h ...

  8. 关于java集合类HashMap的理解

    一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了不同步和允许使用 null 之外,HashMap  ...

  9. IntelliJ IDEA中 todo的使用

    在代码的注释部分加入TODO 大小写忽略,如下图所示 查看项目中有哪些待办项,所下图所示

  10. Windows 安装 Vue

    引言 在公司 linux 环境下安装不顺利,回家在 windows 下操作感觉到一种幸福 nginx 先安装了 nginx,其实跟 vue 没关系,只是打算用它做 web 服务,此处略过 nginx ...