рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдпрд╣ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдкреНрд▓реЗ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд▓рд┐рдП рд╕реНрд╡реИрдЧрд░ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЬреАрд╡рди рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд░реЗрдВред рдореИрдВ рдмрддрд╛ рджреВрдБрдЧрд╛:- рд╕реНрд╡реИрдЧрд░-рдкреНрд▓реЗ (рдкреНрд▓реЗ рдореЙрдбреНрдпреВрд▓ рдЬреЛ рдЖрдкрдХреЛ рд╕реНрд╡реИрдЧрд░-рдПрдкрд┐ рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рдУрдкрдирдПрдкреАрдЖрдИ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ) рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдХреИрд╕реЗ рдЬрдХрдбрд╝реЗрдВ рдФрд░ рд╕реНрд╡реИрдЧрд░-рдЙрдИ рдХреЛ рдХреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ (рдЙрддреНрдкрдиреНрди рджрд╕реНрддрд╛рд╡реЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ)
- рдореИрдВ рд╕реНрд╡реИрдЧрд░-рдХреЛрд░ рдХреЗ рдореБрдЦреНрдп рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ рдФрд░ рд╕реНрдХреИрд▓рд╛ рдХреЗ рд▓рд┐рдП рдЙрдирдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛
- рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рдП
- рд╕реНрд╡реИрдЧрд░ рдореЗрдВ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ рдкрддрд╛ рдХрд░реЗрдВ, рдЬреЛ рдЬреЗрдирд░рд┐рдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рд╣реИ
- ADT (рдмреАрдЬреАрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░) рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡реИрдЧрд░ рдХреЛ рдХреИрд╕реЗ рд╕рд┐рдЦрд╛рдирд╛ рд╣реИ
- рд╕рдВрдЧреНрд░рд╣ рдХрд╛ рд╡рд░реНрдгрди рдХреИрд╕реЗ рдХрд░реЗрдВ
рдпрд╣ рдЖрд▓реЗрдЦ рдЙрди рд╕рднреА рдХреЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрдЧрд╛ рдЬреЛ рд╕реНрдХрд╛рд▓рд╛ рдкрд░ Play рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдкреАрдЖрдИ рдХреЗ рдкреНрд░рд▓реЗрдЦрди рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВредрдирд┐рд░реНрднрд░рддрд╛ рдЬреЛрдбрд╝реЗрдВ
рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рдХрдИ рд╕реНрд░реЛрддреЛрдВ рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВ рдпрд╣ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓рддрд╛ рд╣реВрдВ рдХрд┐ рд╕реНрд╡реИрдЧрд░ рдФрд░ рдкреНрд▓реЗ рдлреНрд░реЗрдорд╡рд░реНрдХ рджреЛрд╕реНрддреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕реНрд╡реИрдЧрд░ рдкреНрд▓реЗ 2 рдореЙрдбреНрдпреВрд▓ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИредрдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдкрддрд╛ github рдкрд░:https://github.com/swagger-api/swagger-playрдирд┐рд░реНрднрд░рддрд╛ рдЬреЛрдбрд╝реЗрдВ:libraryDependencies ++= Seq(
"io.swagger" %% "swagger-play2" % "2.0.1-SNAPSHOT"
)
рдФрд░ рдпрд╣рд╛рдВ рд╕рдорд╕реНрдпрд╛ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ:рдЗрд╕ рд▓реЗрдЦрди рдХреЗ рд╕рдордп, рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдпрд╛ рддреЛ рдореЗрд╡реЗрди-рдХреЗрдВрджреНрд░реАрдп рдпрд╛ рд╕реЛрдирд╛рдЯрд╛рдЗрдк рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕реЗ рдирд╣реАрдВ рдЦреАрдВрдЪрд╛ рдЬрд╛ рд░рд╣рд╛ рдерд╛редрдорд╛рд╡реЗрди-рдХреЗрдВрджреНрд░реАрдп рдореЗрдВ, рд╕рднреА рдкрд╛рдП рдЧрдП рдирд┐рд░реНрдорд╛рдг рд╕реНрдХреЗрд▓ 2.12 рдореЗрдВ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдПред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, Scala 2.13 рдХреЗ рд▓рд┐рдП рдПрдХ рднреА рдЗрдХрдЯреНрдареЗ рд╕рдВрд╕реНрдХрд░рдг рдирд╣реАрдВ рдерд╛редрдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╢рд╛ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рд╡реЗ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрдВрдЧреЗредрд╕реЛрдирд╛рдЯрд╛рдЗрдк-рд░рд┐рд▓реАрдЬ рднрдВрдбрд╛рд░ рдкрд░ рдЪрдврд╝рддреЗ рд╣реБрдП, рдореБрдЭреЗ рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рд╡рд░реНрддрдорд╛рди рдХрд╛рдВрдЯрд╛ рдорд┐рд▓рд╛ред рдЬреАрдереБрдм рдкрд░ рдкрддрд╛:https://github.com/iterable/swagger-playрддреЛ, рд╣рдо рдирд┐рд░реНрднрд░рддрд╛ рдбрд╛рд▓реЗрдВ:libraryDependencies ++= Seq(
"com.iterable" %% "swagger-play" % "2.0.1"
)
рд╕реЛрдирд╛рдЯрд╛ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдЬреЛрдбрд╝реЗрдВ:resolvers += Resolver.sonatypeRepo("releases")
(рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдорд╛рд╡реЗрди-рдХреЗрдВрджреНрд░реАрдп рд╣реИ)рдЕрдм рдпрд╣ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдореЙрдбреНрдпреВрд▓ рдХреЛ рд╕рдХреНрд░рд┐рдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИред рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓play.modules.enabled += "play.modules.swagger.SwaggerModule"
рд╕рд╛рде рд╣реА рдорд╛рд░реНрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рд░реНрдЧ рдЬреЛрдбрд╝реЗрдВ:GET /swagger.json controllers.ApiHelpController.getResources
рдФрд░ рдореЙрдбреНрдпреВрд▓ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИредрдЕрдм рд╕реНрд╡реИрдЧрд░ рдкреНрд▓реЗ рдореЙрдбреНрдпреВрд▓ рдПрдХ рдЬрд╕рди рдлрд╝рд╛рдЗрд▓ рдЙрддреНрдкрдиреНрди рдХрд░реЗрдЧрд╛ рдЬрд┐рд╕реЗ рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИредрд╕реНрд╡реИрдЧрд░ рдХреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЖрдирдВрдж рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рднреА рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рд╕реНрд╡реИрдЧрд░-рдпреВрдЖрдИред рдпрд╣ swagger.json рдлрд╝рд╛рдЗрд▓ рдкрдврд╝рдиреЗ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╕рд░реНрд╡рд░ рдХреЛ рдЖрд░рд╛рдо рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рдХреА рдХреНрд╖рдорддрд╛, рдкреЛрд╕реНрдЯрдореИрди, рд░реЗрд╕реНрдЯ-рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рдЕрдиреНрдп рд╕рдорд╛рди рдЯреВрд▓ рдХрд╛ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЧреНрд░рд╛рдлрд┐рдХрд▓ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИредрддреЛ, рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ:libraryDependencies += "org.webjars" % "swagger-ui" % "3.25.3"
рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ, рд╣рдо рдПрдХ рд╡рд┐рдзрд┐ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рд╕реНрдерд┐рд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЗрдВрдбреЗрдХреНрд╕ред Html рдлрд╝рд╛рдЗрд▓ рдХреЛ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ:def redirectDocs: Action[AnyContent] = Action {
Redirect(
url = "/assets/lib/swagger-ui/index.html",
queryStringParams = Map("url" -> Seq("/swagger.json")))
}
рдЦреИрд░, рд╣рдо рд░реВрдЯ рдХреЛ рд░реВрдЯ рдлрд╛рдЗрд▓ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:GET /docs controllers.HomeController.redirectDocs()
рдмреЗрд╢рдХ, рдЖрдкрдХреЛ рд╡реЗрдмрдЬрд░реНрд╕-рдкреНрд▓реЗ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЬреЛрдбрд╝реЗрдВ:libraryDependencies += "org.webjars" %% "webjars-play" % "2.8.0"
рдФрд░ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рд░реВрдЯ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ:GET /assets
рдмрд╢рд░реНрддреЗ рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓ рд░рд╣рд╛ рд╣реЛ, рд╣рдо рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╣реИрдВhttp: // localhost: 9000 / рдбреЙрдХреНрд╕рдФрд░, рдЕрдЧрд░ рд╕рдм рдХреБрдЫ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕реНрд╡реИрдЧрд░ рдкреЗрдЬ рдкрд░ рдкрд╣реБрдВрдЪ рдЬрд╛рддреЗ рд╣реИрдВ:рдкреГрд╖реНрда рдореЗрдВ рдЕрднреА рддрдХ рд╣рдорд╛рд░реЗ рдмрд╛рдХреА-рдПрдкреАрдЖрдИ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╕реНрд╡реИрдЧрд░-рдкреНрд▓реЗ рдореЙрдбреНрдпреВрд▓ рджреНрд╡рд╛рд░рд╛ рд╕реНрдХреИрди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛редрдПрдиреЛрдЯреЗрд╢рди
рд╕рднреА рд╕реНрд╡реИрдЧрд░-рдПрдкреА-рдХреЛрд░ рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рд╡рд┐рд╕реНрддреГрдд рд╡рд┐рд╡рд░рдг рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.Xред рдореЗрд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ:@
Api - рдирд┐рдпрдВрддреНрд░рдХ рд╡рд░реНрдЧ рдиреЛрдЯ рдХрд░рддрд╛ рд╣реИ рдПрдХ рд╕реНрд╡реИрдЧрд░ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд░реВрдк рдореЗрдВ (рд╕реНрдХреИрдирд┐рдВрдЧ рдХреЗ рд▓рд┐рдП)@
ApiImplicitParam - рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдиреБрд░реЛрдз рдореБрдЦреНрдп рднрд╛рдЧ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ) рдПрдХ "рдирд┐рд╣рд┐рдд" рдкреИрд░рд╛рдореАрдЯрд░@
ApiImplicitParams - рдХрдИ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдВрдЯреЗрдирд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ @
ApiImplicitParam рдПрдиреЛрдЯреЗрд╢рди@
ApiModel - рдЖрдк рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ@
ApiModelProperty рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрд╕рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ -@
ApiOperation рдбрд╛рдЯрд╛ рдореЙрдбрд▓ рд╡рд░реНрдЧ рдХреНрд╖реЗрддреНрд░ - рдХрд╛ рд╡рд░реНрдгрди рдирд┐рдпрдВрддреНрд░рдХ рд╡рд┐рдзрд┐ (рд╢рд╛рдпрдж рдЗрд╕ рд╕реВрдЪреА рдореЗрдВ рдореБрдЦреНрдп рдПрдиреЛрдЯреЗрд╢рди)@
рдЖрдкреАрдкрд╛рд░рд╛рдо- рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ)@
ApiResponse рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ -@
ApiResponses рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ - рдХрдИ @
ApiResponse рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдВрдЯреЗрдирд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ ред рдЖрдорддреМрд░ рдкрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рдЙрддреНрддрд░ рд╢рд╛рдорд┐рд▓ рд╣реЛрддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рддреНрд░реБрдЯрд┐ рдХреЛрдб рд╣реЛрддреЗ рд╣реИрдВ)ред рдПрдХ рд╕рдлрд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЖрдорддреМрд░ рдкрд░ @
рдПрдкрд┐рдСрдкрд░реЗрд╢рди рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИ редрдЗрд╕рд▓рд┐рдП, рд╕реНрд╡реИрдЧрд░ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдВрддреНрд░рдХ рд╡рд░реНрдЧ рдХреЛ рд╕реНрдХреИрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ @
рдПрдкреА рдПрдиреЛрдЯреЗрд╢рди рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ@Api(value = ┬лRestController┬╗, produces = ┬лapplication/json┬╗)
class RestController @Inject()(
рдпрд╣ рд╕реНрд╡реИрдЧрд░ рдХреЗ рд▓рд┐рдП рд░реВрдЯ рдлрд╛рдЗрд▓ рдореЗрдВ рдирд┐рдпрдВрддреНрд░рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдФрд░ рдЙрдирдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВредрд▓реЗрдХрд┐рди рд╕рд┐рд░реНрдл рд╕реНрд╡реИрдЧрд░ рдХрдВрдЯреНрд░реЛрд▓рд░ рдХреНрд▓рд╛рд╕ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИред рд╕реНрд╡реИрдЧрд░ рдЕрдиреНрдп рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рд╣рдорд╛рд░рд╛ рдЗрдВрддрдЬрд╛рд░ рдХрд░ рд░рд╣рд╛ рд╣реИредрд╕реНрд╡реИрдЧрд░ рдЕрдкрдиреЗ рдЖрдк рдРрд╕рд╛ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛? рдХреНрдпреЛрдВрдХрд┐ рдЙрд╕реЗ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реА рдХрдХреНрд╖рд╛рдПрдВ рдХрд┐рд╕ рддрд░рд╣ рд╕реЗ рдЕрдиреБрдХреНрд░рдорд┐рдд рд╣реЛрддреА рд╣реИрдВред рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдореИрдВ uPickle рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдХреЛрдИ Circe рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдХреЛрдИ Play-JSON рдХрд╛ред рдЗрд╕рд▓рд┐рдП, рдЖрдкрдХреЛ рдкреНрд░рд╛рдкреНрдд рдФрд░ рдЬрд╛рд░реА рдХреА рдЧрдИ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рд╣реЛрдЧрд╛редрдЪреВрдВрдХрд┐ рдкреНрд░рдпреБрдХреНрдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕реНрдХрд╛рд▓рд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдХрдИ рдмрд╛рд░реАрдХрд┐рдпрд╛рдВ рд╣реИрдВредрдФрд░ рдкрд╣рд▓реА рдЪреАрдЬрд╝ рдЬреЛ рдЖрдкрдХреЛ рдирд┐рдкрдЯрд╛рдиреА рд╣реИ рд╡рд╣ рд╣реИ рд╕рд┐рдВрдЯреИрдХреНрд╕: рдиреЗрд╕реНрдЯреЗрдб рдПрдиреЛрдЯреЗрд╢рди рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВредрдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрд╛рд╡рд╛ рдХреЛрдб:@ApiResponses(value = {
@ApiResponse(code = 400, message = "Invalid ID supplied"),
@ApiResponse(code = 404, message = "Pet not found") })
рд╕реНрдХрд╛рд▓рд╛ рдореЗрдВ рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:@ApiResponses(value = Array(
new ApiResponse(code = 400, message = "Invalid ID supplied"),
new ApiResponse(code = 404, message = "Pet not found") ))
рдЙрджрд╛рд╣рд░рдг 1
рддреЛ, рдЪрд▓реЛ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдПрдХ рдЗрдХрд╛рдИ рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рд╣реИ:def find(id: String): Action[AnyContent] =
safeAction(AllowRead(DrillObj)).async { implicit request =>
drillsDao.findById(UUID.fromString(id))
.map(x => x.fold(NotFound(s"Drill with id=$id not found"))(x =>
Ok(write(x)))).recover(errorsPf)
}
рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд┐рд╡рд░рдг рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдПрдХ рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░, рдФрд░ рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдПрдВ рднреАред рд╕рдлрд▓ рд╣реЛрдиреЗ рдкрд░, рд╡рд┐рдзрд┐ рдбреНрд░рд┐рд▓ рдХреНрд▓рд╛рд╕ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд▓реМрдЯрд╛рдПрдЧреА: @ApiOperation(
value = " ",
response = classOf[Drill]
)
@ApiResponses(value = Array(
new ApiResponse(code = 404, message = "Drill with id=$id not found")
))
def find(@ApiParam(value = "String rep of UUID, id ") id: String)=
safeAction(AllowRead(DrillObj)).async { implicit request =>
drillsDao.findById(UUID.fromString(id))
.map(x => x.fold(NotFound(s"Drill with id=$id not found"))(x =>
Ok(write(x)))).recover(errorsPf)
}
рд╣рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╡рд░реНрдгрди рдорд┐рд▓рд╛ред рд╕реНрд╡реИрдЧрд░ рдиреЗ рд▓рдЧрднрдЧ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рдХрд┐ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рд╡рд╕реНрддреБ рдХреЛ рдХрд┐рд╕ рдХреНрд░рдо рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рдерд╛: рд╣рдорд╛рд░реЗ рдбреНрд░рд┐рд▓ рдХреНрд▓рд╛рд╕ рдореЗрдВ рд╕реНрдЯрд╛рд░реНрдЯ рдФрд░ рдПрдВрдб рдлреАрд▓реНрдб рдЗрдВрд╕реНрдЯреЗрдВрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИрдВ, рдФрд░ рд▓реЙрдиреНрдЧ рдореЗрдВ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рд╣реИрдВред рдореИрдВ 0 рдХреЛ рдЕрдзрд┐рдХ рдЙрдкрдпреБрдХреНрдд рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдмрджрд▓рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред рд╣рдо рдЕрдкрдиреА рдХрдХреНрд╖рд╛ рдореЗрдВ @ApiModel, @ApiModelProperty рдПрдиреЛрдЯреЗрд╢рди рд▓рд╛рдЧреВ рдХрд░рдХреЗ рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:@ApiModel
case class Drill(
id: UUID,
name: String,
@ApiModelProperty(
dataType = "Long",
example = "1585818000000"
)
start: Instant,
@ApiModelProperty(
dataType = "Long",
example = "1585904400000"
)
end: Option[Instant],
isActive: Boolean
)
рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдореЙрдбрд▓ рдХрд╛ рдмрд┐рд▓реНрдХреБрд▓ рд╕рд╣реА рд╡рд┐рд╡рд░рдг рд╣реИ:
рдЙрджрд╛рд╣рд░рдг 2
рдкреЛрд╕реНрдЯ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрд╣рд╛рдВ рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдиреБрд░реЛрдз рдирд┐рдХрд╛рдп рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, @
ApiImplicitParams рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: @ApiOperation(value = " ")
@ApiImplicitParams(Array(
new ApiImplicitParam(
value = " ",
required = true,
dataTypeClass = classOf[Drill],
paramType = "body"
)
))
@ApiResponses(value = Array(
new ApiResponse(code = 200, message = "ok")
))
def insert() = safeAction(AllowWrite(DrillObj)).async { implicit request =>
рдЙрджрд╛рд╣рд░рдг 3
рдЕрдм рддрдХ, рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рдерд╛ред рдпрд╣рд╛рдБ рдПрдХ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╢реНрд░реЗрдгреА рд╣реИ рдЬреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╣реИ:case class SessionedResponse[T](
val ses: SessionData,
val payload: T
)
рд╕реНрд╡реИрдЧрд░ рдЬреЗрдирд░рд┐рдХ рдХреЛ рдЕрднреА рддрдХ рдХрдо рд╕реЗ рдХрдо рдирд╣реАрдВ рд╕рдордЭрддрд╛ рд╣реИред рд╣рдо рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ рд╕рдВрдХреЗрдд рдирд╣реАрдВ рджреЗ рд╕рдХрддреЗ:@ApiOperation(
value = " ",
response = classOf[SessionedResponse[Drill]]
)
рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдЬрд┐рди рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЬрд╝рд░реВрд░рддреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЛ рдЙрдкрд╡рд░реНрдЧрд┐рдд рдХрд░реЗрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо DrillSessionedResponse рдХреЛ рдЙрдкрд╡рд░реНрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВредрдХреЗрд╡рд▓ рдкрд░реЗрд╢рд╛рдиреА рдпрд╣ рд╣реИ, рд╣рдо рдХреЗрд╕ рдХреНрд▓рд╛рд╕ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдирд╣реАрдВ рдорд┐рд▓ рд╕рдХрддреЗ рд╣реИрдВред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, рдХреЗрд╕ рдХреНрд▓рд╛рд╕ рдХреЛ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдмрджрд▓рдиреЗ рд╕реЗ рдореБрдЭреЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рд░реЛрдХрддрд╛ рд╣реИред рдлрд┐рд░:class SessionedResponse[T](
val ses: SessionData,
val payload: T
)
object SessionedResponse {
def apply[T](ses: SessionData, payload: T) = new SessionedResponse[T](ses, payload)
}
private[controllers] class DrillSessionedResponse(
ses: SessionData,
payload: List[Drill]
) extends SessionedResponse[List[Drill]](ses, payload)
рдЕрдм рдореИрдВ рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ рдЗрд╕ рд╡рд░реНрдЧ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ:@ApiOperation(
value = " ",
response = classOf[DrillSessionedResponse]
)
рдЙрджрд╛рд╣рд░рдг 4
рдЕрдм ADT рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдПрдХ рдФрд░ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдЙрджрд╛рд╣рд░рдг - рдмреАрдЬреАрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░редрд╕реНрд╡реИрдЧрд░ рдПрдбреАрдЯреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрдВрддреНрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:рд╕рд╛рд░ @
: ApiModel рдЗрд╕ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП 2 рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ1. рдЙрдкрдкреНрд░рдХрд╛рд░ - рдЙрдкрд╡рд░реНрдЧреЛрдВ рдХреА рдЧрдгрдирд╛2. discriminator рдХреНрд╖реЗрддреНрд░ рд╣реИ рдЬрд┐рд╕ рдкрд░ рдЙрдкрд╡рд░реНрдЧреЛрдВ рдПрдХ-рджреВрд╕рд░реЗ рд╕реЗ рднрд┐рдиреНрди рд╣реЛрддреЗ рд╣реИрдВ -редрдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, UPickle, рдХреЗрд╕ рдХрдХреНрд╖рд╛рдУрдВ рд╕реЗ JSON рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░ рд░рд╣рд╛ рд╣реИ, $ рдкреНрд░рдХрд╛рд░ рдХреЗ рдлрд╝реАрд▓реНрдб рдХреЛ рд╕реНрд╡рдпрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдФрд░ рдХреЗрд╕ - рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рд╡рд┐рд╡реЗрдХрд╢реАрд▓ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕рд╛рде рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реНрд╡реАрдХрд╛рд░реНрдп рдирд╣реАрдВ рдерд╛редрдореИрдВрдиреЗ рдПрдХ рдЕрд▓рдЧ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╡рд╣рд╛рдБ рд╣реИsealed trait Permission
case class Write(obj: Obj) extends Permission
case class Read(obj: Obj) extends Permission
рдЬрд╣рд╛рдВ рдУрдмреНрдЬ рдПрдХ рдФрд░ рдПрдбреАрдЯреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХреЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:
case object DrillObj extends Obj
case object TeamObj extends Obj
рд╕реНрд╡реИрдЧрд░ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдореЙрдбрд▓ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд░реНрдЧ (рдпрд╛ рд╡рд┐рд╢реЗрд╖рддрд╛) рдХреЗ рдмрдЬрд╛рдп, рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдмрдирд╛рдП рдЧрдП рдПрдХ рд╡рд░реНрдЧ рдХреЛ рдЖрд╡рд╢реНрдпрдХ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:@ApiModel(value = "Permission")
case class FakePermission(
@ApiModelProperty(
name = "$type",
allowableValues = "ru.myproject.shared.Read, ru.myproject.shared.Read"
)
t: String,
@ApiModelProperty(allowableValues = "permission.drill, permission.team"
obj: String
)
рдЕрдм рд╣рдореЗрдВ рдЕрдиреБрдорддрд┐ рдХреЗ рдмрдЬрд╛рдп рдПрдиреЛрдЯреЗрд╢рди рдореЗрдВ FakePermission рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛@ApiImplicitParams(Array(
new ApiImplicitParam(
value = "",
required = true,
dataTypeClass = classOf[FakePermission],
paramType = "body"
)
))
рд╕рдВрдЧреНрд░рд╣
рдЖрдЦрд┐рд░реА рдмрд╛рдд рдЬреЛ рдореИрдВ рдкрд╛рдардХреЛрдВ рдХрд╛ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдХрд╣рд╛, рд╕реНрд╡реИрдЧрд░ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдирд╣реАрдВ рд╕рдордЭрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд╣ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рдирддрд╛ рд╣реИредрддреЛ, @
ApiOperation рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рдкрд╛рд╕ рдПрдХ responseContainer рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЖрдк рдорд╛рди "рд╕реВрдЪреА" рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВредрдЗрдирдкреБрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ, рдПрдХ рд╕рдВрдХреЗрддdataType = "List[ru.myproject.shared.roles.FakePermission]"
рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рднреАрддрд░ рдЬреЛ рдЗрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреИрджрд╛ рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрджрд┐ рдЖрдк scala.collection.List рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ - рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИредрдирд┐рд╖реНрдХрд░реНрд╖
рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, рд╕реНрд╡реИрдЧрд░-рдХреЛрд░ рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдореИрдВ рд░реЗрд╕реНрдЯ-рдПрдкреАрдЖрдИ рдФрд░ рд╕рднреА рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛, рдЬрд┐рд╕рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдФрд░ рдмреАрдЬреАрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рд╕реНрд╡реИрдЧрд░-рдкреНрд▓реЗ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдкреАрдЖрдИ рд╡рд┐рд╡рд░рдг рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╖реНрдЯрддрдо рд╣реИред