مرحبًا ، ماذا عن هيكل تفاعلي ذاتي تلقائي ومساعدة والمزيد؟ وبدون مشاكل ، وحتى على JVM؟

أصبح ساعي البريد صداع في العمل بالنسبة لي. على الرغم من أننا كلنا TDDs في الكلمات ، ومن خلال الضوء الأحمر لـ Cucumber ، نرى ما تم كسره بالضبط ، ولكن في الواقع كان عليّ إرسال طلبات REST في واجهة Postman في كثير من الأحيان. في بداية العمل ، كان من الضروري الحصول على رمز مصادقة (طلب إنشاء وطلب للتحقق ، يختلف المستخدمون) ، ثم الانتقال إلى الإشارات المرجعية وتحرير المعلمات وبدء طلبات أخرى. انقر فوق انقر فوق انقر. بترتيب مختلف. لقد قمت بالفعل بكتابة نصوص برمجية باستخدام cURL ، وقمت بتقديم طلبات في IDEA - هذا ليس مناسبًا. محفز مثالي للتحول إلى الاختبارات التلقائية ، كانت هذه مجرد طلبات لفهم ما كان يحدث في لحظة فريدة في مزيج من حالة الخدمة ، وإصدارها ، وأطرها المركزية وراءها ، والطقس في المنزل ، وبالتأكيد لم تندرج تحت اختبار الانحدار. بدأ النقر فوق انقر فوق أكل الكثير من الوقت وزيادة المسافة المقطوعة من الماوس.
Spring Shell, shell , Spring. , . , — . — shell, . , — Spring State Machine. , — , — , , Kotlin, Akka "" . State Machine , .
Spring Initializr Gradle Kotlin. .
curl 'https://start.spring.io/starter.zip?type=gradle-project&language=kotlin&bootVersion=2.2.6.RELEASE&baseDir=shell-state&groupId=me.votez.spring&artifactId=shell-state&name=shell-state&description=Demo%20project%20for%20Spring%20State%20Machine%20and%20Shell&packageName=me.votez.spring.shellstate&packaging=jar&javaVersion=1.8' --compressed --output shellstate.zip && unzip shellstate.zip
Spring Shell gradle
implementation("org.springframework.shell:spring-shell-starter:2.0.0.RELEASE")
(shell). , ShellComponent ( ) , ShellMethod , . , ShellOption. , Bean Validation. , Enum ( , help).
— . — , , actuator .…
( runBlocking — )
package me.votez.spring.shellstate
import org.springframework.shell.standard.ShellComponent
import org.springframework.shell.standard.ShellMethod
import org.springframework.shell.standard.ShellOption
import kotlinx.coroutines.*
import org.springframework.shell.standard.ShellMethodAvailability
import java.util.*
import kotlin.random.Random
@ShellComponent
class ServerCommands {
private var token: String? = null
@ShellMethod("Authenticate and obtain token")
fun login(
@ShellOption name:String,
@ShellOption password:String,
@ShellOption(defaultValue = "admin") scope: String) = runBlocking {
token = UUID.randomUUID().toString()
delay(2_000)
"Connected"
}
}
@ShellMethod("List projects regstered on server")
fun list(
@ShellOption(defaultValue = "PROJECT", help = "Possible values are PROJECT and USER") type:EntityType) = when(type) {
EntityType.PROJECT -> listOf("Roga i Kopita", "Svetliy Put", "NIICHAVO")
EntityType.USER -> listOf( "Ivanov", "Petrov", "Sidorov")
}
}
enum class EntityType {
PROJECT,
USER
}
. IntelliJ IDEA, Spring Shell JLine, Linux, MacOS Windows, IDE — .
$ bash ./gradlew build
$ java -jar build/libs/shell-state-0.0.1-SNAPSHOT.jar
help, . clear, exit, quit, script, stacktrace.
2020-05-03 12:49:35.442 INFO 23211 --- [ main] m.v.s.s.ShellStateApplicationKt : Started ShellStateApplicationKt in 1.036 seconds (JVM running for 0.936)
shell:>help
AVAILABLE COMMANDS
Built-In Commands
clear: Clear the shell screen.
exit, quit: Exit the shell.
help: Display help about available commands.
script: Read and execute commands from a file.
stacktrace: Display the full stacktrace of the last error.
Server Commands
list: List projects registered on server
login: Authenticate and obtain token
shell:>help list
NAME
list - List projects registered on server
SYNOPSYS
list [[--type] entity-type]
OPTIONS
--type entity-type
Possible values are PROJECT and USER
[Optional, default = PROJECT]
. login list L, . l TAB , o TAB, login. . , > login root 123456 , — Connected. list .
list , list . :
@ShellMethodAvailability("list")
fun listAvailable() = if (token != null) Availability.available() else Availability.unavailable("cannot run without auth token")
shell, , . help , .
2020-05-02 13:30:12.593 INFO 4443 --- [ main] m.v.s.s.ShellStateApplicationKt : Started ShellStateApplicationKt in 1.525 seconds (JVM running for 1.252)
shell:>list
Command 'list' exists but is not currently available because cannot run without auth token
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
shell:>help
AVAILABLE COMMANDS
Built-In Commands
clear: Clear the shell screen.
exit, quit: Exit the shell.
help: Display help about available commands.
script: Read and execute commands from a file.
stacktrace: Display the full stacktrace of the last error.
Server Commands
* list: List projects regstered on server
login: Authenticate and obtain token
Commands marked with (*) are currently unavailable.
Type `help <command>` to learn more.
shell:>help list
NAME
list - List projects registered on server
SYNOPSYS
list [[--type] entity-type]
OPTIONS
--type entity-type
Possible values are PROJECT and USER
[Optional, default = PROJECT]
CURRENTLY UNAVAILABLE
This command is currently not available because cannot run without auth token.
, . , , , . command prompt, . , application.properties — , Spring Framework ( ). prompt , .
PrompProvider, , JLine.
@ConfigurationProperties(prefix="shell")
class ServerCommands : PromptProvider
lateinit var env: String
override fun getPrompt(): AttributedString =
AttributedString("${env}:>",
AttributedStyle.DEFAULT.foreground(
if (token == null) AttributedStyle.YELLOW else AttributedStyle.GREEN))
, . .
, , (soap, protobuf ) — , - . , .
Spring State Machine
, . . , , , . , … , .
Spring State Machine.
, (), -. — The Evolution of Trust. , () . xml — , - .
, . , "" . Spring State Machine , , .
, . , . — Spring SM , . " ", - , - , , — .
, , . - — , .
?
, .

