
рдЖрдзреБрдирд┐рдХ рджреБрдирд┐рдпрд╛ рдореЗрдВ рдХрдИ рд╕реЗрд╡рд╛рдПрдВ, рдЕрдзрд┐рдХрд╛рдВрд╢ рднрд╛рдЧ рдХреЗ рд▓рд┐рдП, "рдХреБрдЫ рднреА рдирд╣реАрдВ"ред рдЙрдирдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЕрдиреНрдп рдбреЗрдЯрд╛рдмреЗрд╕ / рд╕реЗрд╡рд╛рдУрдВ / рдХреИрд╢ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдирд┐рдпрдореЛрдВ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЗрд╕ рд╕рднреА рдбреЗрдЯрд╛ рдХреЗ рдПрдХрддреНрд░реАрдХрд░рдг рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдХрдо рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдпрд╣ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЧреЛрд▓рдВрдЧ рдЬреИрд╕реА рднрд╛рд╖рд╛рдПрдВ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рдкреНрд░рдгрд╛рд▓реА рдХреЗ рд╕рд╛рде рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИрдВ, рдЬреЛ рдЧреИрд░-рдЕрд╡рд░реЛрдзрдХ рдХреЛрдб рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИред
рдЬреЗрд╡реАрдПрдо рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ, рдЪреАрдЬреЗрдВ рдереЛрдбрд╝реА рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИрдВред рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рдереНрд░реЗрдбреНрд╕ рдХреЛ рдмреНрд▓реЙрдХ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдЪреМрдЦрдЯреЗ рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИрдВред рддреЛ stdlib рдЦреБрдж рднреА рдХрдИ рдмрд╛рд░ рдпрд╣реА рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдФрд░ рдЬрд╛рд╡рд╛ рдореЗрдВ рдЧреЛрд▓рдВрдЧ рдореЗрдВ рдЧреЛрд░реЛрдЗрдЯрд┐рди рдХреЗ рд╕рдорд╛рди рдХреЛрдИ рддрдВрддреНрд░ рдирд╣реАрдВ рд╣реИред
рдлрд┐рд░ рднреА, рдЬреЗрд╡реАрдПрдо рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ рдФрд░ рдирдП рджрд┐рд▓рдЪрд╕реНрдк рдЕрд╡рд╕рд░ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВред рдХреЛрдЯрд▓рд┐рди рдХреЗ рд╕рд╛рде рдХреЛрдЯрд▓рд┐рди рд╣реИ, рдЬреЛ рдЙрдирдХреЗ рдЙрдкрдпреЛрдЧ рдореЗрдВ рдЧреЛрд░рдВрдЧ рдЧреЛрд░реЛрдЗрдЯрд┐рди рдХреЗ рд╕рдорд╛рди рд╣реИрдВ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╡реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ)ред рдЬреЗрдИрдкреА рд▓реВрдо рд╣реИ, рдЬреЛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЬреЗрд╡реАрдПрдо рдореЗрдВ рдлрд╛рдЗрдмрд░ рд▓рд╛рдПрдЧрд╛ред рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рд╡реЗрдм рдлреНрд░реЗрдорд╡рд░реНрдХ рдореЗрдВ рд╕реЗ рдПрдХ - рд╕реНрдкреНрд░рд┐рдВрдЧ - рдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рдкрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз рд╕реЗрд╡рд╛рдПрдВ рдмрдирд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рдЬреЛрдбрд╝рд╛ред рдФрд░ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ 2.2 рдХреА рд╣рд╛рд▓рд┐рдпрд╛ рд░рд┐рд▓реАрдЬ рдХреЗ рд╕рд╛рде, рдХреЛрдЯрд▓рд┐рди рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдФрд░ рднреА рдмреЗрд╣рддрд░ рд╣реИред
рдореИрдВ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд░рддрд╛ рд╣реВрдВ, рдПрдХ рдХрд╛рд░реНрдб рд╕реЗ рджреВрд╕рд░реЗ рдХрд╛рд░реНрдб рдореЗрдВ рдкреИрд╕реЗ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯреА рд╕реА рд╕реЗрд╡рд╛ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдХрдИ рдмрд╛рд╣рд░реА рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ 2.2 рдФрд░ рдХреЛрдЯрд▓рд┐рди рдкрд░ рдПрдХ рдЖрд╡реЗрджрди рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдПред
рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ рдпрджрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рд╡рд╛, рдХреЛрдЯрд▓рд┐рди, рдЧреНрд░реИрдбрд▓, рд╕реНрдкреНрд░рд┐рдВрдЧ, рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ 2, рд░рд┐рдПрдХреНрдЯрд░, рд╡реЗрдм рдлреНрд▓рдХреНрд╕, рдЯреЙрдордХреИрдЯ, рдиреЗрдЯреНрдЯреА, рдХреЛрдЯрд▓рд┐рди oroutines, рдЧреНрд░реИрдбрд▓ рдХреЛрдЯрд▓рд┐рди рдбреАрдПрд╕рдПрд▓ рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдкреАрдПрдЪрдбреА рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВред рд▓реЗрдХрд┐рди рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдпрд╣ рдмрд╛рдд рдирд╣реАрдВ рд╣реИред рдХреЛрдб рдХреЛ рдЕрдзрд┐рдХрддрдо рд░реВрдк рд╕реЗ рд╕рд░рд▓ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рдЖрдк JVM рджреБрдирд┐рдпрд╛ рд╕реЗ рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рд╕рдм рдХреБрдЫ рдЖрдкрдХреЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
рдпрджрд┐ рдЖрдк рд╕реНрд╡рдпрдВ рдПрдХ рд╕реЗрд╡рд╛ рд▓рд┐рдЦрдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХреА рдЬрд╝рд░реВрд░рдд рдХреА рд╣рд░ рдЪреАрдЬрд╝ рд╕реНрдерд╛рдкрд┐рдд рд╣реИ:
- рдЬрд╛рд╡рд╛ 8+
- рдбреЙрдХрд░ рдФрд░ рдбреЙрдХрд░ рдХрдореНрдкреЛрдЬрд╝;
- cURL рдФрд░ рдЕрдзрд┐рдорд╛рдирддрдГ jq ;
- git;
- рдЕрдзрд┐рдорд╛рдирддрдГ рдХреЛрдЯрд▓рд┐рди рдХреЗ рд▓рд┐рдП рдПрдХ IDE (Intellij Idea, Eclipse, VS,
vim , рдЖрджрд┐)ред рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдиреЛрдЯрдмреБрдХ рдореЗрдВ рд╕рдВрднрд╡ рд╣реИред
рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд╕реЗрд╡рд╛ рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рджреЛрдиреЛрдВ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рд╣реЛрдВрдЧреЗ, рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЗрдВрд╕реНрдЯреЙрд▓реЗрд╢рди рдФрд░ рдЕрд╕реЗрдВрдмрд▓реА рдЪрд▓рд╛рдПрдВ рдФрд░ рд╕реЗрд╡рд╛рдУрдВ рдФрд░ рдЙрдирдХреЗ рдПрдкреАрдЖрдИ рдкрд░ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред
рд╕реЗрд╡рд╛рдУрдВ рдФрд░ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдХреЗрд╡рд▓ рдЪрд┐рддреНрд░рдг рдкреНрд░рдпреЛрдЬрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ; рдЕрдкрдиреЗ рдареЗрд╕ рдХреЗ рд▓рд┐рдП рд╕рднреА AS IS
рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рди рдХрд░реЗрдВ!
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЛ рд╕реНрд╡рдпрдВ рдХреЗ рд▓рд┐рдП рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХреНрд▓реЛрди рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕ рдПрдХреАрдХрд░рдг рдХреЗ рд╕рд╛рде рд╣рдо рдЗрд╕реЗ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЬрд╛рдПрдВрдЧреЗ:
git clone https://github.com/evgzakharov/spring-demo-services && cd spring-demo-services
рдПрдХ рдЕрд▓рдЧ рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ, рд╣рдо gradle
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рднреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХрддреНрд░ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рдПрдХ рд╕рдлрд▓ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд╛рдж рд╕рднреА рд╕реЗрд╡рд╛рдУрдВ рдХреЛ docker-compose
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
./gradlew build && docker-compose up
рдЬрдмрдХрд┐ рд╕рдм рдХреБрдЫ рдбрд╛рдЙрдирд▓реЛрдб рдФрд░ рдЗрдВрд╕реНрдЯреЙрд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред

