栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot中通过lua脚本来获取序列号的方法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot中通过lua脚本来获取序列号的方法

序言:

事件:此web项目的功能及其简单,就是有客户端来访问redis序列号服务时发送jison报文,项目已经在测试环境成功运行2周了,具体的代码我就直接上了,此博客仅是自己的记录,同学们可做参考!

一、工程目录结构

二、配置文件

1、pom.xml



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.2.6.RELEASE
		 
	
	com.test
	seq-gen
	0.0.1-SNAPSHOT
	seq-gen
	generate sequence from redis

	
		UTF-8
		UTF-8
		1.8
	

	
		
		

		
		
			org.apache.logging.log4j
			log4j-api
			2.11.1
		
		
			org.apache.logging.log4j
			log4j-core
			2.11.1
		
		
			org.apache.logging.log4j
			log4j-web
			2.11.1
		
		
		
			org.apache.logging.log4j
			log4j-slf4j-impl
			2.11.1
		
		
		
			org.apache.logging.log4j
			log4j-1.2-api
			2.11.1
		
		
		
			com.lmax
			disruptor
			3.4.2
		
		
			org.slf4j
			slf4j-api
			1.7.21
		

		
			org.springframework.boot
			spring-boot-starter-data-redis
		
		
			com.alibaba
			fastjson
			1.2.62
		
		
			redis.clients
			jedis
		

		
			org.springframework.boot
			spring-boot-starter-web
		
		
			org.springframework.boot
			spring-boot-starter
			
				
					org.springframework.boot
					spring-boot-starter-logging
				
			
		
		
		
			org.springframework.boot
			spring-boot-devtools
			true
		
		
			org.projectlombok
			lombok
			true
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
	

	
		
			
				org.apache.maven.plugins
				maven-compiler-plugin
				
					1.8
					1.8
				
			
			
				org.springframework.boot
				spring-boot-maven-plugin
				
					
						
							repackage
						
					
				
			
			
				org.apache.maven.plugins
				maven-surefire-plugin
				2.4.2
				
					true
				
			
		
	

2、applicaiton.properties

spring.redis.database= 0
spring.redis.host= 127.0.0.1
spring.redis.port= 6379
spring.redis.pool.max-active= 8
spring.redis.pool.max-wait= -1ms
spring.redis.pool.max-idle= 8
spring.redis.pool.min-idle= 0
spring.redis.pool.timeout= 2000ms
server.port= 8085

3、luascripts脚本

