springboot程序以jar包运行时,有时希望能够保存程序运行的状态信息,以便程序终止后,能够在重新启动程序以后,能够根据之前的状态继续进行后续的处理。
在jar包的类路径下放置一个状态信息文件snowflake.properties。
1. 保存程序状态
/**
* 文件不存在时,不影响正常使用
* 只是不能持久化顺序号
*/
public void saveCheckPoint() {
String fileName = "snowflake.properties";
String filePath = getConfFile(fileName);
try {
File confFile = new File(filePath);
if (!confFile.exists()) {
confFile.createNewFile();
}
FileOutputStream outputStream = new FileOutputStream(confFile);
String configInfo = "sequence=" + sequence;
outputStream.write(configInfo.getBytes(StandardCharsets.UTF_8));
outputStream.close();
System.out.println("id持久化成功到:" + this.sequence);
} catch (Exception e) {
e.printStackTrace();
}
}
2. 读取程序状态
/**
* 文件不存在时,不需要报错
*/
public void restoreCheckPoint() {
String fileName = "snowflake.properties";
String confPath = getConfFile(fileName);
try {
File confFile = new File(confPath);
// 文件不存在,不进行读取
if (!confFile.exists()) {
return;
}
InputStream inputStream = new FileInputStream(confFile);
// 设置1KB的缓冲区
byte buf[] = new byte[1024];
int read = inputStream.read(buf);
inputStream.close();
String buffInfo = new String(buf);
String confInfo = buffInfo.substring(0, read);
if (confInfo.startsWith("sequence=")) {
String splits[] = confInfo.split("=");
String sequence = splits[1];
this.sequence = Long.parseLong(sequence);
System.out.println("id恢复成功到:" + this.sequence);
}
} catch (Exception e) {
e.printStackTrace();
}
}
3. 状态信息文件路径
// 获取配置文件路径
public String getConfFile(String fileName)
{
URL resource1 = getClass().getResource("/");
String path = resource1.getPath();
System.out.println("path1 = " + path);
int endPos = path.indexOf(".jar!");
if(endPos > 0)
path = path.substring(0, endPos);
System.out.println("path2 = " + path);
endPos = path.lastIndexOf("/");
if(path.startsWith("file:/"))
path = path.substring(6, endPos);
else if(path.startsWith("/"))
path = path.substring(1, endPos);
System.out.println("path3 = " + path);
path = path + "/snowflake.properties";
System.out.println("path4 = " + path);
return path;
}
4. 恢复和保存状态信息
@RequestMapping("/add")
public String add()
{
restoreCheckPoint();
System.out.println("下单成功");
if(sequence == null)
sequence = 0l;
else
sequence = sequence + 1;
saveCheckPoint();
return "Hello world!";
}
这里按照每次都读取保存的状态信息的方式,在实际应用场景下,可以只在程序启动的时候保存之前保存的状态信息,然后保存起来,在后续过程中,将中间状态保存在内存中,并在必要的时候进行持久化保存。
这里将中间状态信息保存在了jar包所在目录下的一个文件中,这就需要运行程序的用户具有jar包所在目录的创建文件和写文件权限。
5. 启动jar包,执行测试
控制台可以看到输出信息类似如下:
id恢复成功到:37
下单成功
path1 = file:/D:/order/target/order.jar!/BOOT-INF/classes!/
path2 = file:/D:/order/target/order
path3 = D:/order/target
path4 = D:/order/target/snowflake.properties
id持久化成功到:38