feat: serial service
This commit is contained in:
@@ -29,3 +29,4 @@ include(
|
|||||||
"simple-jwt-spring-boot-starter",
|
"simple-jwt-spring-boot-starter",
|
||||||
"property-guard-spring-boot-starter"
|
"property-guard-spring-boot-starter"
|
||||||
)
|
)
|
||||||
|
include("simple-serial")
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Simple Serial
|
||||||
|
|
||||||
|
> Thanks to [@siujamo](https://github.com/siujamo)'s donation.
|
||||||
|
|
||||||
|
Simple Serial reuses the configuration of Redis connections to provide am easy-to-use serial
|
||||||
|
service.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Simple Serial reused the redis configuration of Spring Boot to provide redis support for the
|
||||||
|
service.
|
||||||
|
|
||||||
|
Besides, **Simple Serial** provides a configuration property `onixbyte.serial.start-serial` to
|
||||||
|
specify the start value of a serial, and default to `0`.
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
}
|
||||||
|
|
||||||
|
val artefactVersion: String by project
|
||||||
|
val projectUrl: String by project
|
||||||
|
val projectGithubUrl: String by project
|
||||||
|
val licenseName: String by project
|
||||||
|
val licenseUrl: String by project
|
||||||
|
|
||||||
|
val jacksonVersion: String by project
|
||||||
|
val springBootVersion: String by project
|
||||||
|
|
||||||
|
group = "com.onixbyte"
|
||||||
|
version = artefactVersion
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
|
||||||
|
implementation("org.springframework.boot:spring-boot-autoconfigure:$springBootVersion")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-logging:$springBootVersion")
|
||||||
|
implementation("org.springframework.boot:spring-boot-configuration-processor:$springBootVersion")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-data-redis:$springBootVersion")
|
||||||
|
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:$springBootVersion")
|
||||||
|
testImplementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion")
|
||||||
|
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("simpleSerialSpringBootStarter") {
|
||||||
|
groupId = group.toString()
|
||||||
|
artifactId = "simple-serial-spring-boot-starter"
|
||||||
|
version = artefactVersion
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name = "Simple Serial :: Spring Boot Starter"
|
||||||
|
description = "A Redis based easy-to-use serial service."
|
||||||
|
url = projectUrl
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name = licenseName
|
||||||
|
url = licenseUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scm {
|
||||||
|
connection = "scm:git:git://github.com:OnixByte/JDevKit.git"
|
||||||
|
developerConnection = "scm:git:git://github.com:OnixByte/JDevKit.git"
|
||||||
|
url = projectGithubUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id = "zihluwang"
|
||||||
|
name = "Zihlu Wang"
|
||||||
|
email = "really@zihlu.wang"
|
||||||
|
timezone = "Asia/Hong_Kong"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from(components["java"])
|
||||||
|
|
||||||
|
signing {
|
||||||
|
sign(publishing.publications["simpleSerialSpringBootStarter"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "sonatypeNexus"
|
||||||
|
url = URI(providers.gradleProperty("repo.maven-central.host").get())
|
||||||
|
credentials {
|
||||||
|
username = providers.gradleProperty("repo.maven-central.username").get()
|
||||||
|
password = providers.gradleProperty("repo.maven-central.password").get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024-2025 OnixByte.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.onixbyte.serial;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis Configuration provides redis templates for operations to serial.
|
||||||
|
*
|
||||||
|
* @author siujamo
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
public class RedisConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RedisTemplate for serial service.
|
||||||
|
*
|
||||||
|
* @param redisConnectionFactory redis connection factory
|
||||||
|
* @return a configured redis template for serial service
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<String, Long> serialRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||||
|
var redisTemplate = new RedisTemplate<String, Long>();
|
||||||
|
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||||
|
redisTemplate.setKeySerializer(RedisSerializer.string());
|
||||||
|
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Long.class));
|
||||||
|
redisTemplate.afterPropertiesSet();
|
||||||
|
return redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024-2025 OnixByte.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.onixbyte.serial;
|
||||||
|
|
||||||
|
import com.onixbyte.serial.properties.SerialProperties;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code SerialService} provides simple serial operations.
|
||||||
|
*
|
||||||
|
* @author siujamo
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@EnableConfigurationProperties(SerialProperties.class)
|
||||||
|
public class SerialService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SerialService.class);
|
||||||
|
|
||||||
|
private final String appName;
|
||||||
|
private final RedisTemplate<String, Long> serialRedisTemplate;
|
||||||
|
private final SerialProperties serialProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*
|
||||||
|
* @param appName the name of this application
|
||||||
|
* @param serialRedisTemplate serial redis template
|
||||||
|
* @param serialProperties serial properties
|
||||||
|
*/
|
||||||
|
public SerialService(@Value("${spring.application.name}") String appName,
|
||||||
|
RedisTemplate<String, Long> serialRedisTemplate,
|
||||||
|
SerialProperties serialProperties) {
|
||||||
|
this.appName = appName;
|
||||||
|
this.serialRedisTemplate = serialRedisTemplate;
|
||||||
|
this.serialProperties = serialProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a serial key.
|
||||||
|
*
|
||||||
|
* @param tag tag of the serial
|
||||||
|
* @return key of a serial
|
||||||
|
*/
|
||||||
|
public String buildKey(String tag) {
|
||||||
|
return appName + ":serial:" + tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next available serial for specific tag.
|
||||||
|
*
|
||||||
|
* @param tag tag of the serial
|
||||||
|
* @return next available serial
|
||||||
|
*/
|
||||||
|
public Long nextSerial(String tag) {
|
||||||
|
var key = buildKey(tag);
|
||||||
|
var next = Optional.ofNullable(serialRedisTemplate.opsForValue().get(key))
|
||||||
|
.orElse(serialProperties.getStartSerial());
|
||||||
|
serialRedisTemplate.opsForValue().set(key, next + 1);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset all serial values.
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
var keys = serialRedisTemplate.keys(buildKey("*"));
|
||||||
|
var startSerial = serialProperties.getStartSerial();
|
||||||
|
|
||||||
|
if (!keys.isEmpty()) {
|
||||||
|
for (var key : keys) {
|
||||||
|
serialRedisTemplate.opsForValue().set(key, startSerial);
|
||||||
|
log.debug("Serial {} has been reset to {}", key, startSerial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024-2025 OnixByte.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.onixbyte.serial.properties;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SerialProperties can modify the start value of a serial.
|
||||||
|
*
|
||||||
|
* @author siujamo
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties(prefix = "onixbyte.serial")
|
||||||
|
public class SerialProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start of the serial, default to 0.
|
||||||
|
*/
|
||||||
|
private Long startSerial = 0L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the start of the serial.
|
||||||
|
*
|
||||||
|
* @return start of the serial
|
||||||
|
*/
|
||||||
|
public Long getStartSerial() {
|
||||||
|
return startSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the start of the serial.
|
||||||
|
*
|
||||||
|
* @param startSerial start of the serial
|
||||||
|
*/
|
||||||
|
public void setStartSerial(Long startSerial) {
|
||||||
|
this.startSerial = startSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
public SerialProperties() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2024-2025 OnixByte.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
#
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
com.onixbyte.serial.RedisConfig
|
||||||
|
com.onixbyte.serial.SerialService
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2024-2025 OnixByte.
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
<property name="COLOURFUL_OUTPUT" value="%black(%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK}) %highlight(%-5level) %black(---) %black([%10.10t]) %cyan(%-20.20logger{20}) %black(:) %msg%n"/>
|
||||||
|
<property name="STANDARD_OUTPUT" value="%date{'dd MMM, yyyy HH:mm:ss', Asia/Hong_Kong, en-UK} %-5level %black(---) [%10.10t] %-20.20logger{20} : %msg%n"/>
|
||||||
|
|
||||||
|
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>${COLOURFUL_OUTPUT}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
Reference in New Issue
Block a user