背景
为了服务阿里云交付场景,沉淀重复组件,我们现在针对坐标转换与近邻搜索这一使用需求做统一工具类封装,
近邻搜索封装使用spring boot starter的方式来暴露服务,使用mybatis interceptor 统一处理近邻搜索查询。
主要功能
坐标转换:支持百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具。
近邻搜索:支持搜索指定坐标与距离的范围的数量。
HuTool: 支持HuTool(https://hutool.cn/docs/#/)
Data-Factory:用于根据对象,随机自动生成初始化信息。便于测试。
代码仓库地址
git@code.dayu.work:aliyun-gts-backend-lib/aliyun-gts-tool.git
1.examples代码获取
1.1 示例程序
aliyun-gts-tool-examples.zip
(128 KB)
https://iwhale-citybrain.yuque.com/docs/share/06f21927-74be-45db-922c-bb86078412c8?#7YeJE
1.2 setting.xml
settings_public.xml
(5 KB)
https://iwhale-citybrain.yuque.com/docs/share/06f21927-74be-45db-922c-bb86078412c8?#7YeJE
2.使用
坐标转换
如果需要使用已发布的版本,在 dependencyManagement 中添加如下配置。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.aliyun.gts.bpaas</groupId>
<artifactId>aliyun-gts-tool-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后在 dependencies 中添加如下依赖。
<dependency>
<groupId>com.aliyun.gts.bpaas</groupId>
<artifactId>aliyun-gts-tool-coordinate-conversion</artifactId>
</dependency>
说明:GeoUtil比CoordinateConversionUtil转换出来的精度略高,两个皆可使用。
Java代码示例:
/**
* 火星坐标系=>地球坐标系
*/
Point pp = GeoUtil.convertCoord(28.487833, 112.651837,CoordTypeEnum.MARS, CoordTypeEnum.EARTH);
log.info("火星转地球:原坐标==》新坐标:{}==》{}","[112.651837, 28.487833]",pp);
//控制台打印:火星转地球:原坐标==》新坐标:[112.651837, 28.487833]==》Point [lon=112.64643390630435, lat=28.491286559279445]
/**
* 火星坐标系=>百度坐标系
*/
Point pp1 = GeoUtil.convertCoord(28.487833, 112.651837,CoordTypeEnum.MARS, CoordTypeEnum.BAIDU);
log.info("火星转百度:原坐标==》新坐标:{}==》{}","[112.651837, 28.487833]",pp1);
//控制台打印:火星转百度:原坐标==》新坐标:[112.651837, 28.487833]==》Point [lon=112.65834032600979, lat=28.493868372862735]
/**
* convertLatLonByCoordinate
* 百度转84
*/
double[] doubles = CoordinateConversionUtil.convertLatLonByCoordinate("baidu", "wgs84", 130.00, 35.35);
log.info("84转百度:原坐标==》新坐标:{}==》{}","[35.35, 130.00]",doubles);
控制台打印:84转百度:原坐标==》新坐标:[35.35, 130.00]==》[35.35684229464699, 130.0059248711622]
/**
* bd09towgs84 百度转84
*/
double[] doubles = CoordinateConversionUtil.bd09towgs84(130.00, 35.35);
log.info("百度转84:原坐标==》新坐标:{}==》{}","[35.35, 130.00]",doubles);
控制台打印:百度转84:原坐标==》新坐标:[35.35, 130.00]==》[129.98758363761826, 35.34416976271194]
/**
* wgs84tobd09 84转百度
*/
double[] doubles = CoordinateConversionUtil.wgs84tobd09(130.00, 35.35);
log.info("84转百度:原坐标==》新坐标:{}==》{}","[35.35, 130.00]",doubles);
控制台打印:84转百度:原坐标==》新坐标:[35.35, 130.00]==》[35.35684229464699, 130.0059248711622]
/**
* gcj02towgs84 火星转84
*
*/
double[] doubles = CoordinateConversionUtil.gcj02towgs84(130.00, 35.35);
log.info("火星转84:原坐标==》新坐标:{}==》{}","[35.35, 130.00]",doubles);
控制台打印:火星转84:原坐标==》新坐标:[35.35, 130.00]==》[129.9940753004387, 35.350072433660955]
/**
* gcj02tobd09 火星转百度
*/
double[] doubles = CoordinateConversionUtil.gcj02tobd09(130.00, 35.35);
log.info("火星转百度:原坐标==》新坐标:{}==》{}","[35.35, 130.00]",doubles);
控制台打印:火星转百度:原坐标==》新坐标:[35.35, 130.00]==》[130.0065433752444, 35.355802376024315]
/**
* bd09togcj02 百度转火星
*/
double[] doubles = CoordinateConversionUtil.bd09togcj02(130.00, 35.35);
log.info("百度转火星:原坐标==》新坐标:{}==》{}","[35.35, 130.00]",doubles);
控制台打印:百度转火星:原坐标==》新坐标:[35.35, 130.00]==》[129.9934846897474, 35.344072159276536]
/**
* wgs84togcj02 84转火星
*/
double[] doubles = CoordinateConversionUtil.wgs84togcj02(130.00, 35.35);
log.info("84转火星:原坐标==》新坐标:{}==》{}","[35.35, 130.00]",doubles);
控制台打印:84转火星:原坐标==》新坐标:[35.35, 130.00]==》[130.0059246995613, 35.34992756633905]
近邻搜索
规划
通过具体的某一位置查找附近(某一距离)范围内有多少目标物,比如:附近的人
实现方案
将要查询具体的业务部分剥离,依据传入的经纬度以及半径计算出该圆的外切正方形,并获取该外切正方形的最小、最大的经纬度坐标
利用mybatis interceptor将要查询的sql进行拦截,并将外切正方形的经纬度作为筛选条件修改sql并执行,可大大减少计算的数据量。
通过将业务表中的经纬度设置索引提升检索效率。
注意
该方案是通过转换成圆形的外切正方形来进行范围筛选的方式来实现的,扩充了查询范围;
如果需求就是搜索圆形内的数据的话,这样会多了一些数据.
如果需要使用已发布的版本,在 dependencyManagement 中添加如下配置。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.aliyun.gts.bpaas</groupId>
<artifactId>aliyun-gts-tool-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后在 dependencies 中添加如下依赖。
<dependency>
<groupId>com.aliyun.gts.bpaas</groupId>
<artifactId>aliyun-gts-tool-near-search-starter</artifactId>
</dependency>
配置
在application.properties(或者yml文件)中配置如下内容:
spring.mybatis.enable.near.search= true
不配置或配置为false 不使用近邻查询
示例:
建表语句:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) DEFAULT NULL,
`lng` double(20) DEFAULT NULL,
`lat` double(20) DEFAULT NULL,
PRIMARY KEY (`id`)
);
insert into user ( id, name, lng, lat ) values ( 1, 'li1', 120.12, 55.35 );
insert into user ( id, name, lng, lat ) values ( 2, 'li2', 130.12, 25.35 );
insert into user ( id, name, lng, lat ) values ( 3, 'li3', 110.12, 35.35 );
insert into user ( id, name, lng, lat ) values ( 4, 'li4', 90.12, 39.35 );
insert into user ( id, name, lng, lat ) values ( 5, 'li5', 210.12, 37.35 );
insert into user ( id, name, lng, lat ) values ( 6, 'li6', 134.16, 35.95 );
insert into user ( id, name, lng, lat ) values ( 7, 'li7', 146.17, 51.35 );
insert into user ( id, name, lng, lat ) values ( 8, 'li8', 150.12, 42.35 );
insert into user ( id, name, lng, lat ) values ( 9, 'li9', 140.92, 31.35 );
insert into user ( id, name, lng, lat ) values ( 10, 'li10', 115.12, 15.35 );
Java代码示例:
@Autowired
private UserService userService;
/**
* 近邻查询用户
*
* @return
*/
@GetMapping("/use/nearSearch")
public ResultResponse selectUserNearSearch() {
ResultResponse resp = new ResultResponse();
//使用近邻查询,先设置坐标与距离。
NearSearchTreadLocal.setNearSearchDto(130.55, 31.55, 950.55);
List<User> select = userService.select();
resp.setData(select);
resp.setMessage("success");
return resp;
}
select sql
@Select({
"<script>",
"select",
"id, ",
"name, ",
"lng, ",
"lat ",
"from user",
"</script>"
})
@ResultMap("user")
List<User> select();
使用近邻查询执行sql:
SELECT id, name, lng, lat FROM user
WHERE 1 = 1 AND lat >= 23.00151024424151 AND lat <= 40.09848975575849
AND lng >= 120.50451509566236 AND lng <= 140.59548490433767
HuTool
简介:
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
Hutool中的工具方法来自每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;
Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
本工具类集成hutool 版本为:5.5.2
hutool 官方文档:https://hutool.cn/docs/#/
使用
在 dependencyManagement 中添加如下配置。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.aliyun.gts.bpaas</groupId>
<artifactId>aliyun-gts-tool-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后在 dependencies 中添加如下依赖。
<!-- hutool 依赖 start-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- hutool使用excel需要自己引入poi-ooxml hutool 5.X poi-ooxml版本需要4.1.2以上(包含4.1.2) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- hutool 依赖 end-->
hutool http
注意:hutool的http没有使用连接池;每次发起请求都会有个新的http connection。
Java代码部分示例(HuTool更多http使用链接:https://hutool.cn/docs/#/http/%E6%A6%82%E8%BF%B0 ):
@RestController
@Slf4j
public class HutoolHttpController {
@GetMapping("/http/get")
public ResultResponse get() {
ResultResponse resp = new ResultResponse();
// 最简单的HTTP请求,可以自动通过header等信息判断编码,不区分HTTP和HTTPS
String result1 = HttpUtil.get("https://www.baidu.com");
log.info("最简单的HTTP GET请求:回参:{}", result1);
// 当无法识别页面编码的时候,可以自定义请求页面的编码
String result2 = HttpUtil.get("https://www.baidu.com", CharsetUtil.CHARSET_UTF_8);
log.info("自定义请求页面的编码 GET请求:回参:{}", result2);
//可以单独传入http参数,这样参数会自动做URL编码,拼接在URL中
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("city", "北京");
String result3 = HttpUtil.get("https://www.baidu.com", paramMap);
log.info("单独传入http参数,这样参数会自动做URL编码,拼接在URL中 GET请求:回参:{}", result3);
resp.setMessage("success");
return resp;
}
@GetMapping("/http/post")
public ResultResponse post() {
ResultResponse resp = new ResultResponse();
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("city", "北京");
String result= HttpUtil.post("https://www.baidu.com", paramMap);
log.info("post请求:回参:{}", result);
resp.setMessage("success");
return resp;
}
@GetMapping("/http/postFile")
public ResultResponse postFile() throws IOException {
ResultResponse resp = new ResultResponse();
HashMap<String, Object> paramMap = new HashMap<>();
//文件上传只需将参数中的键指定(默认file),值设为文件对象即可,对于使用者来说,文件上传与普通表单提交并无区别
ClassPathResource resource = new ClassPathResource("test.txt");
paramMap.put("file", resource.getFile());
String result= HttpUtil.post("https://www.baidu.com", paramMap);
log.info("postFile请求:回参:{}", result);
resp.setMessage("success");
return resp;
}
@GetMapping("/http/downloadFile")
public ResultResponse downloadFile() throws IOException {
ResultResponse resp = new ResultResponse();
String fileUrl = "https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%9B%BE%E7%89%87&step_word=&hs=2&pn=0&spn=0&di=110550&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=0&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=undefined&cs=2771978851%2C2906984932&os=1129264759%2C401419237&simid=4129865264%2C640069134&adpicid=0&lpn=0&ln=1439&fr=&fmq=1607429240011_R&fm=&ic=undefined&s=undefined&hd=undefined&latest=undefined©right=undefined&se=&sme=&tab=0&width=undefined&height=undefined&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fa2.att.hudong.com%2F27%2F81%2F01200000194677136358818023076.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fp7rtwg_z%26e3Bkwthj_z%26e3Bv54AzdH3Ftrw1AzdH3Fwd_d0_b8_a8daaaaa8l9m008nmncbb8badna0m_3r2_z%26e3Bip4s&gsm=1&rpstart=0&rpnum=0&islist=&querylist=&force=undefined";
//将文件下载后保存在指定路径,返回结果为下载文件大小
long size = HttpUtil.downloadFile(fileUrl, System.getProperty("user.dir"));
log.info("downloadFile请求:回参:{}", size);
resp.setMessage("success");
return resp;
}
}
hutool Excel
Java代码部分示例(HuTool更多Excel使用链接:https://hutool.cn/docs/#/poi/%E6%A6%82%E8%BF%B0 ):
@RestController
@Slf4j
public class HutoolExcelController {
@GetMapping("/excel/getReader")
public ResultResponse getReader() throws IOException {
ResultResponse resp = new ResultResponse();
ClassPathResource resource = new ClassPathResource("test.xlsx");
ExcelReader reader = ExcelUtil.getReader(resource.getPath());
log.info("ExcelReader :{}", reader.getSheetNames());
List<List<Object>> listList = reader.read();
log.info("excel list list :{}",listList);
//通过sheet编号获取
ExcelReader reader1 = ExcelUtil.getReader(resource.getPath(), 0);
log.info("ExcelReader :{}", reader1.getSheet().getSheetName());
//通过sheet名获取
ExcelReader sheet1 = ExcelUtil.getReader(resource.getInputStream(), "sheet1");
log.info("ExcelReader :{}", sheet1.getSheet().getSheetName());
resp.setMessage("success");
return resp;
}
@GetMapping("/excel/getWriter")
public ResultResponse getWriter() throws IOException {
ResultResponse resp = new ResultResponse();
ClassPathResource resource = new ClassPathResource("test.xlsx");
List<String> row1 = CollUtil.newArrayList("aa", "bb", "cc", "dd");
List<String> row2 = CollUtil.newArrayList("aa1", "bb1", "cc1", "dd1");
List<String> row3 = CollUtil.newArrayList("aa2", "bb2", "cc2", "dd2");
List<String> row4 = CollUtil.newArrayList("aa3", "bb3", "cc3", "dd3");
List<String> row5 = CollUtil.newArrayList("aa4", "bb4", "cc4", "dd4");
List<List<String>> rows = CollUtil.newArrayList(row1, row2, row3, row4, row5);
//通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter(resource.getPath());
//通过构造方法创建writer
//ExcelWriter writer = new ExcelWriter(resource.getPath());
//指定sheet写内容
writer.setSheet("test");
//跳过当前行,既第一行,非必须,在此演示用
writer.passCurrentRow();
//合并单元格后的标题行,使用默认标题样式
writer.merge(row1.size() - 1, "测试标题");
/*
* 合并单元格,并写入对象到单元格<br>
* 如果写到单元格中的内容非null,行号自动+1,否则当前行号不变<br>
* 样式为默认标题样式,可使用{@link #getHeadCellStyle()}方法调用后自定义默认样式
*
* @param firstRow 起始行,0开始
* @param lastRow 结束行,0开始
* @param firstColumn 起始列,0开始
* @param lastColumn 结束列,0开始
* @param content 合并单元格后的内容
* @param isSetHeaderStyle 是否为合并后的单元格设置默认标题样式
*/
writer.merge(2,4,0,0,"111",true);
writer.merge(5,6,0,0,"222",true);
//一次性写出内容,强制输出标题
writer.write(rows, true);
//关闭writer,释放内存
writer.close();
//通过sheet名获取
ExcelReader sheet1 = ExcelUtil.getReader(resource.getInputStream(), "test");
log.info("ExcelReader :{}", sheet1.read());
resp.setMessage("success");
return resp;
}
}
上面getWriter方法导出的excel表格格式如下图:
Data-Factory
简介:
此项目主要用于根据对象来随机自动生成初始化信息,便于数据mock和测试。
具备一下特性:
8 大基本类型的支持
数组、对象、枚举、Map、链表、Set 等支持
String、BigDecimal、BigInteger、Currency 等常见类型的支持
Date、LocalDate、LocalDateTime、LocalTime、Year 等常见日期类型支持
支持 Regex 正则表达式
@DataFactory 注解支持灵活配置
官网地址:https://github.com/houbb/data-factory
基础使用:
注解属性
/**
* 数据生成注解
* @author binbin.hou
* @date 2019/3/9
* @since 0.0.2
*/
@Inherited
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataFactory {
/**
* 是否忽略此字段
*
* @return 默认不忽略
*/
boolean ignore() default false;
/**
* 数字整数部分最大值。
* 只作用于数字类型的字段
*
* @return 返回最大值
*/
int max() default 100;
/**
* 数字整数部分最小值。
* 只作用于数字类型的字段
*
* @return 返回最小值
*/
int min() default 0;
/**
* 精度。
* 作用于Float、Double、BigDecimal 小数部分长度
*
* @return 返回精度
*/
int precision() default 2;
/**
* 最大长度。只作用于String类型的字段
*
* @return 返回最大长度
*/
int maxLen() default 30;
/**
* 最小长度。只作用于String类型的字段
*
* @return 返回最小长度
*/
int minLen() default 1;
/**
* 指定当前字段的类实现策略
* @return 实现类
* @since 0.0.6
*/
Class<? extends IData> data() default IData.class;
}
详见:https://github.com/houbb/data-factory/blob/master/doc/blog/DataFactory-01-%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81.md
构造对象
@Data
public class UserExamples {
private String name;
@DataFactory(min = 1, max = 100)
private Integer age;
private Date birthday;
private LocalDateTime localDateTime;
private List<String> stringList;
private StatusEnum statusEnum;
private Map<String, String> map;
}
构建方法
UserExamples userExamples = DataUtil.build(UserExamples.class)
示例接口
/**
* 返回mock示例用户对象
* @return 示例用户对象
*/
@GetMapping("/dataFactory/userExample/build")
public ResultResponse<UserExamples> buildUserExample() {
return ResultResponse.success(dataFactoryService.buildUserExample());
}
实际调用返回
{
"message": "success",
"data": {
"name": "R",
"age": 92,
"birthday": "2021-01-28T09:36:27.420+0000",
"localDateTime": "2021-01-28T17:36:27.423",
"stringList": [
"1dTjYhHfHW96EGzVsKHMrJx",
"LqApqTp",
"HwyOg43A2xJTfx",
"EsFYgZdwEQysvbmclDAOwAletDm",
"cOLLG7vGl0H6tPYxhi"
],
"statusEnum": "WORKING",
"map": {
"CwZRzuigeGJAIPEiluqwkhyUq1yZ": "D1DlY6Cu",
"kfyvlBDYw1Qwy0JqfbNHuC": "dh3bEj",
"Xrk8nkD": "7PW7uXde41C6HvokuMoCT5yKt",
"Fa2egqRFCpG": "oI9Do1WZdHWFfVs9fgwRLq2GpB",
"6": "achr3",
"Y5xLYwgGuBItgqTbZ": "DStj9taKwL1umXMFXsSUyeI"
}
}
}
自定义配置使用:
自定义实现
public class MyFormatLocalDateTime implements IData<String>{
@Override
public String build(IContext iContext, Class<String> aClass) {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
}
public class MyStringData implements IData<String> {
@Override
public String build(IContext context, Class<String> stringClass) {
return "test";
}
}
构造对象
public class CustomizeExamples {
@DataFactory(data = MyStringData.class)
private String testStringCustomize;
private LocalDateTime localDateTime;
@DataFactory(data = MyFormatLocalDateTime.class)
private String testFormatLocalDateTime;
}
构建方法
CustomizeExamples customizeExamples = DataUtil.build(CustomizeExamples.class)
示例接口
/**
* 返回自定义示例对象
* @return 自定义示例对象
*/
@GetMapping("/dataFactory/customizeExample/build")
public ResultResponse<CustomizeExamples> buildCustomizeExample(){
return ResultResponse.success(dataFactoryService.buildCustomizeExample());
}
实际调用返回
{
"message": "success",
"data": {
"testStringCustomize": "test",
"localDateTime": "2021-01-28T16:56:15.95",
"testFormatLocalDateTime": "2021-01-28 16:56:15"
}
}
流水号生成
如果需要使用已发布的版本,在 dependencyManagement 中添加如下配置。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.aliyun.gts.bpaas</groupId>
<artifactId>aliyun-gts-tool-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后在 dependencies 中添加如下依赖。
<dependency>
<groupId>com.aliyun.gts.bpaas</groupId>
<artifactId>aliyun-gts-tool-serial-number</artifactId>
</dependency>
主键生成
Long primaryKey = SerialNumberUtil.genPrimaryKey();
业务号生成
业务号生成有两种方式
1.调用SerialNumberUtil的genSerialNum()方法生成
2.用注解+实现接口的方式去生成
方法和参数介绍
/**
* 生成流水号 若需要隐藏跟多的参数进来,可以加传参。如订单类型(订单id就没啥必要了)等等
*
* @param serviceType 业务类型,比如订单号、消费流水号、操作流水号等等 请保持一个公司内不要重复
* 最大值:30(11110) 占5位
* @param shortParam 短参数 不具体定义什么 一般用于表示类型。如这表示订单流水号,这里可以表示订单类型
* 最大值:30(11110) 占5位
* @param longParam 长参数,一般用于记录id参数什么的,比如是订单的话,这里可以表示商户ID(商户一般不会非常多吧)
* 最大值:999999999(101111101011110000011111111) 占30位 表示9.999亿的数据 相信作为id的话,一般都超不过这个数值吧
* @return 流水号 年月日时分秒+long类型的数字 = string串
*/
public static String genSerialNum(long serviceType, long shortParam, long longParam)
SerialNumberUtil
String serialNum = SerialNumberUtil.genSerialNum(1, 2, 300);
注解+实现接口
测试类
@SerialCodeServiceType(serviceType = 1) // 业务类型注解,最大值30
@Data
public class BizOrder implements SerialCodeGenerable {
@SerialCodeShortParam // 短参数注解,整型,不能大于30,
private Integer orderType; // 保存短参数的属性
@SerialCodeLongParam // 长参数注解,整型,不能大于999999999
private Long orderId; // 保存长参数的属性
private LocalDateTime createTime;
@StoreSerialNumber // 保存业务号的注解;作用:同一个对象多次调用getSerialNumber方法只会生成一次业务号
private String orderCode; // 保存业务号的属性
public static void main(String[] args) {
// 方式2
BizOrder bizOrder = new BizOrder();
bizOrder.setOrderType(2);
bizOrder.setOrderId(26456785L);
String serialNum = bizOrder.getSerialNumber();
}
}
通过业务号反推出serviceType,shortParam,longParam示例
public static void main(String[] args) {
// 生成主键
System.out.println(SerialNumberUtil.genPrimaryKey());
System.out.println(SerialNumberUtil.genSerialNum(1,2,26456785L));
System.out.println(serialNum); //20181121173040299068801480344
//拿到日期时间
System.out.println(SerialNumber.getDate(serialNum)); //2018-11-21T17:30:40
//拿毫秒值
System.out.println(SerialNumber.getMills(serialNum));
//拿到serviceType
System.out.println(SerialNumber.getServiceType(serialNum)); //1
//拿到shortParam
System.out.println(SerialNumber.getShortParam(serialNum)); //2
//拿到longParam
System.out.println(SerialNumber.getLongParam(serialNum)); //26456785L
}