分享十条Java后端开发实战经验,干货满满!
前沿
借助本篇文章,旨在对自己在公司、个人项目的实战经验总结,包括JAVA常遇到的业务场景技术栈、第三方库以及可复用的代码编写,希望能给大家带来帮助。
目前,我总结了10条常见的业务开发经验,毫无保留的分享给大家..., 主要涵盖内容如下:悟耕开源Easypoi Excel导入导出最佳实践Alibaba Excel导出时自定义格式转换优雅实现不建议直接使用@Async实现异步,需自定义线程池解决Java行业常见业务开发数值计算丢失精度问题Hutool TreeUtil快速构造返回树形结构事务@Transactional的失效场景Spring Event实现异步业务开发中通用的策略模式模板使用ip2region获取用户地址位置信息利用好Java现有优秀的开发库一、悟耕开源easypoi - Excel导入导出最佳实践
Excel导入导出几乎在很多中后台项目都会用到,特别是一些CRM、OA、商城、企业应用等系统都十分常见,在开发的过程中我也遇到过很多Excel大数据导入导出的功能,一直以来,使用easypoi做了不少导入导出的需求,导入导出数据量从10万级到现在百万级(Excel峰值103万数据量),整理了一下easypoi的导入导出的基础和高级用法。大数据导出数据转换以及数据加密Excel导入数据校验,并提供错误日志下载1.1 注解说明
常见的5个注解类分别是:@Excel :作用到filed上面,是对Excel列的一个描述;@ExcelCollection:表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示;@ExcelEntity:表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段;@ExcelIgnore:和名字一样表示这个字段被忽略跳过这个导导出;@ExcelTarget:这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理。1.2 定义easypoi实体类import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.handler.inter.IExcelDataModel; import cn.afterturn.easypoi.handler.inter.IExcelModel; import lombok.Data; import javax.validation.constraints.NotBlank; import java.io.Serializable; @Data public class SdSchoolSysUserVerify implements IExcelModel, IExcelDataModel, Serializable { private static final long serialVersionUID = 1L; @Excel(name = "行号") private Integer rowNum; @Excel(name = "错误信息") private String errorMsg; /** * 真实姓名 */ @Excel(name = "姓名(必填)", width = 25) @NotBlank(message = "姓名不能为空") private String realname; /** * 部门编码,需要和用户导入模板名称对应 */ @Excel(name = "部门编码(必填)", width = 30) @NotBlank(message = "部门编码不能为空") private String deptOrgCode; /** * 角色编码 */ @Excel(name = "角色编码(必填)", width = 15) @NotBlank(message = "角色编码不能为空") private String roleCode; /** * 手机号码 */ @Excel(name = "手机号码(选填)", width = 15) private String phone; /** * 电子邮件 */ @Excel(name = "电子邮件(选填)", width = 15) private String email; /** * 性别(1:男 2:女) */ @Excel(name = "性别(选填)", width = 15) private String sexName; /** * 工号(选填) */ @Excel(name = "工号(选填)", width = 15) private String workNo; /** * 商户ID **/ private Integer tenantId; }1.3 基础的导入导出逻辑(数据校验)
easyPoi导入校验使用起来也很简单,以导入系统优化为例:
第一步,定义一个检验类SdSchoolSysUserVerify,通过实现IExcelModel、IExcelDataModel,当我们需要输出导入校验错误信息的时候,它们两个就显的很重要了,IExcelModel负责设置错误信息,IExcelDataModel负责设置行号。package cn.afterturn.easypoi.handler.inter; /** * Excel 本身数据文件 */ public interface IExcelDataModel { /** * 获取行号 */ public Integer getRowNum(); /** * 设置行号 */ public void setRowNum(Integer rowNum); }
第二步,定义完实体之后,那么如何实现我们的校验逻辑呢,接着自定义一个系统用户导入校验处理器SdSchoolSysUserVerifyHandler,通过实现IExcelVerifyHandler,处理器里编写我们的校验逻辑:/** * 系统用户批量导入校验处理器 * * @author: jacklin * @since: 2021/3/31 11:47 **/ @Component public class SdSchoolSysUserVerifyHandler implements IExcelVerifyHandler { private static final String PREFIX = "【"; private static final String SUFFIX = "】"; @Autowired private ISysBaseAPI sysBaseAPI; @Override public ExcelVerifyHandlerResult verifyHandler(SdSchoolSysUserVerify userVerify) { LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); userVerify.setTenantId(Integer.valueOf(loginUser.getRelTenantIds())); StringJoiner joiner = new StringJoiner(", ", PREFIX, SUFFIX); if (StringUtils.isBlank(userVerify.getRealname())) { joiner.add("用户姓名不能为空"); } //根据用户姓名和商户ID查询用户记录,大于0则提示该姓名用户已存在 int realNameCount = sysBaseAPI.countByRealName(userVerify.getRealname(), userVerify.getTenantId()); if (realNameCount > 0) { joiner.add("该姓名用户已存在,如需添加该用户请在页面添加"); } if (StringUtils.isBlank(userVerify.getDeptOrgCode())) { joiner.add("部门编码不能为空"); } else { //查询系统是否存在该部门编码 int deptOrgCodeCount = sysBaseAPI.queryDepartCountByDepartSysCodeTenantId(userVerify.getDeptOrgCode(), userVerify.getTenantId()); if (deptOrgCodeCount == 0) { joiner.add("部门编码不存在"); } } if (oConvertUtils.isEmpty(userVerify.getRoleCode())) { joiner.add("用户角色编码不能为空"); } else { //查询系统是否存在该角色 int count = sysBaseAPI.queryRoleCountByRoleCodeTenantId(userVerify.getRoleCode(), userVerify.getTenantId()); if (count == 0) { joiner.add("该用户角色编码不存在"); } else { //查询配置是否用户支持导入该角色 int supportUserImportCount = sysBaseAPI.queryIsSupportUserImportByRoleCode(userVerify.getRoleCode(), userVerify.getTenantId()); if (supportUserImportCount == 0) { joiner.add("该用户角色编码不支持导入"); } } } if (oConvertUtils.isNotEmpty(userVerify.getPhone())) { boolean isPhone = Validator.isMobile(userVerify.getPhone()); if (!isPhone) { joiner.add("手机号填写格式不正确"); } } if (oConvertUtils.isNotEmpty(userVerify.getEmail())) { boolean isEmail = Validator.isEmail(userVerify.getEmail()); if (!isEmail) { joiner.add("邮箱填写格式不正确"); } } if (!"【】".equals(joiner.toString())) { return new ExcelVerifyHandlerResult(false, joiner.toString()); } return new ExcelVerifyHandlerResult(true); } }
第三步,在完成第一、二步之后,我们只需要在导入的时候通过 params.setVerifyHandler(userVerifyHandler)、params.setNeedVerfiy(true)即可以实现导入校验了。1.4 不同类型数据的导入和导出(Map/Object)
在某些复杂的场景,我们导入的时候不想直接构造一个bean然后标记注解,但是中间需要处理一些字段逻辑没办法直接导入到数据库,这是用可以用map的形式导入,下面我以一个客户导入的需求演示一下如何通过map的方式导入数据:核心方法://Map数据格式导入 ExcelImportResult
一个陌生男人的来信28语嫣这是一张淡淡的水墨。这大概是在春天。两棵矮矮的山樱树,选择两处坡地,对应地耐心注视着。一阵淡淡的似有似无的风沟通了我们。一条浅浅的似曾相识的小路沟通了我们。一些似是而非的花朵悄
新华时评奔向星辰大海,不懈奋斗2022年全年载人航天工程实施6次发射任务,常年有人照料的空间站全面建成,长征六号甲运载火箭开展首飞9日发布的中国航天科技活动蓝皮书(2021年),展示了2021年中国航天的最新成
SpaceX可能失去上周发射的几乎所有Starlink卫星?SpaceX公司透露,在一场地磁暴扰乱其部署后,它可能失去上周发射的几乎所有Starlink卫星。该公司在其网站上发表的一篇文章中说,在2月3日星期四部署49颗Starlink互联
地球拥有多少颗卫星?地球只有1颗天然卫星,那就是月球。不过,围绕地球的人造卫星却越来越多。群星环绕的地球人造卫星被火箭带到地球上空,在引力和惯性的作用下绕地球公转。土星有82颗卫星,是目前已知拥有最多
读中国节,过中国年除夕,中国节我们的传统节日故事内文。由出版社提供中国节我们的传统节日故事(全16册)向华文中央美术学院绘本创作工作室图上海人民出版社2022年1月蓝宁编者按文化自信和文化寻根,都离
产科住院,别的不带也要带上这个来产房住院有几天了,宝宝还是没出世。作为准家长的的我真的是憋的难受。但是呢,也不算是完全没有收获吧。住院,尤其是在产科住院,真的是比较费心的拿的东西太多。不仅要带上产妇的东西,孩子
江苏发现一宝藏古刹,古木幽深,绿茵曲水,紧邻闹市却远离喧嚣江苏有一寺庙,至今约700余年,集园林与佛教为一体,超多人来!随着人们对旅游景点的认知,使得越来越多的游客在选择打卡地时,不会再像起初那样,对于好玩的景点一无所知,必定现在的网络很
嘉午台上赏嘉午今天8号,前往嘉午台,从曲江过去也就40分钟。嘉午台村口扫码车直接开到山门口,开始登山。白道峪山脚下积雪市区虽然没有雪,但走到山里后,就进入了一个冰雪世界。山脚下入口处道场路上一开
住古代房子的那些事儿关于住房的问题,不只是当今老百姓的头等大事,在古人同样也有房子的烦恼。古时候的住可以分成两部分,一是短期旅行的住宿,二是长期在某地生活的住房。住房可以租,可以买,买包括买现房和买地
来老挝旅游时,当地美女问要不要香烟原来是暗藏猫腻旅游已经成为很多人释放压力的一种选择,在这个过程中,我们可以暂时忘却工作或者生活中的烦恼,跟自己的朋友尽情体验自然风光带来的愉悦感。(此处已添加小程序,请到今日头条客户端查看)而社
夜尿增多,可能是早期糖尿病肾损害,怎么办?做好以下两点很重要糖尿病夜间尿量多是什么原因糖尿病患者,出现夜尿增多,要警惕早期肾脏损害的可能。糖尿病作为一种常见的慢性代谢性疾病,肾脏损害是其并发症之一。研究表明,在我国2030的糖尿病患者合并有