рдЯреЛрдХрди рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдиреБрд░реЛрдз, рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдб рдирдВрдмрд░ рдФрд░ рдХрд╛рд░реНрдб рдХреЗ рдмреАрдЪ рд╣рд╕реНрддрд╛рдВрддрд░рд┐рдд рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рд░рд╛рд╢рд┐ рд╕реЗрд╡рд╛ рдХреЗ рдкреНрд░рд╡реЗрд╢ рджреНрд╡рд╛рд░ рдкрд░ рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛рдПрдЧреА (рдбреЗрдореЛ рд╕реЗрд╡рд╛):
{ "authToken": "auth-token1", "cardFrom": "55593478", "cardTo": "55592020", "amount": "10.1" }
authToken
рдЯреЛрдХрди рдХреЗ рдЕрдиреБрд╕рд╛рд░, authToken
AUTH
рд╕реЗрд╡рд╛ рдореЗрдВ рдЬрд╛рдиреЗ рдФрд░ userId
рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдЖрдк рддрдм USER
рдЕрдиреБрд░реЛрдз рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд░ рд╕рднреА рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред AUTH
рдЙрди рддреАрди рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреА рдЬрд╛рдирдХрд╛рд░реА рджреЗрдЧрд╛ рдЬреЛ рд╣рдо рдПрдХреНрд╕реЗрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред AUTH
рд╕реЗ рдирдореВрдирд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛:
{ "userId": 158, "cardAccess": true, "paymentAccess": true, "userAccess": true }
рдХрд╛рд░реНрдбреЛрдВ рдХреЗ рдмреАрдЪ рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкрд╣рд▓реЗ рдХрд╛рд░реНрдб рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдб рдирдВрдмрд░ рдХреЗ рд╕рд╛рде рдЬрд╛рдПрдВред рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ, рд╣рдо cardId
рдкреНрд░рд╛рдкреНрдд cardId
, рдлрд┐рд░ рдЙрдирдХреЗ рд╕рд╛рде рд╣рдо PAYMENT
рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬреЗрдВрдЧреЗ рдФрд░ рдПрдХ рд╣рд╕реНрддрд╛рдВрддрд░рдг рдХрд░реЗрдВрдЧреЗред рдФрд░ рдЕрдВрддрд┐рдо - рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╕реЗ рд╣рдо рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХреЗ рд╕рд╛рде fromCardId
рдФрд░ рд╡рд░реНрддрдорд╛рди рд╢реЗрд╖ рд░рд╛рд╢рд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдПрдВред
рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рдПрдХ рдЫреЛрдЯреА рд╕реА рджреЗрд░реА рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЯрд╛рдЗрдордЯрд╛рдЗрдо рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рдХрд╛ рдореВрд▓реНрдп рд╕рднреА рдХрдВрдЯреЗрдирд░реЛрдВ рдореЗрдВ рдлреЗрдВрдХрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрд░реА рдорд┐рд▓реАрд╕реЗрдХрдВрдб рдореЗрдВ рд╕реЗрдЯ рдХреА рдЬрд╛рддреА рд╣реИред рдФрд░ AUTH
рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рд╡рд┐рд╡рд┐рдзрддрд╛ рд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, SUCCESS_RATE
рдХреЗ рдореВрд▓реНрдп рдореЗрдВ SUCCESS_RATE
рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рдЬреЛ рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ true
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдбреЙрдХрдЯрд░-рдХрдВрдкреЛрдЬ.рдорд╛рдЗрд▓ рдлрд╝рд╛рдЗрд▓:
version: '3' services: service-auth: build: service-auth image: service-auth:1.0.0 environment: - SUCCESS_RATE=1.0 - TIMEOUT=100 ports: - "8081:8080" service-card: build: service-card image: service-card:1.0.0 environment: - TIMEOUT=100 ports: - "8082:8080" service-payment: build: service-payment image: service-payment:1.0.0 environment: - TIMEOUT=100 ports: - "8083:8080" service-user: build: service-user image: service-user:1.0.0 environment: - TIMEOUT=100 ports: - "8084:8080"
рд╕рднреА рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд▓рд┐рдП, 8081 рд╕реЗ 8084 рддрдХ рдкреЛрд░реНрдЯ рдЕрдЧреНрд░реЗрд╖рдг рдЖрд╕рд╛рдиреА рд╕реЗ рд╕реАрдзреЗ рдЙрди рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
Demo service
рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдкрд╣рд▓реЗ, рдЖрдЗрдП, рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдФрд░ рд╕рдВрдЧрд╛рдорд┐рддрд┐ рдХреЗ рдмрд┐рдирд╛ рдЬрд┐рддрдирд╛ рд╕рдВрднрд╡ рд╣реЛ рд╕рдХреЗ рдЕрдирд╛рдбрд╝реА рд▓рд┐рдЦрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ 2.2.1, рдХреЛрдЯрд▓рд┐рди рдФрд░ рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рд▓реЗрдВред рд╣рдо рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХрд╛ рдХреНрд▓реЛрди рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ spring-mvc-start
рд╢рд╛рдЦрд╛ рдореЗрдВ рдЬрд╛рддреЗ рд╣реИрдВ:
git clone https://github.com/evgzakharov/demo-service && cd demo-service && git checkout spring-mvc-start
demo.Controller
рдлрд╛рдЗрд▓ рдкрд░ рдЬрд╛рдПрдВред рдЗрд╕рдХреЗ рдкрд╛рд╕ рдПрдХрдорд╛рддреНрд░ рдЦрд╛рд▓реА processRequest
рд╣реИ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рдзрд┐ рд▓рд┐рдЦреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдПред
@PostMapping fun processRequest(@RequestBody serviceRequest: ServiceRequest): Response { .. }
рд╡рд┐рдзрд┐ рдХреЗ рдкреНрд░рд╡реЗрд╢ рджреНрд╡рд╛рд░ рдкрд░ рдХрд╛рд░реНрдбреЛрдВ рдХреЗ рдмреАрдЪ рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдХрд╛ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛ред
data class ServiceRequest( val authToken: String, val cardFrom: String, val cardTo: String, val amount: BigDecimal )
рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рд╡рд╕рдВрдд рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВрд╕реНрдкреНрд░рд┐рдВрдЧ рдореЗрдВ рдПрдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд DI рд╣реИ рдЬреЛ рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред DemoController рдХреЛ рд╡рд┐рд╢реЗрд╖ RestController
рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: DI рдореЗрдВ рдмреАрди рдХреЛ рдкрдВрдЬреАрдХреГрдд рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдкрдиреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рднреА рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдкреЛрд╕реНрдЯрдкреНрд░реЛрд╕реЗрд╕рд░ PostMapping
рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рд╕рднреА рддрд░реАрдХреЛрдВ рдХреЛ PostMapping
рдФрд░ рдЙрдиреНрд╣реЗрдВ POST
рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИред
рд╣реИрдВрдбрд▓рд░ рднреА DemoController рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░реЙрдХреНрд╕реА рдХреНрд▓рд╛рд╕ рдмрдирд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рддрд░реНрдХ processRequest
рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рдкрд╛рд╕ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рддрд░реНрдХ рд╣реИ, рдЬреЛ @RequestBody
рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рд╣реИред рдЗрд╕рд▓рд┐рдП, рдкреНрд░реЙрдХреНрд╕реА рдореЗрдВ, рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ JSON рдХрдВрдЯреЗрдВрдЯ рдХреЗ рд╕рд╛рде ServiceRequest
рд╡рд░реНрдЧ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред
рдЗрд╕реЗ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рдХреЗ рд╕рднреА рддрд░реАрдХреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрдирд╛рдП рдЧрдП рд╣реИрдВ, рдЖрдкрдХреЛ рдмрд╕ рдЙрдиреНрд╣реЗрдВ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХреЗрд╡рд▓ рдкрд╛рдБрдЪ рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВ, рдкреНрд░рддреНрдпреЗрдХ рдХреНрд░рд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХред рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХреЙрд▓ рд╕реНрд╡рдпрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ RestTemplate
рдмреНрд▓реЙрдХрд┐рдВрдЧ рдХреЙрд▓ рдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИрдВред
AUTH
рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐:
private fun getAuthInfo(token: String): AuthInfo { log.info("getAuthInfo") return restTemplate.getForEntity("${demoConfig.auth}/{token}", AuthInfo::class.java, token) .body ?: throw RuntimeException("couldn't find user by token='$token'") }
рдЪрд▓реЛ рд╡рд┐рдзрд┐ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдЯрд┐рдкреНрдкрдгреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рджрд░реНрд╢рд╛рддреА рд╣реИ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рдХреНрдпрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИ:
@PostMapping fun processRequest(@RequestBody serviceRequest: ServiceRequest): Response {
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рд╡рд┐рдзрд┐ рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдмрд┐рдирд╛ рдЗрд╕ рдмрд╛рдд рдХрд╛ рдзреНрдпрд╛рди AUTH
рдХрд┐ AUTH
рд╣рдореЗрдВ рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рддрдХ рдкрд╣реБрдБрдЪ рд╕реЗ рд╡рдВрдЪрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдЬрдм рдпрд╣ рдирд┐рдХрд▓рддрд╛ рд╣реИ (рдпрд╛ spring-mvc
рд╢рд╛рдЦрд╛ рдореЗрдВ рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж), рддреЛ рдЖрдк рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╕реЗрд╡рд╛ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
рд╡рд╕рдВрдд- mvc рд╢рд╛рдЦрд╛ рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди fun processRequest(@RequestBody serviceRequest: ServiceRequest): Response { val authInfo = getAuthInfo(serviceRequest.authToken) val userInfo = findUser(authInfo.userId) val cardFromInfo = findCardInfo(serviceRequest.cardFrom) val cardToInfo = findCardInfo(serviceRequest.cardTo) sendMoney(cardFromInfo.cardId, cardToInfo.cardId, serviceRequest.amount) val paymentInfo = getPaymentInfo(cardFromInfo.cardId) return SuccessResponse( amount = paymentInfo.currentAmount, userName = userInfo.name, userSurname = userInfo.surname, userAge = userInfo.age ) }
рд╕реЗрд╡рд╛ рд╢реБрд░реВ рдХрд░реЗрдВ (рдбреЗрдореЛ-рд╕рд░реНрд╡рд┐рд╕ рдлрд╝реЛрд▓реНрдбрд░ рд╕реЗ):
./gradlew bootRun
рд╣рдо рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬрддреЗ рд╣реИрдВ:
./demo-request.sh
рдЬрд╡рд╛рдм рдореЗрдВ, рд╣рдореЗрдВ рдРрд╕рд╛ рдХреБрдЫ рдорд┐рд▓рддрд╛ рд╣реИ:
тЮЬ demo-service git:(spring-mvc) тЬЧ ./demo-request.sh + curl -XPOST http://localhost:8080/ -d @demo-payment-request.json -H 'Content-Type: application/json; charset=UTF-8' + jq . % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 182 0 85 100 97 20 23 0:00:04 0:00:04 --:--:-- 23 { "amount": 989.9, "userName": "Vasia", "userSurname": "Pupkin", "userAge": 18, "status": true }
рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рдЖрдкрдХреЛ рд╕реЗрд╡рд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 6 рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдФрд░ рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ 100 рдПрдордПрд╕ рдХреА рджреЗрд░реА рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ, рдХреБрд▓ рд╕рдордп 600 рдПрдордПрд╕ рд╕реЗ рдХрдо рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ 700 рдПрдордПрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ, рд╕рднреА рдУрд╡рд░рд╣реЗрдб рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдПред рдЕрдм рддрдХ рдХреЛрдб рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ, рдФрд░ рдЕрдЧрд░ рд╣рдо рдЕрдм рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ AUTH
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЬрд╛рдВрдЪ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдРрд╕рд╛ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реЛрдЧрд╛ (рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рд░рд┐рдлреИрдХреНрдЯрд░рд┐рдВрдЧ рдХреА рддрд░рд╣)ред
рд▓реЗрдХрд┐рди рдЖрдЗрдП рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рдЖрдк рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рдХреИрд╕реЗ рдЧрддрд┐ рджреЗ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк AUTH
рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рддреНрдпрд╛рдкрди рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рдирд╣реАрдВ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 2 рд╕реНрд╡рддрдВрддреНрд░ рдХрд╛рд░реНрдп рд╣реИрдВ:
- рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░
USER
рд╕реЗ рдбреЗрдЯрд╛ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рдирд╛; - рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдб рдХреЗ рд▓рд┐рдП
cardId
рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛, рднреБрдЧрддрд╛рди рдХрд░рдирд╛ рдФрд░ рдХреБрд▓ рд░рд╛рд╢рд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ред
рдпреЗ рдХрд╛рд░реНрдп рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдлрд┐рд░ рдХреБрд▓ рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛ рд╕рдордп рдХреЙрд▓ рдХреА рд╕рдмрд╕реЗ рд▓рдВрдмреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░реЗрдЧрд╛ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рджреВрд╕рд░рд╛) рдФрд░ 300 рдПрдордПрд╕ + рдПрдХреНрд╕ рдПрдордПрд╕ рдУрд╡рд░рд╣реЗрдб рдХреЗ рд▓рд┐рдП рдХреБрд▓ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдХреЙрд▓ рд╕реНрд╡рдпрдВ рдЕрд╡рд░реБрджреНрдз рд╣реЛ рд░рд╣реА рд╣реИрдВ, рд╕рдорд╛рдирд╛рдВрддрд░ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рдЙрдиреНрд╣реЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдереНрд░реЗрдб рдкрд░ рдЪрд▓рд╛рдирд╛ рд╣реИред рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рдХреЙрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдереНрд░реЗрдб рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдмрд╣реБрдд рдорд╣рдВрдЧрд╛ рд╣реЛрдЧрд╛ред рдПрдХ рдЕрдиреНрдп рддрд░реАрдХрд╛ рд╣реИ рдереНрд░реЗрдбрдкреВрд▓ рдкрд░ рдХрд╛рд░реНрдп рдЪрд▓рд╛рдирд╛ред рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рдРрд╕рд╛ рд╕рдорд╛рдзрд╛рди рдЙрдЪрд┐рдд рд▓рдЧрддрд╛ рд╣реИ, рдФрд░ рд╕рдордп рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрдо рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдХрдВрдкреНрд▓реАрдЯрдЯреЗрдмрд▓ рд╕рд┐рд╡рдиреА рдкрд░ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдЖрдкрдХреЛ async
рдкреЛрд╕реНрдЯрдлрд┐рдХреНрд╕ рдХреЗ рд╕рд╛рде рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдкреГрд╖реНрдарднреВрдорд┐ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдФрд░ рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ ForkJoinPool.commonPool()
рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдХреЙрд▓рд┐рдВрдЧ рдХреЗ рддрд░реАрдХреЗ, рдХрд╛рд░реНрдпреЛрдВ рдХреЛ ForkJoinPool.commonPool()
рдкрд░ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ рдпрд╛ spring-mvc-async
рд╢рд╛рдЦрд╛ рдкрд░ рдЬрд╛рдПрдВред
рд╡рд╕рдВрдд- mvc-async рд╢рд╛рдЦрд╛ рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди fun processRequest(@RequestBody serviceRequest: ServiceRequest): Response { val authInfoFuture = CompletableFuture.supplyAsync { getAuthInfo(serviceRequest.authToken) } val userInfoFuture = authInfoFuture.thenApplyAsync { findUser(it.userId) } val cardFromInfo = CompletableFuture.supplyAsync { findCardInfo(serviceRequest.cardFrom) } val cardToInfo = CompletableFuture.supplyAsync { findCardInfo(serviceRequest.cardTo) } val waitAll = CompletableFuture.allOf(cardFromInfo, cardToInfo) val paymentInfoFuture = waitAll .thenApplyAsync { sendMoney(cardFromInfo.get().cardId, cardToInfo.get().cardId, serviceRequest.amount) } .thenApplyAsync { getPaymentInfo(cardFromInfo.get().cardId) } val paymentInfo = paymentInfoFuture.get() val userInfo = userInfoFuture.get() log.info("result") return SuccessResponse( amount = paymentInfo.currentAmount, userName = userInfo.name, userSurname = userInfo.surname, userAge = userInfo.age ) }
рдпрджрд┐ рд╣рдо рдЕрдм рдЕрдиреБрд░реЛрдз рд╕рдордп рдХреЛ рдорд╛рдкрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ 360 ms рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╣реЛрдЧрд╛ред рдореВрд▓ рд╕рдВрд╕реНрдХрд░рдг рдХреА рддреБрд▓рдирд╛ рдореЗрдВ, рдХреБрд▓ рд╕рдордп рд▓рдЧрднрдЧ 2 рдЧреБрдирд╛ рдХрдо рд╣реЛ рдЧрдпрд╛ред рдХреЛрдб рд╕реНрд╡рдпрдВ рдереЛрдбрд╝рд╛ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдЗрд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред рдФрд░ рдЕрдЧрд░ рдпрд╣рд╛рдВ рд╣рдо AUTH
рд╕реЗ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЪреЗрдХ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред
рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕реНрд╡рдпрдВ рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдПрдХ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рд╣реИ? 1000 рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрд╣реЗрдВ? рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде, рдпрд╣ рдмрд╣реБрдд рдЬрд▓реНрджреА рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рднреА рдереНрд░реЗрдбрдкреВрд▓ рдзрд╛рдЧреЗ рдЕрд╡рд░реБрджреНрдз рдХреЙрд▓ рдХрд░рдиреЗ рдореЗрдВ рд╡реНрдпрд╕реНрдд рд╣реИрдВред рдФрд░ рд╣рдо рдЗрд╕ рдирд┐рд╖реНрдХрд░реНрд╖ рдкрд░ рдЖрддреЗ рд╣реИрдВ рдХрд┐ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг рднреА рд╕реВрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдХреЗрд╡рд▓ рд╕реЗрд╡рд╛ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реА рд░рд╣рддрд╛ рд╣реИред рдЖрдк рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рддрдм рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХрдВрдкреНрд▓реАрдЯрдЯреЗрдмрд▓ рд╕рд┐рд╡рдиреА, рдлреНрд▓рдХреНрд╕, рдСрдмреНрдЬрд░реНрд╡реЗрдмрд▓, рдбрд┐рдлрд░реНрдб, рдкреНрд░реЛрдорд┐рд╕ рдпрд╛ рдЗрд╕реА рддрд░рд╣ рдХреА рд╡рд╕реНрддреБ рдкрд░ рд╡рд╛рдкрд╕ рдЖрдПрдВрдЧреЗ, рдЬрд┐рд╕ рдкрд░ рдЙрдореНрдореАрджреЛрдВ рдХреА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рд╣реИред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде, рд╣рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдзрд╛рд░рд╛рдУрдВ рдкрд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ - рдпрд╣ рдПрдХ (рдпрд╛ рдХрдо рд╕реЗ рдХрдо рдзрд╛рд░рд╛рдУрдВ рдХреЗ рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдЕрд▓рдЧ рдкреВрд▓) рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛ рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдзрд╛рд░ рд▓рд┐рдпрд╛ рд╣реИред
рдХреНрдпрд╛ рдЕрдм рд╣рдо рд╕реЗрд╡рд╛ рдкрд░ рднрд╛рд░реА рдмреЛрдЭ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдЗрд╕ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, Tomcat рдкрд░ рдПрдХ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ, рдЬреЛ рдХрд┐ рд╕реНрдЯрд╛рд░реНрдЯрд░ org.springframework.boot:spring-boot-starter-web
рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ 2.2.1 рдореЗрдВ рдкреНрд░рдпреБрдХреНрдд рд╣реЛрддрд╛ рд╣реИ org.springframework.boot:spring-boot-starter-web
ред рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рддрд╛рдХрд┐ рдереНрд░реЗрдбрдкреВрд▓ рд╕реЗ рдПрдХ рдзрд╛рдЧрд╛ рдЗрд╕рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЖрдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред рдФрд░ рдореБрдХреНрдд рдкреНрд░рд╡рд╛рд╣ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдирдП рдЕрдиреБрд░реЛрдз рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреА "рдХрддрд╛рд░" рдмрди рдЬрд╛рдПрдВрдЧреЗред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реА рд╕реЗрд╡рд╛ рд╣реА рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рднреЗрдЬрддреА рд╣реИред рдЗрд╕рдХреЗ рддрд╣рдд рдПрдХ рдкреВрд░реА рдзрд╛рд░рд╛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдирд╛ рдФрд░ рдЗрд╕реЗ рддрдм рддрдХ рд░реЛрдХрдирд╛, рдЬрдм рддрдХ рдХрд┐ рд╕рднреА рдХреЗ рдЬрд╡рд╛рдм рдирд╣реАрдВ рдЖрддреЗ, рджрд┐рдЦрддрд╛ рд╣реИ, рдЗрд╕реЗ рд╣рд▓реНрдХреЗ рдврдВрдЧ рд╕реЗ, рд╢рд╛рдирджрд╛рд░ рд░реВрдк рд╕реЗ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рд╕реНрдкреНрд░рд┐рдВрдЧ рдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ Netty рдпрд╛ Undertow рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз рд╡реЗрдм рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛ рджрд┐рдпрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХреЗрд╡рд▓ spring-boot-starter-web
рдХреЛ spring-boot-starter-webflux
рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ рдХреЛ рдереЛрдбрд╝рд╛ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдореЗрдВ рдЕрдиреБрд░реЛрдз рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЛрдиреЛ рдореЗрдВ "рд▓рд┐рдкрдЯреЗ" рд╣реЛрдВрдЧреЗред рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП рдЕрдм рд╡рд┐рдзрд┐ рдореЗрдВ рдЖрдкрдХреЛ рдореЛрдиреЛ рдкрд░рд┐рд╡рд░реНрддрди рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рд╡рд┐рдзрд┐ рдХрд╛ рдЕрдкрдирд╛ рдЧреИрд░-рдЕрд╡рд░реЛрдзрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рд┐рдЦрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, spring-webflux-start
рд╢рд╛рдЦрд╛ рдкрд░ рдЬрд╛рдПрдВред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕реНрдкреНрд░рд┐рдВрдЧ рдмреВрдЯ рдХреЗ рд▓рд┐рдП рд╕реНрдЯрд╛рд░реНрдЯрд░ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдЕрдм рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рдХреЗ рд╕рд╛рде рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЧреИрд░-рдЕрд╡рд░реБрджреНрдз рд╡реЗрдмрдХреНрд▓рд╛рдЗрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗ рдЧрдП рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рднреА рдмрджрд▓ рдЧрдпрд╛ рд╣реИред
AUTH рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрджрд╛рд╣рд░рдг рд╡рд┐рдзрд┐:
private fun getAuthInfo(token: String): Mono<AuthInfo> { log.info("getAuthInfo") return WebClient.create().get() .uri("${demoConfig.auth}/$token") .retrieve() .bodyToMono(AuthInfo::class.java) }
рдкрд╣рд▓реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдореЗрдВ processRequest
рд╡рд┐рдзрд┐ рдХреА рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдбрд╛рд▓рд╛ рдЧрдпрд╛ рд╣реИред рд░рд┐рдПрдХреНрдЯрд░ рдкрд░ рд╕реНрд╡рдпрдВ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдкрд┐рдЫрд▓реА рдмрд╛рд░ рдХреА рддрд░рд╣, рдкрд╣рд▓реЗ AUTH
рд╕реЗ рдЪреЗрдХ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ AUTH
рдмрд┐рдирд╛ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдПрдВ, рдФрд░ рдлрд┐рд░ рджреЗрдЦреЗрдВ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝рдирд╛ рдХрд┐рддрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ:
fun processRequest(@RequestBody serviceRequest: Mono<ServiceRequest>): Mono<Response> {
рдЗрд╕рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк spring-webflux
рд╕реЗ рдореЗрд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рддреБрд▓рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
рд╡рд╕рдВрдд-рд╡реЗрдмрдлреНрд▓рдХреНрд╕ рд╢рд╛рдЦрд╛ рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди fun processRequest(@RequestBody serviceRequest: Mono<ServiceRequest>): Mono<Response> { val cacheRequest = serviceRequest.cache() val userInfoMono = cacheRequest.flatMap { getAuthInfo(it.authToken) }.flatMap { findUser(it.userId) } val cardFromInfoMono = cacheRequest.flatMap { findCardInfo(it.cardFrom) } val cardToInfoMono = cacheRequest.flatMap { findCardInfo(it.cardTo) } val paymentInfoMono = cardFromInfoMono.zipWith(cardToInfoMono) .flatMap { (cardFromInfo, cardToInfo) -> cacheRequest.flatMap { request -> sendMoney(cardFromInfo.cardId, cardToInfo.cardId, request.amount).map { cardFromInfo } } }.flatMap { getPaymentInfo(it.cardId) } return userInfoMono.zipWith(paymentInfoMono) .map { (userInfo, paymentInfo) -> log.info("result") SuccessResponse( amount = paymentInfo.currentAmount, userName = userInfo.name, userSurname = userInfo.surname, userAge = userInfo.age ) } }
рд╕рд╣рдордд рд╣реВрдВ рдХрд┐ рдЕрдм рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (рдкрд┐рдЫрд▓реЗ рдЕрд╡рд░реБрджреНрдз рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреА рддреБрд▓рдирд╛ рдореЗрдВ) рд▓рд┐рдЦрдирд╛ рдЕрдзрд┐рдХ рдХрдард┐рди рд╣реЛ рдЧрдпрд╛ рд╣реИред рдФрд░ рдЕрдЧрд░ рд╣рдо AUTH
рд╕реЗ "рднреВрд▓" рдЪреЗрдХ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдХрд░рдирд╛ рдЗрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдпрд╣ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рд╕рд╛рд░ рд╣реИред рдпрд╣ рдЕрд╕рдВрдмрджреНрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд╢реНрд░реГрдВрдЦрд▓рд╛рдУрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдмреНрд░рд╛рдВрдЪрд┐рдВрдЧ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ, рддреЛ рдХреЛрдб рдЕрдм рдЗрддрдирд╛ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИред
Kotlin coroutines, рдЬреЛ рдХрд┐рд╕реА рднреА рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ / рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдХреЛрдб рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдЕрдиреБрдХреВрд▓ рд╣реИрдВ, рдпрд╣рд╛рдВ рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд░рд┐рдПрдХреНрдЯрд░ , рдХрдВрдкреНрд▓реАрдЯрдЯреЗрдмрд▓ рд╕реАрдореЗрдВрдЯ , рдЖрджрд┐ рдХреЗ рд▓рд┐рдП рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд▓рд┐рдЦрд┐рдд рд░реИрдкрд░ рд╣реИрдВред рд▓реЗрдХрд┐рди рднрд▓реЗ рд╣реА рдЖрдкрдХреЛ рд╕рд╣реА рди рдорд┐рд▓реЗ, рд╡рд┐рд╢реЗрд╖ рдмрд┐рд▓реНрдбрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЖрдк рдЗрд╕реЗ рд╣рдореЗрд╢рд╛ рд╕реНрд╡рдпрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдЖрдЗрдП рд╣рдо рдЕрдкрдиреЗ рджрдо рдкрд░ рдХреЛрд░рдЯрд╛рдЗрди рдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, spring-webflux-coroutines-start
рд╢рд╛рдЦрд╛ рдкрд░ рдЬрд╛рдПрдВред рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрднрд░рддрд╛ build.gradle.kts рдореЗрдВ рдЗрд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ:
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:$kotlinCoroutinesVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:$kotlinCoroutinesVersion")
рдФрд░ processRequest
рддрд░реАрдХрд╛ processRequest
рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ:
suspend fun processRequest(@RequestBody serviceRequest: ServiceRequest): Response = coroutineScope {
рдЗрд╕реЗ рдЕрдм рдореЛрдиреЛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ рдФрд░ рдмрд╕ рдПрдХ рдирд┐рд▓рдВрдмрд┐рдд рд╕рдорд╛рд░реЛрд╣ (рд╡рд╕рдВрдд рдФрд░ рдХреЛрдЯрд▓рд┐рди рдХреЗ рдПрдХреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж) рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рдХрд┐ рд╣рдо рд╡рд┐рдзрд┐ рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд coroutines рдмрдирд╛рдПрдВрдЧреЗ, рд╣рдореЗрдВ рдПрдХ рдЪрд╛рдЗрд▓реНрдб рд╕реНрдХрд╛рдЙрдЯ coroutineScope
рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА (рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдЧреБрдВрдЬрд╛рдЗрд╢ рдмрдирд╛рдиреЗ рдХреЗ рдХрд╛рд░рдгреЛрдВ рдХреА рд╕рдордЭ рдХреЗ рд▓рд┐рдП, рд╕рдВрд░рдЪрд┐рдд рд╕рдВрдЧрдгрдирд╛ рдкрд░ рд░реЛрдорди рдПрд▓рд┐рд╕реЗрд░реЛрд╡ рдХрд╛ рдкреЛрд╕реНрдЯ рджреЗрдЦреЗрдВ)ред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЕрдиреНрдп рд╕реЗрд╡рд╛ рдХреЙрд▓ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдмрджрд▓реЗ рд╣реИрдВред рд╡реЗ рдЙрд╕реА рдореЛрдиреЛ рдХреЛ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕ рдкрд░ рдХреНрд╡реЗрд░реА рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд▓рд┐рдП рд╡рд╛рдЯреНрд╕рдПрдк suspend
рд╡рд┐рдзрд┐ рдХреЛ "рдкреНрд░рддреАрдХреНрд╖рд╛" рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдпрджрд┐ рдЖрдкрдХреЗ рд▓рд┐рдП рдХреЙрд░рдЯреЙрдпрдиреНрд╕ рдЕрднреА рднреА рдПрдХ рдирдИ рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИ, рддреЛ рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд╡рд┐рд╡рд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рдЕрджреНрднреБрдд рдорд╛рд░реНрдЧрджрд░реНрд╢рд┐рдХрд╛ рд╣реИ ред processRequest
рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВред рдЕрдзрд┐рдХ рд╕реЗ рдЕрдзрд┐рдХ рд╡рд┐рдзрд┐ рдпрд╛ spring-webflux-coroutines
рд╢рд╛рдЦрд╛ рдкрд░ рдЬрд╛рдПрдВ:
рд╡рд╕рдВрдд-рд╡реЗрдмрдлреНрд▓рдХреНрд╕-рдХреЛрд░рдЯрд╛рдЗрдиреНрд╕ рд╢рд╛рдЦрд╛ рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди suspend fun processRequest(@RequestBody serviceRequest: ServiceRequest): Response = coroutineScope { log.info("start") val userInfoDeferred = async { val authInfo = getAuthInfo(serviceRequest.authToken).awaitFirst() findUser(authInfo.userId).awaitFirst() } val paymentInfoDeferred = async { val cardFromInfoDeferred = async { findCardInfo(serviceRequest.cardFrom).awaitFirst() } val cardToInfoDeferred = async { findCardInfo(serviceRequest.cardTo).awaitFirst() } val cardFromInfo = cardFromInfoDeferred.await() sendMoney(cardFromInfo.cardId, cardToInfoDeferred.await().cardId, serviceRequest.amount).awaitFirst() getPaymentInfo(cardFromInfo.cardId).awaitFirst() } val userInfo = userInfoDeferred.await() val paymentInfo = paymentInfoDeferred.await() log.info("result") SuccessResponse( amount = paymentInfo.currentAmount, userName = userInfo.name, userSurname = userInfo.surname, userAge = userInfo.age ) }
рдЖрдк рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде рдХреЛрдб рдХреА рддреБрд▓рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрд░рдЖрдЙрдЯ рдХреЗ рд╕рд╛рде, рдЖрдкрдХреЛ рдЕрдЧреНрд░рд┐рдо рдореЗрдВ рд╕рднреА рд╢рд╛рдЦрд╛ рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╕реЛрдЪрдирд╛ рд╣реЛрдЧрд╛ред рд╣рдо рд╕рд┐рд░реНрдл await
рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕рд╣реА рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╢рд╛рдЦрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреЛрдб рдореВрд▓ рд╕реАрдзрд╛ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рдорд╛рди рд╕рдВрднрд╡ рд╣реИ, рдЬреЛ рдмрджрд▓рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред рдФрд░ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрд╛рд░рдХ рдпрд╣ рд╣реИ рдХрд┐ рдХреЛрд░рд╛рдЙрдЯреАрди рдмрд╕ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рд╢реАрд▓ рдХреЛрдб рдореЗрдВ рдПрдореНрдмреЗрдбреЗрдб рд╣реЛрддреЗ рд╣реИрдВред
рдЖрдкрдХреЛ рдЗрд╕ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рддреНрдордХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЕрдзрд┐рдХ рдкрд╕рдВрдж рдЖ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд░реНрд╡реЗрдХреНрд╖рдг рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрдИ рд▓реЛрдЧреЛрдВ рдХреЛ рдпрд╣ рдЕрдзрд┐рдХ рдХрдард┐рди рд▓рдЧрддрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рджреЛрдиреЛрдВ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЙрдирдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЖрдк рдЕрдкрдиреА рдкрд╕рдВрдж рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╡реИрд╕реЗ, рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдХреЛрдЯрд▓рд┐рди рдореЗрдВ рдлреНрд▓реЛ рдХреЗ рд╕рд╛рде "рдХреЛрд▓реНрдб" рдХреЙрд░рдЯрд╛рдЗрди рдмрдирд╛рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рднреА рд╣реИ, рдЬреЛ рд░рд┐рдПрдХреНрдЯрд░ рдХреЗ рд╕рдорд╛рди рд╣реИрдВред рд╕рдЪ рд╣реИ, рд╡реЗ рдЕрднреА рднреА рдкреНрд░рд╛рдпреЛрдЧрд┐рдХ рдЪрд░рдг рдореЗрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдм рдЖрдк рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ рдЖрдЬрд╝рдорд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдореИрдВ рдпрд╣рд╛рдВ рд╕рдорд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдФрд░ рдЕрдВрдд рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ рдЫреЛрдбрд╝рддрд╛ рд╣реВрдВ:
рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рд░реБрдЪрд┐ рд░рдЦрддреЗ рдереЗ рдФрд░ рдЖрдк рд╕рднреА рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рдзрд┐ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд╕реНрд╡рдпрдВ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реЗред рдФрд░, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдореИрдВ рдпрд╣ рд╡рд┐рд╢реНрд╡рд╛рд╕ рджрд┐рд▓рд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдкрдХреЛ рдХреЛрд░рдЯрд╛рдЗрди рдХреЗ рд╕рд╛рде рд╡рд┐рдХрд▓реНрдк рдЕрдзрд┐рдХ рдкрд╕рдВрдж рд╣реИ =)
рдЕрдВрдд рддрдХ рдкрдврд╝рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдХреЛ рдзрдиреНрдпрд╡рд╛рдж!