, "" . . ( ) , Thread Pool, shell, SSM - — .
command prompt " ", .
, . Quick Start.
, — . — command prompt. , , — , token. null-safe lateinit.
.
override fun configure(transitions: StateMachineTransitionConfigurer<State, Event>) {
transitions
.withExternal()
.source(State.INIT).target(State.CONNECTING)
.event(Event.LOGIN)
.and()
.withExternal()
.source(State.CONNECTING).target(State.READY).event(Event.CONNECTED)
.action { context -> context.extendedState.variables["token"] = context.messageHeaders["token"] }.and()
.withExternal()
.source(State.CONNECTING).target(State.INIT).event(Event.FAILED).and()
.withInternal()
.source(State.READY).event(Event.COMMAND).and()
.withExternal()
.source(State.READY).target(State.CONNECTING).event(Event.LOGIN)
}
....
enum class State { INIT, CONNECTING, READY }
enum class Event { LOGIN, CONNECTED, FAILED, COMMAND }
— , — . Spring. , , . .
. login:
@Autowired
lateinit var stateMachine: StateMachine<State, Event>
lateinit var token: String
@ShellMethod("Authenticate and obtain token")
fun login(
@ShellOption name: String,
@ShellOption password: String,
@ShellOption(defaultValue = "admin") scope: String) =
runBlocking {
stateMachine.sendEvent(
MessageBuilder.createMessage(Event.LOGIN, MessageHeaders(mapOf("login" to name))))
delay(1_000)
token = UUID.randomUUID().toString()
stateMachine.sendEvent(
MessageBuilder.createMessage(Event.CONNECTED, MessageHeaders(mapOf("token" to token))))
"Connected"
}
...
command prompt:
private val colors = mapOf(State.READY to AttributedStyle.DEFAULT.foreground(AttributedStyle.GREEN))
.withDefault { AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW) }
override fun getPrompt(): AttributedString =
AttributedString("${env}:>", colors.getValue(stateMachine.state.id))
:
@ShellMethodAvailability("list")
fun listAvailable() =
if (stateMachine.state.id == State.READY) Availability.available()
else Availability.unavailable("requires authentication performed first")
Spring State Machine — (guards), , , , , .
Spring Shell هو حل ممتاز لأدوات مساعدة محددة لتطوير المشروع ، عندما تكون هناك حاجة لأتمتة جزئية للمهام غير التافهة.
Spring State Machine هو واحد آخر من العديد من المشاريع المجتمعية التي تستحق المزيد من الاهتمام وهي تقنية حديثة ، على الرغم من التحيز.
نموذج التعليمات البرمجية متاح على GitHub .
