рдУрдкрди рдПрдкреАрдЖрдИ рдЧреЗрдо: рд╕реНрд╡реИрдЧрд░ рдкреНрд▓реЗ


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдпрд╣ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдкреНрд▓реЗ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд▓рд┐рдП рд╕реНрд╡реИрдЧрд░ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЬреАрд╡рди рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд░реЗрдВред рдореИрдВ рдмрддрд╛ рджреВрдБрдЧрд╛:

  1. рд╕реНрд╡реИрдЧрд░-рдкреНрд▓реЗ (рдкреНрд▓реЗ рдореЙрдбреНрдпреВрд▓ рдЬреЛ рдЖрдкрдХреЛ рд╕реНрд╡реИрдЧрд░-рдПрдкрд┐ рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рдУрдкрдирдПрдкреАрдЖрдИ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ) рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдХреИрд╕реЗ рдЬрдХрдбрд╝реЗрдВ рдФрд░ рд╕реНрд╡реИрдЧрд░-рдЙрдИ рдХреЛ рдХреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ (рдЙрддреНрдкрдиреНрди рджрд╕реНрддрд╛рд╡реЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ)
  2. рдореИрдВ рд╕реНрд╡реИрдЧрд░-рдХреЛрд░ рдХреЗ рдореБрдЦреНрдп рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░реВрдВрдЧрд╛ рдФрд░ рд╕реНрдХреИрд▓рд╛ рдХреЗ рд▓рд┐рдП рдЙрдирдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛
  3. рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рдП
  4. рд╕реНрд╡реИрдЧрд░ рдореЗрдВ рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ рдкрддрд╛ рдХрд░реЗрдВ, рдЬреЛ рдЬреЗрдирд░рд┐рдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рд╣реИ
  5. ADT (рдмреАрдЬреАрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░) рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡реИрдЧрд░ рдХреЛ рдХреИрд╕реЗ рд╕рд┐рдЦрд╛рдирд╛ рд╣реИ
  6. рд╕рдВрдЧреНрд░рд╣ рдХрд╛ рд╡рд░реНрдгрди рдХреИрд╕реЗ рдХрд░реЗрдВ

рдпрд╣ рдЖрд▓реЗрдЦ рдЙрди рд╕рднреА рдХреЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрдЧрд╛ рдЬреЛ рд╕реНрдХрд╛рд▓рд╛ рдкрд░ 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/*file               controllers.Assets.at(path="/public", file)

рдмрд╢рд░реНрддреЗ рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЪрд▓ рд░рд╣рд╛ рд╣реЛ, рд╣рдо рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╣реИрдВ

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


рдЬрд╣рд╛рдВ рдУрдмреНрдЬ рдПрдХ рдФрд░ рдПрдбреАрдЯреА рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХреЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:

//  permission.drill
case object DrillObj extends Obj

// permission.team
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 рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ - рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рдирд┐рд╖реНрдХрд░реНрд╖


рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ, рд╕реНрд╡реИрдЧрд░-рдХреЛрд░ рдПрдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдореИрдВ рд░реЗрд╕реНрдЯ-рдПрдкреАрдЖрдИ рдФрд░ рд╕рднреА рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛, рдЬрд┐рд╕рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдХрд╛рд░ рдФрд░ рдмреАрдЬреАрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рд╕реНрд╡реИрдЧрд░-рдкреНрд▓реЗ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдкреАрдЖрдИ рд╡рд┐рд╡рд░рдг рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╖реНрдЯрддрдо рд╣реИред

All Articles