parent
9a4fffe495
commit
043db3e726
@ -0,0 +1,109 @@ |
||||
package com.gitee.sop.adminserver.api.isv; |
||||
|
||||
import com.gitee.easyopen.annotation.Api; |
||||
import com.gitee.easyopen.annotation.ApiService; |
||||
import com.gitee.easyopen.doc.annotation.ApiDoc; |
||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod; |
||||
import com.gitee.easyopen.util.CopyUtil; |
||||
import com.gitee.easyopen.util.KeyStore; |
||||
import com.gitee.easyopen.util.RSAUtil; |
||||
import com.gitee.fastmybatis.core.PageInfo; |
||||
import com.gitee.fastmybatis.core.query.Query; |
||||
import com.gitee.fastmybatis.core.support.PageEasyui; |
||||
import com.gitee.fastmybatis.core.util.MapperUtil; |
||||
import com.gitee.sop.adminserver.api.isv.param.IsvInfoForm; |
||||
import com.gitee.sop.adminserver.api.isv.param.IsvInfoFormAdd; |
||||
import com.gitee.sop.adminserver.api.isv.param.IsvInfoFormUpdate; |
||||
import com.gitee.sop.adminserver.api.isv.param.IsvPageParam; |
||||
import com.gitee.sop.adminserver.api.isv.result.AppKeySecretVo; |
||||
import com.gitee.sop.adminserver.api.isv.result.IsvVO; |
||||
import com.gitee.sop.adminserver.api.isv.result.PubPriVo; |
||||
import com.gitee.sop.adminserver.common.IdGen; |
||||
import com.gitee.sop.adminserver.entity.IsvInfo; |
||||
import com.gitee.sop.adminserver.mapper.IsvInfoMapper; |
||||
import com.google.common.collect.Sets; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@ApiService |
||||
@ApiDoc("ISV管理") |
||||
public class IsvApi { |
||||
|
||||
@Autowired |
||||
IsvInfoMapper isvInfoMapper; |
||||
|
||||
@Api(name = "isv.info.page") |
||||
@ApiDocMethod(description = "接入方列表") |
||||
PageEasyui pageIsv(IsvPageParam param) { |
||||
Query query = Query.build(param); |
||||
PageInfo<IsvInfo> pageInfo = MapperUtil.query(isvInfoMapper, query); |
||||
List<IsvInfo> list = pageInfo.getList(); |
||||
|
||||
List<IsvVO> retList = new ArrayList<>(list.size()); |
||||
|
||||
for (IsvInfo permClient : list) { |
||||
IsvVO vo = new IsvVO(); |
||||
CopyUtil.copyProperties(permClient, vo); |
||||
//vo.setRoleList(this.buildClientRole(permClient));
|
||||
retList.add(vo); |
||||
} |
||||
|
||||
PageEasyui<IsvVO> pageInfoRet = new PageEasyui<>(); |
||||
pageInfoRet.setTotal(pageInfo.getTotal()); |
||||
pageInfoRet.setList(retList); |
||||
|
||||
return pageInfoRet; |
||||
} |
||||
|
||||
@Api(name = "isv.info.add") |
||||
@ApiDocMethod(description = "添加isv") |
||||
void addIsv(IsvInfoFormAdd param) { |
||||
IsvInfo rec = new IsvInfo(); |
||||
CopyUtil.copyPropertiesIgnoreNull(param, rec); |
||||
isvInfoMapper.saveIgnoreNull(rec); |
||||
|
||||
// this.saveClientRole(rec, param.getRoleCode());
|
||||
// TODO:发送消息队列到zookeeper
|
||||
} |
||||
|
||||
@Api(name = "isv.info.update") |
||||
@ApiDocMethod(description = "修改isv") |
||||
void updateIsv(IsvInfoFormUpdate param) { |
||||
IsvInfo rec = isvInfoMapper.getById(param.getId()); |
||||
CopyUtil.copyPropertiesIgnoreNull(param, rec); |
||||
isvInfoMapper.updateIgnoreNull(rec); |
||||
|
||||
// this.saveClientRole(rec, param.getRoleCode());
|
||||
|
||||
// syncService.syncAppSecretConfig(Sets.newHashSet(param.getApp()));
|
||||
// TODO:发送消息队列到zookeeper
|
||||
} |
||||
|
||||
@Api(name = "isv.pubprikey.create") |
||||
@ApiDocMethod(description = "生成公私钥") |
||||
PubPriVo createPubPriKey() throws Exception { |
||||
KeyStore keyStore = RSAUtil.createKeys(); |
||||
PubPriVo vo = new PubPriVo(); |
||||
vo.setPubKey(keyStore.getPublicKey()); |
||||
vo.setPriKey(keyStore.getPrivateKey()); |
||||
return vo; |
||||
} |
||||
|
||||
@Api(name = "isv.appkeysecret.create") |
||||
@ApiDocMethod(description = "生成appkey") |
||||
AppKeySecretVo createAppKeySecret() { |
||||
String appKey = new SimpleDateFormat("yyyyMMdd").format(new Date()) + IdGen.nextId(); |
||||
String secret = IdGen.uuid(); |
||||
AppKeySecretVo vo = new AppKeySecretVo(); |
||||
vo.setAppKey(appKey); |
||||
vo.setSecret(secret); |
||||
return vo; |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
package com.gitee.sop.adminserver.api.isv.param; |
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||
import lombok.Data; |
||||
import org.hibernate.validator.constraints.Length; |
||||
|
||||
import javax.validation.constraints.NotBlank; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Data |
||||
public class IsvInfoForm { |
||||
/** secret, 数据库字段:secret */ |
||||
@ApiDocField(description = "secret", required = true) |
||||
@NotBlank(message = "secret不能为空") |
||||
@Length(max = 100,message = "secret长度不能超过100") |
||||
private String secret; |
||||
|
||||
/** 公钥, 数据库字段:pub_key */ |
||||
@ApiDocField(description = "pubKey", required = true) |
||||
@NotBlank(message = "pubKey不能为空") |
||||
private String pubKey; |
||||
|
||||
/** 私钥, 数据库字段:pri_key */ |
||||
@ApiDocField(description = "priKey", required = true) |
||||
@NotBlank(message = "priKey不能为空") |
||||
private String priKey; |
||||
|
||||
/** 0启用,1禁用, 数据库字段:status */ |
||||
@ApiDocField(description = "状态:0:启用,1:禁用") |
||||
private Byte status = 0; |
||||
|
||||
// @NotEmpty(message = "角色不能为空")
|
||||
// private List<String> roleCode;
|
||||
} |
@ -0,0 +1,21 @@ |
||||
package com.gitee.sop.adminserver.api.isv.param; |
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
import org.hibernate.validator.constraints.Length; |
||||
|
||||
import javax.validation.constraints.NotBlank; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
public class IsvInfoFormAdd extends IsvInfoForm { |
||||
/** appKey, 数据库字段:app_key */ |
||||
@ApiDocField(description = "appKey", required = true) |
||||
@NotBlank(message = "appKey不能为空") |
||||
@Length(max = 100,message = "appKey长度不能超过100") |
||||
private String appKey; |
||||
} |
@ -0,0 +1,18 @@ |
||||
package com.gitee.sop.adminserver.api.isv.param; |
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import javax.validation.constraints.NotNull; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
public class IsvInfoFormUpdate extends IsvInfoForm { |
||||
@ApiDocField(description = "id") |
||||
@NotNull(message = "id不能为空") |
||||
private Long id; |
||||
} |
@ -0,0 +1,14 @@ |
||||
package com.gitee.sop.adminserver.api.isv.param; |
||||
|
||||
import com.gitee.fastmybatis.core.query.param.PageParam; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
public class IsvPageParam extends PageParam { |
||||
private String appKey; |
||||
} |
@ -0,0 +1,9 @@ |
||||
package com.gitee.sop.adminserver.api.isv.result; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class AppKeySecretVo { |
||||
private String appKey; |
||||
private String secret; |
||||
} |
@ -0,0 +1,36 @@ |
||||
package com.gitee.sop.adminserver.api.isv.result; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author thc |
||||
*/ |
||||
@Data |
||||
public class IsvVO { |
||||
/** 数据库字段:id */ |
||||
private Long id; |
||||
|
||||
/** appKey, 数据库字段:app_key */ |
||||
private String appKey; |
||||
|
||||
/** secret, 数据库字段:secret */ |
||||
private String secret; |
||||
|
||||
/** 公钥, 数据库字段:pub_key */ |
||||
private String pubKey; |
||||
|
||||
/** 私钥, 数据库字段:pri_key */ |
||||
private String priKey; |
||||
|
||||
/** 0启用,1禁用, 数据库字段:status */ |
||||
private Byte status; |
||||
|
||||
/** 数据库字段:gmt_create */ |
||||
private Date gmtCreate; |
||||
|
||||
/** 数据库字段:gmt_modified */ |
||||
private Date gmtModified; |
||||
} |
@ -0,0 +1,10 @@ |
||||
package com.gitee.sop.adminserver.api.isv.result; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class PubPriVo { |
||||
private String pubKey; |
||||
private String priKey; |
||||
|
||||
} |
@ -0,0 +1,167 @@ |
||||
package com.gitee.sop.adminserver.common; |
||||
|
||||
import java.util.UUID; |
||||
|
||||
public class IdGen { |
||||
private static long workId = 0; |
||||
private static SnowflakeIdWorker worker = new SnowflakeIdWorker(workId++, 0); |
||||
|
||||
/** |
||||
* 生成唯一id |
||||
* @return |
||||
*/ |
||||
public static String nextId() { |
||||
return String.valueOf(worker.nextId()); |
||||
} |
||||
|
||||
public static String uuid() { |
||||
return UUID.randomUUID().toString().replace("-", ""); |
||||
} |
||||
|
||||
/** |
||||
* Twitter_Snowflake<br> |
||||
* SnowFlake的结构如下(每部分用-分开):<br> |
||||
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br> |
||||
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br> |
||||
* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) |
||||
* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br> |
||||
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br> |
||||
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br> |
||||
* 加起来刚好64位,为一个Long型。<br> |
||||
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 |
||||
*/ |
||||
public static class SnowflakeIdWorker { |
||||
|
||||
// ==============================Fields===========================================
|
||||
/** 开始时间截 (2015-01-01) */ |
||||
private final long twepoch = 1420041100000L; |
||||
|
||||
/** 机器id所占的位数 */ |
||||
private final long workerIdBits = 5L; |
||||
|
||||
/** 数据标识id所占的位数 */ |
||||
private final long datacenterIdBits = 5L; |
||||
|
||||
/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ |
||||
private final long maxWorkerId = -1L ^ (-1L << workerIdBits); |
||||
|
||||
/** 支持的最大数据标识id,结果是31 */ |
||||
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); |
||||
|
||||
/** 序列在id中占的位数 */ |
||||
private final long sequenceBits = 12L; |
||||
|
||||
/** 机器ID向左移12位 */ |
||||
private final long workerIdShift = sequenceBits; |
||||
|
||||
/** 数据标识id向左移17位(12+5) */ |
||||
private final long datacenterIdShift = sequenceBits + workerIdBits; |
||||
|
||||
/** 时间截向左移22位(5+5+12) */ |
||||
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; |
||||
|
||||
/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */ |
||||
private final long sequenceMask = -1L ^ (-1L << sequenceBits); |
||||
|
||||
/** 工作机器ID(0~31) */ |
||||
private long workerId; |
||||
|
||||
/** 数据中心ID(0~31) */ |
||||
private long datacenterId; |
||||
|
||||
/** 毫秒内序列(0~4095) */ |
||||
private long sequence = 0L; |
||||
|
||||
/** 上次生成ID的时间截 */ |
||||
private long lastTimestamp = -1L; |
||||
|
||||
//==============================Constructors=====================================
|
||||
/** |
||||
* 构造函数 |
||||
* @param workerId 工作ID (0~31) |
||||
* @param datacenterId 数据中心ID (0~31) |
||||
*/ |
||||
public SnowflakeIdWorker(long workerId, long datacenterId) { |
||||
if (workerId > maxWorkerId || workerId < 0) { |
||||
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); |
||||
} |
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) { |
||||
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); |
||||
} |
||||
this.workerId = workerId; |
||||
this.datacenterId = datacenterId; |
||||
} |
||||
|
||||
// ==============================Methods==========================================
|
||||
/** |
||||
* 获得下一个ID (该方法是线程安全的) |
||||
* @return SnowflakeId |
||||
*/ |
||||
public synchronized long nextId() { |
||||
long timestamp = timeGen(); |
||||
|
||||
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
|
||||
if (timestamp < lastTimestamp) { |
||||
throw new RuntimeException( |
||||
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); |
||||
} |
||||
|
||||
//如果是同一时间生成的,则进行毫秒内序列
|
||||
if (lastTimestamp == timestamp) { |
||||
sequence = (sequence + 1) & sequenceMask; |
||||
//毫秒内序列溢出
|
||||
if (sequence == 0) { |
||||
//阻塞到下一个毫秒,获得新的时间戳
|
||||
timestamp = tilNextMillis(lastTimestamp); |
||||
} |
||||
} |
||||
//时间戳改变,毫秒内序列重置
|
||||
else { |
||||
sequence = 0L; |
||||
} |
||||
|
||||
//上次生成ID的时间截
|
||||
lastTimestamp = timestamp; |
||||
|
||||
//移位并通过或运算拼到一起组成64位的ID
|
||||
return ((timestamp - twepoch) << timestampLeftShift) //
|
||||
| (datacenterId << datacenterIdShift) //
|
||||
| (workerId << workerIdShift) //
|
||||
| sequence; |
||||
} |
||||
|
||||
/** |
||||
* 阻塞到下一个毫秒,直到获得新的时间戳 |
||||
* @param lastTimestamp 上次生成ID的时间截 |
||||
* @return 当前时间戳 |
||||
*/ |
||||
protected long tilNextMillis(long lastTimestamp) { |
||||
long timestamp = timeGen(); |
||||
while (timestamp <= lastTimestamp) { |
||||
timestamp = timeGen(); |
||||
} |
||||
return timestamp; |
||||
} |
||||
|
||||
/** |
||||
* 返回以毫秒为单位的当前时间 |
||||
* @return 当前时间(毫秒) |
||||
*/ |
||||
protected long timeGen() { |
||||
return System.currentTimeMillis(); |
||||
} |
||||
|
||||
} |
||||
/*//==============================Test=============================================
|
||||
*/ |
||||
/** 测试 |
||||
public static void main(String[] args) { |
||||
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0); |
||||
for (int i = 0; i < 100; i++) { |
||||
long id = idWorker.nextId(); |
||||
System.out.println("id:" + id); |
||||
System.out.println("toBinaryString:" + Long.toBinaryString(id)); |
||||
} |
||||
} |
||||
*/ |
||||
} |
@ -0,0 +1,49 @@ |
||||
package com.gitee.sop.adminserver.entity; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.util.Date; |
||||
|
||||
import javax.persistence.Column; |
||||
import javax.persistence.GeneratedValue; |
||||
import javax.persistence.GenerationType; |
||||
import javax.persistence.Id; |
||||
import javax.persistence.Table; |
||||
|
||||
|
||||
/** |
||||
* 表名:isv_info |
||||
* 备注:isv信息表 |
||||
* |
||||
* @author tanghc |
||||
*/ |
||||
@Table(name = "isv_info") |
||||
@Data |
||||
public class IsvInfo { |
||||
@Id |
||||
@Column(name = "id") |
||||
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
/** 数据库字段:id */ |
||||
private Long id; |
||||
|
||||
/** appKey, 数据库字段:app_key */ |
||||
private String appKey; |
||||
|
||||
/** secret, 数据库字段:secret */ |
||||
private String secret; |
||||
|
||||
/** 公钥, 数据库字段:pub_key */ |
||||
private String pubKey; |
||||
|
||||
/** 私钥, 数据库字段:pri_key */ |
||||
private String priKey; |
||||
|
||||
/** 0启用,1禁用, 数据库字段:status */ |
||||
private Byte status; |
||||
|
||||
/** 数据库字段:gmt_create */ |
||||
private Date gmtCreate; |
||||
|
||||
/** 数据库字段:gmt_modified */ |
||||
private Date gmtModified; |
||||
} |
@ -0,0 +1,11 @@ |
||||
package com.gitee.sop.adminserver.mapper; |
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper; |
||||
|
||||
import com.gitee.sop.adminserver.entity.IsvInfo; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public interface IsvInfoMapper extends CrudMapper<IsvInfo, Long> { |
||||
} |
Loading…
Reference in new issue