分享十条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
WEB实时消息推送这7种方案能更好地帮你实现前言我有一个朋友(手动狗头)做了一个小破站,现在要实现一个站内信web消息推送的功能,对,就是下图这个小红点,一个很常用的功能。不过他还没想好用什么方式做,这里我帮他整理了一下几种
过度收集个人信息,三家贷款平台被罚关于过度收集个人信息的现象,持续在治理,近日,网信河北通报了违法违规收集使用个人信息的安卓APP。针对人民群众反映强烈的APP非法获取超范围收集过度索权等侵害个人信息的现象。经过湖
安丘市加快商贸企业升规纳限助经济高质量发展日前,记者在位于安丘市金冢子镇的天润食品有限公司内看到,工作人员正在产品包装车间忙碌。该公司成立于2001年,是一家以从事鸭产品加工业为主的企业,经过安丘市商务局指导,企业做好工业
电力行业深度报告新机遇新挑战,绿电价值重估(报告出品方作者民生证券,严家源赵国利)1煤电重启,意味着绿电将死吗?20212022年连续两年夏季的极端高温少雨气候,暴露了国内电力供给偏紧的现状而以煤电为主的火电,在保供过程中
油价又要变,时间定了!本周期(10月24日以来),尽管对石油需求疲弱的担忧持续,但OPEC大幅减产计划在11月进入执行期,市场预期石油供应将收紧,国际油价震荡运行,均价较前期有所上涨。预计11月7日24
我们需要全球发展倡议这样的大规模合作光明日报记者杨逸夫本届进博会汇聚了超过280家世界500强和行业龙头企业参展,各大跨国企业积极将第五届虹桥国际经济论坛作为交流互鉴的平台。11月5日,在由中国商务部国务院国资委与联
减少资金占用激发企业活力来源人民网人民日报打开江苏省扬州市公共资源交易平台的网站,江苏润桥建设工程有限公司的工作人员赵林点击要投标的项目,显示保证金为15万元。他没有选择直接转账,而是接着购买了电子保函,
三季报业绩排序1上游资源产品锂氟化工钾肥磷化工煤炭等。如锂电的融捷股份天齐锂业,前三季度分别增长了4533和2916氟化工龙头巨化股份,前三季度归母净利润为16。99亿元,同比增加557。28,
郑州11月房价新鲜出炉,持续下跌,市场分化,郑州楼市何去何从?根据吉屋网统计数据,郑州11月新房均价12546元,环比下跌0。50,二手房均价13110元,环比下跌6。60。从房价走势可知,一方面,郑州新房已经连续12个月下跌,但近一年中的跌
阿的江找到新工作!加盟宁波富邦,携手爱徒,重返CBA赛场就在新疆男篮宣布阿的江下课后不久,邱彪就成为替代者。不过对于阿的江来说,以他的地位,想要找到新工作并不难。有球迷爆料,阿的江出现在宁波,据了解宁波富邦方面已经邀请阿的江担任球队顾问
深度丨阿的江辞职,祸根其实在管理层最近,阿的江指导最近宣布辞去新疆队主教练职务,在网络上引起了不小的的喧嚣,出于对优秀前辈的敬意,我们先回顾一下阿指导球员和教练时期的成绩球员时代随八一队获得CBA总冠军5次22岁入