local function get_next_seq()
 --KEYS[1]:第一个参数代表存储序列号的key 相当于代码中的业务类型
 local key = tostring(KEYS[1])
 --KEYS[2]:第二个参数代表序列号增长速度
 local incr_amoutt = tonumber(KEYS[2])
 --KEYS[3]`:第四个参数为序列号 (yyMMddHHmmssSSS + 两位随机数)
 local seq = tonumber(KEYS[3])
 --序列号过期时间大小,单位是秒
 -- local month_in_seconds = 24 * 60 * 60 * 7

 --Redis的 SETNX 命令可以实现分布式锁,用于解决高并发
 --如果key不存在,将 key 的值设为 seq,设置成成功返回1 未设置返回0
 --若给定的 key 已经存在,则 SETNX 不做任何动作,获取下一个按照步增的值

 if (1 == redis.call('setnx', key, seq)) --不存在key,
 then
 --设置key的生存时间 为 month_in_seconds秒
 -- 由于序列号需要永久有效,不能过期,所以取消这个设置,需要的可以取消注释
 -- redis.call('expire', key, month_in_seconds)
 --将序列返回给调用者
  return seq
 else
 --key值存在,直接获取下一个增加的值
  local nextSeq = redis.call('incrby', key, incr_amoutt)
  return nextSeq
 end
end
return get_next_seq()

4、log4j2.xml






 
  logs
 
 
 
  
  
   
   
   
   
  
  
  
   
   
   

   
    
    
   
  
  
   
   
   
    
    
   
   
   
  

  
   
   
   
    
    
   
  
 
 
 
  
  
  
  
   
  
  
   
   
   
   
  
 

三、代码部分

1、启动类

package com.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SeqGenApplication {
	private static final Logger log = LoggerFactory.getLogger(SeqGenApplication.class);
	public static void main(String[] args) {
		SpringApplication.run(SeqGenApplication.class, args);
		log.info("start SeqGenApplication sucessfully........");
	}
}

2、Bean

package com.test.bean;

import com.alibaba.fastjson.annotation.JSONField;


public class RspBean {
 public RspBean(){}
 
 @JSonField(name = "SNNumB")
 private Integer sNNumB;
 
 @JSonField(name = "SNNumE")
 private Integer sNNumE;
 
 @JSonField(name = "OprNumb")
 private String 	oprNumb;
 
 @JSonField(name = "OprTime")
 private String oprTime;
 
 @JSonField(name = "BizOrderResult")
 private String bizOrderResult;
 
 @JSonField(name = "ResultDesc")
 private String resultDesc;


 public Integer getSNNumB() {
  return sNNumB;
 }

 public void setSNNumB(Integer sNNumB) {
  this.sNNumB = sNNumB;
 }

 public Integer getSNNumE() {
  return sNNumE;
 }

 public void setSNNumE(Integer sNNumE) {
  this.sNNumE = sNNumE;
 }

 public String getOprNumb() {
  return oprNumb;
 }

 public void setOprNumb(String oprNumb) {
  this.oprNumb = oprNumb;
 }

 public String getOprTime() {
  return oprTime;
 }

 public void setOprTime(String oprTime) {
  this.oprTime = oprTime;
 }

 public String getBizOrderResult() {
  return bizOrderResult;
 }

 public void setBizOrderResult(String bizOrderResult) {
  this.bizOrderResult = bizOrderResult;
 }

 public String getResultDesc() {
  return resultDesc;
 }

 public void setResultDesc(String resultDesc) {
  this.resultDesc = resultDesc;
 }

 @Override
 public String toString() {
  return "RspBean{" +
    "sNNumB=" + sNNumB +
    ", sNNumE=" + sNNumE +
    ", oprNumb='" + oprNumb + ''' +
    ", oprTime='" + oprTime + ''' +
    ", bizOrderResult='" + bizOrderResult + ''' +
    ", resultDesc='" + resultDesc + ''' +
    '}';
 }
}

3、Controller

package com.test.controller;

import com.test.bean.RspBean;
import com.test.service.RedisService;
import com.test.util.CommonUtils;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;



@RestController
public class RedisControlLer {

 private static final Logger log = LoggerFactory.getLogger(RedisControlLer.class);
 @Autowired
 private RedisTemplate redisTemplate;

 @Autowired
 private RedisService redisService;

 @PostMapping(path = "/app/v1/sync/bizOrder/QuerySerialNumber", consumes = "application/json", produces = "application/json")
 public String rcvReq(@RequestBody String jsonparam){

  String prettyJson= CommonUtils.prettyJson(jsonparam);
  log.info("receive requset: ");
  log.info("rn"+prettyJson);
  JSonObject jsonObject = new JSonObject();
  RspBean rw = new RspBean();
  String response = null;
  Map jsonMap = new HashMap();
  try {
   // 将报文放入map中
   jsonMap = CommonUtils.putReq2Map(jsonparam);
   response = redisService.createResponse(jsonMap);
   prettyJson = CommonUtils.prettyJson(response);
   log.info("send Response: ");
   log.info("rn"+prettyJson);
  } catch (Exception ex) {
   if (null == jsonObject || 0 == jsonObject.size()) {
    try {
     String oprNumb = jsonMap.get("oprNumb");
     rw.setOprNumb(oprNumb);
     rw.setBizOrderResult("30000");
     rw.setResultDesc(ex.getMessage());
     JSonObject json = (JSONObject) JSONObject.toJSON(rw);
     response = json.toString();
    } catch (Exception e) {
     e.printStackTrace();
    }
    return response;
   }
  }
  return response;
 }
}

4、Service

package com.test.service;

import java.util.Map;

public interface RedisService {
  String createResponse(Map jsonMap);
}

ServiceImpl

package com.test.service;

import com.test.bean.RspBean;
import com.test.util.CommonUtils;
import com.test.util.RedisUtil;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;



@Component
@Service
public class RedisServiceImpl implements RedisService {
 private static final Logger log = LoggerFactory.getLogger(RedisServiceImpl.class);
 @Override
 public String createResponse(Map jsonMap) {
  String response = null;
  RspBean rw = null;
  JSonObject json = null;

  // 之所以要遍历map是因为怕传过来的key值有小写的,怕get不到对应的值
  String key = null;
  String sNNamevalue = null;
  String increAmountValue = null;
  for (Map.Entry entry : jsonMap.entrySet()) {
   key = entry.getKey();
   if ("SNName".equalsIgnoreCase(key)) {
    sNNamevalue = entry.getValue();
   } else if("SNNum".equalsIgnoreCase(key)){
    increAmountValue = entry.getValue();
   }
  }
  String seq="0";
  // 从redis中获取序列号(根据序列号名称和步长获取序列号)
  List busilist = Arrays.asList(sNNamevalue,increAmountValue,seq);

  Long seqFromRedis = null;
  try {
   seqFromRedis = RedisUtil.getBusiSeq(busilist);
  } catch (Exception e) {
   log.error("cannot get seq from redis cluster ,please check redis cluster"+ "_" + e.getMessage(), e);
  }
  log.info("seqFromRedis:{}", seqFromRedis);
  String oprNumb = jsonMap.get("OprNumb");
  String oprTime = CommonUtils.getCurDateTimestamp();
  try {
   rw = new RspBean();
   int sNNumB;
   if(!StringUtils.isEmpty(seqFromRedis)){
    sNNumB=seqFromRedis.intValue();
    rw.setSNNumB(sNNumB);
    rw.setSNNumE(sNNumB+Integer.parseInt(increAmountValue));
    rw.setBizOrderResult("00000");
    rw.setResultDesc("Success");
   }else{
    rw.setSNNumB(0);
    rw.setSNNumE(0);
    rw.setBizOrderResult("30000");
    rw.setResultDesc("business handles failed....");
   }
   rw.setOprNumb(oprNumb);
   rw.setOprTime(oprTime);
   json = (JSONObject) JSONObject.toJSON(rw);
   response = json.toString();
  } catch (Exception e) {
   log.error("boxing response of json happend error "+ "_" + e.getMessage(), e);
   if (rw != null) {
    rw.setBizOrderResult("30000");
    rw.setResultDesc("business handles failed......");
    json = (JSONObject) JSONObject.toJSON(rw);
    response = json.toString();
   }
   log.info("send Response: [ {} ]", response );
   jsonMap.put("responseToWzw", response);
   return response;

  }
  return response;
 }
}

5、Utils

5.1 CommonUtils

package com.test.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Map;


public class CommonUtils {
 private static final Logger log = LoggerFactory.getLogger(CommonUtils.class);
 public static Map putReq2Map(String jsonparam) {
  // 将json字符串转换为json对象
  return (Map) JSONObject.parse(jsonparam);
 }

 
 public static String getCurDateTimestamp(){
  DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
  LocalDateTime localDateTime = LocalDateTime.now();
  String now=localDateTime.format(dateTimeFormatter);
  return now;
 }

 
 public static String prettyJson(String reqJson){
  JSonObject object = JSONObject.parseObject(reqJson);
  String prettyJson = JSON.toJSonString(object, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue,SerializerFeature.WriteDateUseDateFormat);
  return prettyJson;
 }
}

5.2 ReadConfigsPathUtil

package com.test.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class ReadConfigsPathUtil {
 private static final Logger log = LoggerFactory.getLogger(ReadConfigsPathUtil.class);
 private ReadConfigsPathUtil() {}
 private static Properties properties = null;

 
 public static String getPropertiesPath(String configPath) {
  String sysPath = getRelativePath();
  log.info("sysPath:{}",sysPath);
   String filepath = new StringBuffer(sysPath)
     .append(File.separator)
     .append("config")
     .append(File.separator)
     .append(configPath).toString();
  log.info("filepath:{}",filepath);
  return filepath;
 }
 
 public static String getRelativePath() {
  return System.getProperty("user.dir");
 }

 
 public static String readFileContent(String luascriptPath) {
  String filename = getPropertiesPath(luascriptPath);
  File file = new File(filename);
  BufferedReader reader = null;
  StringBuffer sbf = new StringBuffer();
  try {
   reader = new BufferedReader(new FileReader(file));
   String tempStr;
   while ((tempStr = reader.readLine()) != null) {
    sbf.append(tempStr);
    sbf.append("rn");
   }
   reader.close();
   return sbf.toString();
  } catch (IOException e) {
   e.printStackTrace();
  } finally {
   if (reader != null) {
    try {
     reader.close();
    } catch (IOException e1) {
     e1.printStackTrace();
    }
   }
  }
  return sbf.toString();
 }
}

5.3 RedisUtil

package com.test.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisscript;
import org.springframework.data.redis.core.script.DefaultscriptExecutor;
import org.springframework.data.redis.core.script.Redisscript;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import java.io.IOException;
import java.util.List;


@Component
public class RedisUtil {
 private static final Logger log = LoggerFactory.getLogger(RedisUtil.class);

 private static StringRedisTemplate redisStringTemplate;

 private static Redisscript redisscript;

 private static DefaultscriptExecutor scriptExecutor;

 private RedisUtil(StringRedisTemplate template) throws IOException {
  RedisUtil.redisStringTemplate = template;
   // 之所以会注释掉是由于这段代码可以直接读取resource目录下的非application.properties的文件,
   // 但是这个方法在生产和测试环境不适用,因为配置文件必须暴露初打的jar包里
//  ClassPathResource luaResource = new ClassPathResource("luascript/genSeq.lua");
//  EncodedResource encRes = new EncodedResource(luaResource, "UTF-8");
//  String luaString = FileCopyUtils.copyToString(encRes.getReader());

  String luaString = ReadConfigsPathUtil.readFileContent("luascript/genSeq.lua");
  redisscript = new DefaultRedisscript<>(luaString, Long.class);
  scriptExecutor = new DefaultscriptExecutor<>(redisStringTemplate);
 }
 public static Long getBusiSeq(List Busilist) throws Exception{
  Long seqFromRedis = scriptExecutor.execute(redisscript, Busilist);
  return seqFromRedis;
 }
}

总结

到此这篇关于springboot中通过lua脚本来获取序列号的文章就介绍到这了,更多相关springboot中通过lua脚本来获取序列号内容请搜索考高分网以前的文章或继续浏览下面的相关文章希望大家以后多多支持考高分网!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/133808.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号