PlayFramework 2.2 рдФрд░ Scala рдХреЗ рд╕рд╛рде RSS рдЪрд▓рд╛рдПрдВ



рд╢реБрдн рджрд┐рди, рдкреНрд░рд┐рдп Kravravchiansред

рд╣рдо, рдкреЛрдЧреНрд░реЛрдо рдкреНрд░реЛрдЧреНрд░рд╛рдорд░, рдмрд╣реБрдд рдмрд╛рд░ рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рдПрдХ рдирдИ рднрд╛рд╖рд╛ рдПрдХреНрд╕ рдпрд╛ рдлреНрд░реЗрдорд╡рд░реНрдХ рд╡рд╛рдИ рд╕реАрдЦрддреЗ рд╣реИрдВ - рдкрд░рд┐рдЪрдпрд╛рддреНрдордХ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рдмрд╛рдж рдХреНрдпрд╛ рд▓рд┐рдЦрдирд╛ рд╣реИ рдлрд┐рд░ рднреА рдПрдХ рдФрд░ рд╣реИрд▓реЛ рд╡рд░реНрд▓реНрдб? рдХреБрдЫ рдРрд╕рд╛ рдЬреЛ рдПрдХреНрд╕ / рд╡рд╛рдИ рдХреЗ рдХреБрдЫ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди рджрд┐рдЦрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдЬреНрдпрд╛рджрд╛ рд╕рдордп рдирд╣реАрдВ рд▓рдЧреЗрдЧрд╛ред

рдореЗрд░реЗ рд╕рд╛рдерд┐рдпреЛрдВ рдиреЗ рдЕрдХреНрд╕рд░ рдПрдХ рд╕рдорд╛рди рдкреНрд░рд╢реНрди рдкреВрдЫрд╛ред рдирддреАрдЬрддрди, рдПрдХ рд╕рд░рд▓ рд╡рд┐рдЪрд╛рд░ рдкреИрджрд╛ рд╣реБрдЖ - рдПрдХ рдЖрд░рдПрд╕рдПрд╕ рд░реАрдбрд░ рд▓рд┐рдЦреЗрдВред рдпрд╣рд╛рдВ рдЖрдк рдиреЗрдЯрд╡рд░реНрдХ, рдФрд░ XML рдкрд╛рд░реНрд╕рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдХрдиреЗрдХреНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рдХреЛ рджреЗрдЦреЗрдВред рд╣рд╛рдБ рдЖрдк рдХрднреА рдирд╣реАрдВ рдЬрд╛рдирддреЗ

рддреЛ, рдпрд╣рд╛рдВ рдмреИрдХрдПрдВрдб рдкрд░ рдкреНрд▓реЗ рдлреНрд░реЗрдорд╡рд░реНрдХ 2.2 + рд╕реНрдХрд╛рд▓рд╛ + рдореЛрдВрдЧреЛрдмреАрдбреА рд╕реНрдЯреИрдХ рдореЗрдВ рдПрдХ рд░реЛрдорд╛рдВрдЪрдХ рдпрд╛рддреНрд░рд╛ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ рдФрд░ рдлреНрд░рдВрдЯ рдкрд░ рдПрдВрдЧреБрд▓рд░рдЬреЗрдПрд╕ + рдХреЙрдлреАрд╕реНрдХреНрд░рд┐рдкреНрдЯ ред

рдЯреАрдПрд▓, рдбреЙ
рдкреВрд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рдкреНрд░рд▓реЗрдЦрди рдХреЗ рд╕рд╛рде рд╕реНрдХрд╛рд▓рд╛ рдкрд░ ~ 250-300 рд▓рд╛рдЗрдиреЛрдВ рдФрд░ рд╕реАрдПрд╕ рдкрд░ 150 рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рдерд╛ред рдЦреИрд░, рдХреБрдЫ рдПрдЪ.рдЯреА.рдПрдо.рдПрд▓.
Bitbucket рдкрд░ рдЙрдкрд▓рдмреНрдз рдХреЛрдб


рдФрд░ рдкрд╣рд▓рд╛ рдкрдбрд╝рд╛рд╡ рд╕рд╡рд╛рд▓ рд╣реЛрдЧрд╛ - рд╕реНрдХреИрд▓рд╛, рдЬрд╛рд╡рд╛ рдХреНрдпреЛрдВ рдирд╣реАрдВ? рдФрд░ рдХреНрдпреЛрдВ рдЦреЗрд▓рддреЗ рд╣реИрдВ, рдФрд░ рдПрдХ рд╣реА рд▓рд┐рдлреНрдЯ рдирд╣реАрдВ?

рдЙрддреНрддрд░ рдмрд╣реБрдд рд╣реА рд╕рд░рд▓ рдФрд░ рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рд╣реИрдВред
рд╕реНрдХрд╛рд▓рд╛ рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЙрдЪреНрдЪ рд╕реНрддрд░ рдХреА рдЕрдореВрд░реНрддрддрд╛ рдФрд░ рдХрдо рдХреЛрдб рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЬрдм рдореИрдВрдиреЗ рд╕рднреА рдЕрд╡рд╕рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ 200 рддрд░реАрдХреЛрдВ рдХреЗ рд╕рд╛рде рдорд╛рдирдХ рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП рдкреНрд░рд▓реЗрдЦрди рджреЗрдЦрд╛ ... рдЧрдВрднреАрд░рддрд╛ рд╕реЗ, рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдЖрдЬрд╝рдорд╛рдПрдВред
рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреА рдкрд╕рдВрдж рдХреЗ рд▓рд┐рдП - рд▓рд┐рдлреНрдЯ рдкрд░ рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рдиреЗ рдореБрдЭреЗ ~ 150 рдПрдордПрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдерд╛рдиреАрдпрд╣реЛрд╕реНрдЯ рдкрд░ рдПрдХ рдкреГрд╖реНрда рджрд┐рдпрд╛, рдФрд░ рдпрд╣ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рд╣реИред рдЙрд╕реА рд╕рдордп, рдПрдХ рд╣реА рдорд╢реАрди рдФрд░ рдПрдХ рд╣реА JVM Play рдкрд░, рдпрд╣ ~ 5-10 рдПрдордПрд╕ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛, рд╢рд╛рдпрдж рд╕рд┐рддрд╛рд░реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╣реИрдВред
рдФрд░ рдкреНрд▓реЗ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдкреНрдпрд╛рд░рд╛ рд╣реИред

рдореБрдЭреЗ рдкреНрд▓реЗ рдХреЗ рд╕рд╛рде рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдФрд░ рдЖрд░рдВрдн рдХрд░рдиреЗ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдпрд╛рдж рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рдореЗрдВ рд╕рдм рдХреБрдЫ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЪрдмрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ (рдЕрдкрдиреЗ рдкрд╕рдВрджреАрджрд╛ рдЖрдИрдбреАрдИ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рд╣реИ), рдФрд░ рд╣рдо рдЖрдЧреЗ рдмрдврд╝реЗрдВрдЧреЗред

рдЕрдиреБрд░реЛрдз рдкрде

рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рддрд░реАрдХрд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдЕрдиреБрд░реЛрдз рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рд╣реИред
рдЖрдЬ рдлреНрд░реЗрдорд╡рд░реНрдХ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдмреНрд▓реИрдХ рдмреЙрдХреНрд╕ рдХреЛ рдЫреЛрдбрд╝рдирд╛ рдмреЗрд╣рддрд░ рд╣реИ, рдЦрд╛рд╕рдХрд░ рдЬрдм рд╕реЗ рдЗрд╕реЗ рдиреЗрдЯреНрдЯреА рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реЛрдЧрд╛ рдЧрд╣рд░реА рдЦреБрджрд╛рдИред рд╢рд╛рдпрдж рдЪреАрди рдХреЛред
рдЪреВрдВрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдирджреА рдПрдХ рдмреНрд░реБрдХ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП Play рдореЗрдВ рдХреЛрдИ рднреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд░реВрдЯрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╡рд░реНрдгрд┐рдд рд╣реИ
conf / рдорд╛рд░реНрдЧреЛрдВ
 # рд░реВрдЯ
 # рдпрд╣ рдлрд╛рдЗрд▓ рд╕рднреА рдЖрд╡реЗрджрди рдорд╛рд░реНрдЧреЛрдВ (рдкрд╣рд▓реЗ рдЙрдЪреНрдЪ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╡рд╛рд▓реЗ рдорд╛рд░реНрдЧреЛрдВ) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреА рд╣реИред
 # ~~~~

 # рдЬрд╛рдУ
 GET / рд╕рдорд╛рдЪрд╛рд░ рдирд┐рдпрдВрддреНрд░рдХреЛрдВред NewsController.news (рдЯреИрдЧ: рд╕реНрдЯреНрд░рд┐рдВрдЧ? = "", рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХрд░реЗрдВ: Int? = (System.currentTimeMillis () / 1000) .toInt)ред

 # рдкрд╛рд░реНрд╕ рдЦрдмрд░
 GET / рдкрд╛рд░реНрд╕ рдХрдВрдЯреНрд░реЛрд▓рд░ред NewsController.parseRSS

 # рдЬрд╛рдУ
 GET / рдЯреИрдЧ рдХрдВрдЯреНрд░реЛрд▓рд░ .agsController.tags

 # рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдлрд╝реЛрд▓реНрдбрд░ рд╕реЗ / рд╕рдВрдкрддреНрддрд┐ URL рдкрде рдкрд░ рд╕реНрдереИрддрд┐рдХ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдореИрдк рдХрд░реЗрдВ
 GET / рдЖрд╕реНрддрд┐рдпреЛрдВ / * рдлрд╝рд╛рдЗрд▓ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ.рдПрд╕реЗрдЯреНрд╕ (рдкрде = "/ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ", рдлрд╝рд╛рдЗрд▓)

 # рд╣реЛрдо рдкреЗрдЬ
 рдкреНрд░рд╛рдкреНрдд / рдирд┐рдпрдВрддреНрд░рдХреЛрдВред рдЖрд╡реЗрджрдиред рд╕реВрдЪрдХрд╛рдВрдХ



рдорд╛рд░реНрдЬрд┐рди рдореЗрдВ рдорд╛рд░реНрдЬрд┐рди:
рдореИрдВ рдЕрд▓рдЧ рд╕реЗ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ рдХрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкрджреНрдзрддрд┐ рдХреЗ рд▓рд┐рдП рджрд┐рдП рдЧрдП рддрд░реНрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдмрд╣реБрдд рд╕рдВрднрд╛рд╡рдирд╛ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡рд░реНрддрдорд╛рди рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ред
рд╡реИрд╕реЗ, рдкреНрд▓реЗ рдореЗрдВ рд░рд╛рдЙрдЯрд┐рдВрдЧ рдХрд╛рдлреА рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╣реИ, рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддреЗ рд╕рдордп regexp рддрдХред

рдЯрд┐рдХрдЯ рдкреЗрд╢ рдХрд░реЗрдВ!

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рд╢реАрд░реНрд╖рдХ рд╕реЗ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ - рдХрд╣рд╛рдиреА рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рд╕рд╛рде рдЬрд╛рд░реА рд╣реИред рдкреНрд▓реЗ рдореЗрдВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд┐рдпрдВрддреНрд░рдХ controllers рдкреИрдХреЗрдЬ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрддреЗ рд╣реИрдВ, Controller рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╡реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реЛрддреЗ рд╣реИрдВ рдЬрд┐рдирдХреЗ рддрд░реАрдХреЗ рд░реВрдЯрд┐рдВрдЧ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрддреЗ рд╣реИрдВред
рдЪреВрдВрдХрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди AJAX рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рд░реНрд╡рд░ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдореБрдЦреНрдп рдкреГрд╖реНрда рдХреЛ рд░реЗрдВрдбрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдВрддреНрд░рдХ рдПрдХ рд╡рд░реНрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рддреБрдЪреНрдЫ рд╣реИ рдФрд░ рдХреЗрд╡рд▓ HTML / CS / JS рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИред

рдЯрд╛рдЗрдкреНрдб рдФрд░ 20 рд▓рд╛рдЗрдиреЗрдВ рдирд╣реАрдВ
 package controllers import play.api.mvc._ /** * playRSS entry point */ object Application extends Controller { /** * Main page. So it begins... * @return */ def index = Action { Ok(views.html.index()) } } 


Ok play.api.mvc.SimpleResult рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкреЗрдЬ рдХреЗ рд╣реЗрдбрд░ рдФрд░ рдмреЙрдбреА рд╣реЛрддреЗ рд╣реИрдВред рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдмрд░рд╛рдмрд░ рд╣реЛрдЧреА, рдХреНрдпреЛрдВрдХрд┐ рд╕рдмрд╕реЗ рдЪреМрдХрд╕ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ рдЧрдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, 200 OK ред

рдордЧрд░
рдпрджрд┐ рдкреВрд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реНрдг рдирд┐рдпрдВрддреНрд░рдХ 20 рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдмрд╣реБрдд рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдЖрдк рд░реВрдмрд▓ рдореЗрдВ рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВред

рддреЛ, AJAX рдЧреНрд░рд╛рд╣рдХ рдХреЛ рд╕рдорд╛рдЪрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдЕрдиреБрд░реЛрдз рджреЗрдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реИ? рд░рд╛рдЗрдЯ, JSONред
NewsController рдРрд╕рд╛ рдХрд░рддрд╛ рд╣реИ NewsController

рдСрдмреНрдЬреЗрдХреНрдЯ рдиреНрдпреВрдЬрд╝рдХрдВрдЯреНрд░реЛрд▓рд░
 package controllers import play.api.mvc._ import scala.concurrent._ import models.News import play.api.libs.concurrent.Execution.Implicits.defaultContext import models.parsers.Parser import com.mongodb.casbah.Imports._ object NewsController extends Controller { /** * Get news JSON * @param tag optional tag filter * @param pubDate optional pubDate filter for loading news before this UNIX timestamp * @return */ def news(tag: String, pubDate: Int) = Action.async { val futureNews = Future { try { News asJson News.allNews(tag, pubDate) } catch { case e: MongoException => throw e } } futureNews.map { news => Ok(news).as("application/json") }.recover { case e: MongoException => InternalServerError("{error: 'DB Error: " + e.getMessage + "'}").as("application/json") } } /** * Start new RSS parsing and return first N news * @return */ def parseRSS = Action.async { val futureParse = scala.concurrent.Future { try { Parser.downloadItems(News.addNews(_)) News asJson News.allNews() } catch { case e: Exception => throw e } } futureParse.map(newsJson => Ok(newsJson).as("application/json")).recover { case e: MongoException => InternalServerError("{error: 'DB Error: " + e.getMessage + "'}").as("application/json") case e: Exception => InternalServerError("{error: 'Parse Error: " + e.getMessage + "'}").as("application/json") } } } 


Future ред Async ред рдпрд╣рд╛рдВ рдкрд╣рд▓реА рдмрд╛рд░ рдпрд╣ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреНрд▓реЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╣реИ рдФрд░, рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдЖрдкрдХреЛ рдзрд╛рд░рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдЬрдм рд╣рдореЗрдВ рддрддреНрдХрд╛рд▓ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП we рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ , рддреЛ рдПрдХ рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝реЗрдВ рдпрд╛ рдПрдХ рдФрд░ рдзреАрдореА рдЧрддрд┐ рд╕реЗ I / O рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░реЗрдВ, Future рдмрдЪрд╛рд╡ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ рдореБрдЦреНрдп рдзрд╛рд░рд╛ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд┐рдП рдмрд┐рдирд╛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдПрдХ рдСрдкрд░реЗрд╢рди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред Future рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд╕рдВрджрд░реНрдн рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдереНрд░реЗрдбреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪрд┐рдВрддрд╛ рдирд╣реАрдВ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред
рдЪреВрдВрдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдЕрдм Future[SimpleResult] рдирд╣реАрдВ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди Future[SimpleResult] , ActionBuilder рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ async рд╡рд┐рдзрд┐ рдХрд╛ ActionBuilder (рдЬреЛ Action рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)

рдкрд░рд┐рджреГрд╢реНрдп

рдЖрдЗрдП рдЗрд╕ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рджреБрдГрд╕реНрд╡рдкреНрди рдХреЗ рд╕рд╛рде рд░реБрдХреЗрдВ рдФрд░ рдЙрди рдЯреЗрдореНрдкрд▓реЗрдЯреНрд╕ рдХреЛ рдЪрд╛рд▓реВ рдХрд░реЗрдВ рдЬреЛ рд╣рдорд╛рд░реА рдЖрдВрдЦ рдХреЗ рд▓рд┐рдП рд╕реБрдВрджрд░ рд╣реИрдВред Play рдирд┐рдпрдорд┐рдд HTML рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рд╕реНрдХрд╛рд▓рд╛ рдХреЛрдб рдЖрд╡реЗрд╖рдг рдХреЗ рд╕рд╛рде рд╕рд╛рдорд╛рдиреНрдп HTMLред рдЯреЗрдореНрдкрд▓реЗрдЯ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕реНрд░реЛрдд рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдирд┐рдпрдорд┐рдд рдлрд╝рдВрдХреНрд╢рди рд╣реЛрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдЖрдк рдкреИрд░рд╛рдореАрдЯрд░ рдкрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЕрдиреНрдп рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХрдиреЗрдХреНрдЯ (рдХреЙрд▓) рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╡реИрд╕реЗ, рдХрдИ HTML рдореЗрдВ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдзреАрдореА рд╕рдВрдХрд▓рди рд╕рдордп рдХреЗ рдХрд╛рд░рдг рдХреЛрдб рдореЗрдВ рдирдП рдЯреЗрдореНрдкрд▓реЗрдЯ рдЗрдВрдЬрди рдХреЛ рдирд╛рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ рдареАрдХ рд╣реВрдВред
index.scala.html
 <!DOCTYPE html> <html> <head> <title> playRSS </title> <link rel="shortcut icon" href='@routes.Assets.at("images/favicon.png")' type="image/png"> <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"/> <link rel="stylesheet" href='@routes.Assets.at("stylesheets/main.css")'> @helper.requireJs(core = routes.Assets.at("javascripts/require.js").url, module = routes.Assets.at("javascripts/main").url) </head> <body> <div class="container" id="container" ng-controller="MainCtrl"> <a href="/"><h1>playRSS</h1></a> @control() <div class="row"> <div class="col-lg-12"> @news() </div> </div> </div> </body> </html> 


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рд╕реНрд░реЛрдд рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ - рдереЛрдбрд╝рд╛ рдЬрд╛рджреВред @helper рдХрдиреЗрдХреНрдЯ @helper рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдлреНрд░реЗрдорд╡рд░реНрдХ рджреНрд╡рд╛рд░рд╛ рдЖрдкреВрд░реНрддрд┐ рдХреА рдЬрд╛рддреА рд╣реИ, рдФрд░ рдореЗрди.рдЬреЗрдПрд╕ рдХреЗ рд▓рд┐рдП рдкрде рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдлреНрд░рдВрдЯреЗрдВрдб рдХреЛ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред @news() рдФрд░ @control() рдХреНрд░рдорд╢рдГ news.scala.html рдФрд░ control.scala.html рдЯреЗрдореНрдкрд▓реЗрдЯ рд╣реИрдВред рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╡рд░реНрддрдорд╛рди рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдЕрдВрджрд░ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдорд┐рд▓реЛред
рдФрд░ рднреА
рдЫреЛрд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдЧрд░ / рдФрд░, рдЖрджрд┐ред рд╡рд┐рд╕реНрддреГрдд рджрд╕реНрддрд╛рд╡реЗрдЬ рд╣реИ

рдкрд░реНрд╡рдд рдХрд╕рд╛рдм

рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдЬрд╛рд░реА рд░рдЦреЗрдВред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдорд╛рдирдЧреЛ рдХреЛ рдЪреБрдирд╛ рдЧрдпрд╛ рдерд╛ред рдЪреВрдВрдХрд┐ рдореИрдВ рдЯреЗрдмрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЖрд▓рд╕реА рд╣реВрдВред :)
Casbah рдПрдХ рд░реЛрд▓рд┐рдВрдЧ рдкрд┐рди рдореЗрдВ MongoDB рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдбреНрд░рд╛рдЗрд╡рд░ рд╣реИ ред рдЗрд╕рдХрд╛ рд▓рд╛рдн рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╕рд╛рджрдЧреА рдФрд░ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╣реИред рдФрд░ рдореБрдЦреНрдп рджреЛрд╖ рдХреЛ рдЕрдВрдд рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛рдПрдЧрд╛ред

рдЪрд╛рд▓рдХ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ:


рдФрд░ рдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ред рдЪреВрдБрдХрд┐ рдкрд╛рдардХ рдХреЛ рд╕рд░рд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ рдЬреЛ рдХрд┐ MongoDB рд╕реЗ рдЬрд░реВрд░рддрдордВрдж рд╕рдВрдЧреНрд░рд╣ рдХреЛ рд╡рд┐рддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред DAO рдпрд╛ DI рдХреЛ рдмрд╛рдбрд╝ рджреЗрдиреЗ рдХрд╛ рд╕рд╣реА рд╢рдмреНрдж рдмрд╕ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╣реИред

рдСрдмреНрдЬреЗрдХреНрдЯ рдбреЗрдЯрд╛рдмреЗрд╕
 package models import com.mongodb.casbah.Imports._ import play.api.Play /** * Simple object for DB connection */ object Database { private val db = MongoClient( Play.current.configuration.getString("mongo.host").get, Play.current.configuration.getInt("mongo.port").get). getDB(Play.current.configuration.getString("mongo.db").get) /** * Get collection by its name * @param collectionName * @return */ def collection(collectionName:String) = db(collectionName) /** * Clear collection by its name * @param collectionName * @return */ def clearCollection(collectionName:String) = db(collectionName).remove(MongoDBObject()) } 


рдорд╛рд░реНрдЬрд┐рди рдореЗрдВ рдорд╛рд░реНрдЬрд┐рди:
рд╕реНрдХрд╛рд▓рд╛ рдореЗрдВ, рд╡рд╕реНрддреБрдПрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рд┐рдВрдЧрд▓рдЯрди рд╣реИрдВред рдпрджрд┐ рдЖрдк рдЙрдмрд╛рдК рдореЛрдб рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдирд╛рдо рд╡рд░реНрдЧ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рддрд╛рддреНрдХрд╛рд▓рд┐рдХ (рдЬрд╛рд╡рд╛ / рдЬреЗрд╡реАрдПрдо рджреГрд╢реНрдп рдореЗрдВ)ред рддреЛ рд╣рдорд╛рд░рд╛ рдХрдиреЗрдХреНрд╢рди рддрдм рдмрдврд╝реЗрдЧрд╛ рдЬрдм рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдкреВрд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЪрдХреНрд░ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред

рдпрд╣ рд╕реНрдХрд╛рд▓рд╛ рдФрд░ рдХреИрд╕рдмрд╛рд╣ рдХреЗ рдЖрдзрд╛рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ:

рд╡рд╕реНрддреБ рд╕рдорд╛рдЪрд╛рд░
 /** * Default news container * @param id MongoID * @param title * @param link * @param content * @param tags Sequence of tags. Since categories could be joined into one * @param pubDate */ case class News(val id: String = "0", val title: String, val link: String, val content: String, val tags: Seq[String], val pubDate: Long) /** * News object allows to operate with news in database. Companion object for News class */ object News { .... /** * Method to add news to database * @param news filled News object * @return */ def addNews(news: News) = { val toInsert = MongoDBObject("title" -> news.title, "content" -> news.content, "link" -> news.link, "tags" -> news.tags, "pubDate" -> news.pubDate) try { col.insert(toInsert) } catch { case e: Exception => } } .... /** * Get news from DB * @param filter filter for find() method * @param sort object for sorting. by default sorts by pubDate * @param limit limit for news select. by default equals to newsLimit * @return */ def getNews(filter: MongoDBObject, sort: MongoDBObject = MongoDBObject("pubDate" -> -1), limit: Int = newsLimit): Array[News] = { try { col.find(filter). sort(sort). limit(limit). map((o: DBObject) => { new News( id = o.as[ObjectId]("_id").toString, title = o.as[String]("title"), link = o.as[String]("link"), content = o.as[String]("content"), tags = o.as[MongoDBList]("tags").map(_.toString), pubDate = o.as[Long]("pubDate")) }).toArray } catch { case e: MongoException => throw e } } } 


MongoDB, рдПрдкреАрдЖрдИ рдФрд░ рдХреЗрд╕ рдХреНрд▓рд╛рд╕ рдиреНрдпреВрдЬрд╝ рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреА рддреБрдЪреНрдЫ рдлрд┐рд▓рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдЪрд┐рддред рдЕрдм рддрдХ, рд╕рдм рдХреБрдЫ рдкреНрд░рд╛рдердорд┐рдХ рд╣реИред рдмрд╣реБрдд рдЕрдзрд┐рдХред
рдХреБрдЫ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рдЪрд╛рд╣рд┐рдПред рдПрдХрддреНрд░реАрдХрд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ?

рдЯреИрдЧ рдирд┐рдХрд╛рд▓ рд░рд╣реЗ рд╣реИрдВ
 /** * News tag container * @param name * @param total */ case class Tags(name: String, total: Int) /** * Tags object allows to operate with tags in DB */ object Tags { /** * News collection contains all tag info */ private val col: MongoCollection = Database.collection("news") /** * Get all tags as [{name: "", total: 0}] array of objects * @return */ def allTags: Array[Tags] = { val group = MongoDBObject("$group" -> MongoDBObject( "_id" -> "$tags", "total" -> MongoDBObject("$sum" -> 1) )) val sort = MongoDBObject("$sort" -> MongoDBObject("total"-> -1)) try { col.aggregate(group,sort).results.map((o: DBObject) => { val name = o.as[MongoDBList]("_id").toSeq.mkString(", ") val total = o.as[Int]("total") Tags(name, total) }).toArray } catch { case e: MongoException => throw e } } } 


.aggregate рдЖрдкрдХреЛ рдмрд┐рдирд╛ рдорд╛рдирдЪрд┐рддреНрд░ рдХреЗ рдЪрдорддреНрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рд╕реБрд╡рд┐рдзрд╛ рджреЗрддрд╛ рд╣реИред рдФрд░ рд╕реНрдХрд╛рд▓рд╛ рдореЗрдВ рдХрд╛рдо рдХрд╛ рд╕рд┐рджреНрдзрд╛рдВрдд рдХрдВрд╕реЛрд▓ рд╕реЗ рд╣реА рд╣реИред рдПрдХ рддрд░рд╣ рдХрд╛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди-рд░рд╛рд╕реНрддрд╛, рдХреЗрд╡рд▓ рдХреЙрдорд╛ рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ред рдЯреИрдЧ рджреНрд╡рд╛рд░рд╛ рд╕рдореВрд╣реАрдХреГрдд, рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рд╕рдорд╛рди рдФрд░ рд╕рдВрдкреВрд░реНрдг рдЪреАрдЬрд╝ рдХреЛ рдХреНрд░рдордмрджреНрдз рдХрд░рддрд╛ рд╣реИред рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ред

рд╡реИрд╕реЗ, рдХреЗрд╕рдмрд╛рд╣ рдПрдХ рдЧрдврд╝ рд╣реИ

рдЖрдк JSON-XMLed рд╣реИрдВ

рдЖрдкрдХреЛ рдХрднреА рд╣рд╛рд░ рдирд╣реАрдВ рдорд╛рдирдиреА рдЪрд╛рд╣рд┐рдП
рдЖрдкрдХреЛ рдХрднреА рдирд┐рд░рд╛рд╢ рдирд╣реАрдВ рд╣реЛрдиреЗ рджреЗрдВрдЧреЗ

рдХреНрдпреЛрдВрдХрд┐ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд░реВрдк рд╕реЗ рдЯрд╛рдЗрдк рдХреА рдЧрдИ рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ XML / JSON рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдПрдХ рдзреЛрдЦрд╛ рдЬреИрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИред рд╕рдВрджреЗрд╣ рд╕реЗ рд╕рдВрдХреНрд╖рд┐рдкреНрддред
рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕реНрдХрд╛рд▓рд╛ рдореЗрдВ XML рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдореЗрд░реА рдЖрдВрдЦреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЦреБрд╢реА рд╣реИ (рдЬрд╛рд╡рд╛ рдореЗрдВ рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рдХрд╛рд░рдЦрд╛рдиреЛрдВ рдХреЗ рдмрд╛рдж)ред
XML рдкрд╛рд░реНрд╕рд░
 package models.parsers import scala.xml._ import models.News import java.util.Locale import java.text.{SimpleDateFormat, ParseException} import java.text._ import play.api.Play import collection.JavaConversions._ /** * Simple XML parser */ object Parser { /** * RSS urls from application.conf */ val urls = try { Play.current.configuration.getStringList("rss.urls").map(_.toList).getOrElse(List()) } catch { case e: Throwable => List() } /** * Download and parse XML, fill News object and pass it to callback * @param cb */ def downloadItems(cb: (News) => Unit) = { urls.foreach { (url: String) => try { parseItem(XML.load(url)).foreach(cb(_)) } catch { case e: Exception => throw e } } } /** * Parse standart RSS time * @param s * @return */ def parseDateTime(s: String): Long = { try { new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH).parse(s).getTime / 1000 } catch { case e: ParseException => 0 } } /** * For all items in RSS parse its content and return list of News objects * @param xml * @return */ def parseItem(xml: Elem): List[News] = (xml \\ "item").map(buildNews(_)).toList /** * Fill and return News object * @param node * @return */ def buildNews(node: Node) = new News( title = (node \\ "title").text, link = (node \\ "link").text, content = (node \\ "description").text, pubDate = parseDateTime((node \\ "pubDate").text), tags = Seq((node \\ "category").text)) } 


рдореИрдВ рд╕рд╣рдордд рд╣реВрдВ
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдлреЙрд░реНрдо \ рдпрд╛ \\ рдХреЗ рдирд╛рдо рд╡рд╛рд▓реА рд╡рд┐рдзрд┐рдпрд╛рдВ рдПрдХ рд╕реНрдЯреВрдкрд░ рдореЗрдВ рд╕рдВрдЪрд╛рд▓рд┐рдд рд╣реЛрддреА рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдХреБрдЫ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ рдЬрдм рдЖрдк рдЬрд╛рд╡рд╛ рд╕реЗ BigInteger рдХреЛ рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВред

JSON рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛? рд╕реНрдХрд╛рд▓рд╛ рдореЗрдВ рджреЗрд╢реА JSON рдЕрдм рддрдХ рдХреЛрдИ рднреА рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рдирд╣реАрдВ рд╣реИред рдзреАрдорд╛ рдФрд░ рдбрд░рд╛рд╡рдирд╛ред
рдореБрд╢реНрдХрд┐рд▓ рд╕рдордп рдореЗрдВ, Play and its Writes / Reads from play.api.libs.json рдкреИрдХреЗрдЬ play.api.libs.json ред рдХреНрдпрд╛ рдХрд┐рд╕реА рдХреЛ PHP 5.4 рд╕реЗ JsonSerializable рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкрддрд╛ рд╣реИ? рддреЛ рдкреНрд▓реЗ рдореЗрдВ рдЕрднреА рднреА рдЖрд╕рд╛рди рд╣реИ!

JSON рд▓рд┐рдЦрддреЗ рд╣реИрдВ
 case class News(val id: String = "0", val title: String, val link: String, val content: String, val tags: Seq[String], val pubDate: Long) /** * News object allows to operate with news in database. Companion object for News class */ object News { /** * Play Magic * @return */ implicit def newsWrites = Json.writes[News] /** * Converts array of news to json * @param src Array of News instances * @return JSON string */ def asJson(src: Array[News]) = { Json.stringify(Json.toJson(src)) } } 


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

рддрд╛рд░реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рдВрдЯреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ

рдЬрдмрдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдКрдм рд░рд╣рд╛ рд╣реИ рдФрд░ рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рджреНрд╡рд╛рд░рд╛ рд╕рд░реНрд╡рд░ рдХреЛ рднреЗрдЬреЗ рдЧрдП рдЕрдиреБрд░реЛрдз рдХреЗ рдЬрд╡рд╛рдм рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ ... рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВред рдПрдХ рдФрд░ рджреГрд╢реНрдпред
рдЬреИрд╕рд╛ рдХрд┐ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, CoffeeScript рдФрд░ AngularJS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдЗрд╕ рдмрдВрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп рдкреАрда рдХреЗ рдареАрдХ рдиреАрдЪреЗ рджрд░реНрдж рдХреА рд╕рдВрдЦреНрдпрд╛ 78.5% рдХрдо рд╣реЛ рдЧрдИред рдХреЛрдб рдХреА рд░рд╛рд╢рд┐ рдХреА рддрд░рд╣ред
рдпрд╣ рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдкрд╛рдардХ рдореЗрдВ рдЗрди рд╕реНрдЯрд╛рдЗрд▓рд┐рд╢, рдлреИрд╢рдиреЗрдмрд▓ рдФрд░ рдпреБрд╡рд╛ рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред рдФрд░ рдЗрд╕рд▓рд┐рдП рднреА рдХрд┐ рдореЗрд░реА рдкрд╕рдВрдж рдХреЗ рдврд╛рдВрдЪреЗ рдореЗрдВ рдмреЛрд░реНрдб рдкрд░ рдХреЙрдлреАрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдФрд░ рд▓реЗрд╕ рдХрдВрдкрд╛рдЗрд▓рд░ рд╣реИрдВред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЕрдиреБрднрд╡реА рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреБрдЫ рдирдпрд╛ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рд╕реАрдЦреЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдХреЗрд╡рд▓ рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рдЯреНрд░рд┐рдХреНрд╕ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ред

рдЕрдХреНрд╕рд░ рдХреЛрдгреАрдп рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рдмреАрдЪ рдбреЗрдЯрд╛ рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрддрд╛ рд╣реИред рдФрд░ рдХреЗрд╡рд▓ рдкрд░рд┐рд╖реНрдХрд╛рд░ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рдЬреНрдЬрди рд╣реА рдирд╣реАрдВ рдЬрд╛рддреЗ (рдЬреИрд╕реЗ рдХрд┐ рд▓реЛрдХрд▓рд╕реНрдЯреЛрд░реЗрдЬ рдХреЛ рд▓рд┐рдЦрдирд╛) ...
рдФрд░ рдХрд╛рд╕реНрдХреЗрдЯ рдмрд╕ рдЦреБрд▓ рдЬрд╛рддрд╛ рд╣реИред
рд╕реЗрд╡рд╛ рдХреЛ рдмрдирд╛рдирд╛ рдФрд░ рдЖрд╡рд╢реНрдпрдХ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдореЗрдВ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ
рдкреНрд░рдЪрд╛рд░
 define ["angular","ngInfinite"],(angular,infiniteScroll) -> newsModule = angular.module("News", ['infinite-scroll']) newsModule.factory 'broadcastService', ["$rootScope", ($rootScope) -> broadcastService = message: {}, broadcast: (sub, msg)-> if typeof msg == "number" then msg = {} this.message[sub] = angular.copy msg $rootScope.$broadcast(sub) ] newsModule 


рд╣рдо рднреЗрдЬрддреЗ рд╣реИрдВ
 define ["app/NewsModule"], (newsModule)-> newsModule.controller "PanelCtrl", ["$scope", "$http", "broadcastService", ($scope, $http, broadcastService)-> $scope.loadByTag = (tag) -> if tag.active tag.active = false broadcastService.broadcast("loadAll",0) else broadcastService.broadcast("loadByTag",tag.name) ] 


рд╣рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ
 define ["app/NewsModule","url"], (newsModule,urlParser)-> newsModule.controller "NewsCtrl", ["$scope", "$http", "broadcastService", ($scope, $http, broadcastService)-> #recieving message $scope.$on "loadAll", ()-> $scope.after = 0 $scope.tag = false $scope.busy = false $scope.loadByTag() ] 


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

рд╕рднреА рдЖрддреЗ рд╣реИрдВ

рдЖрдВрддреНрд░ рдФрд░ рдкреАрда рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреА рдЕрд░рд╛рдЬрдХ рдпрд╛рддреНрд░рд╛ рдХреЗ рдмрд╛рдж, рдпрд╣ рдпреЛрдЧреНтАНрдп рд╣реИред
рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди, рдШрд╛рддрдХ рдФрд░ рдмрд╣реБрдд рдЬреНрдпрд╛рджрд╛ рдирд╣реАрдВ, рд╣рд░ рдХрд┐рд╕реА рдХреЛ рдЕрдкрдиреЗ рд▓рд┐рдП рдЪреБрдирдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдЕрднреА рднреА рдЙрд╕ рдЙрдкрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдпрд╣ рдХрд╛рд░реНрдЧреЛ рдХреА рдЦреЗрддреА рдХреЗ рдмрдЬрд╛рдп, рд╕рд╣реА рдмреИрдарддрд╛ рд╣реИ?

рдореБрдЭреЗ рдкрд╕рдВрдж рдЖрдпрд╛:

рдкрд╕рдВрдж рдирд╣реАрдВ рдЖрдпрд╛:


рд╕рд╛рде рд╣реА, рд╡рд┐рдХрд╛рд╕ рдХрд░рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рднрд╡рд┐рд╖реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЕрд╡рд░реБрджреНрдз рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рд╕рд╛рд╡рдзрд╛рди рд░рд╣рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдПрдХ рд╣реИ рд▓реЗрдХрд┐рдиред рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдирд┐рд╖реНрдкрд╛рджрди рдХрд╛ рдореБрдЦреНрдп рдзрд╛рдЧрд╛ рдЕрд╡рд░реБрджреНрдз рдирд╣реАрдВ рд╣реЛрдЧрд╛, рджреВрд╕рд░реЗ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдФрд░ рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд░реНрдпрд╛рдкреНрдд рдзрд╛рдЧреЗ рд╣реИрдВ рдФрд░ рдХрдИ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рдЕрдиреБрд░реЛрдз рдирд╣реАрдВ рд╣реЛрдВрдЧреЗред рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░? рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдкреНрд▓реЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рд╕рдорд╛рди рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХреГрддрд┐ рдбреНрд░рд╛рдЗрд╡рд░реЛрдВ рдореЗрдВ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Casbah рдХреЗ рдмрдЬрд╛рдп ReactiveMongoред рдпрд╛ рдХрдо рд╕реЗ рдХрдо рдЕрднрд┐рдиреЗрддрд╛рдУрдВ рдФрд░ рдереНрд░реЗрдб рдкреВрд▓ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВред рд▓реЗрдХрд┐рди рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рдХрд╣рд╛рдиреА рд╣реИ ...

рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

рдкреБрдирд╢реНрдЪ
рдпрджрд┐ рдпрд╣ рд╕реНрдХреНрд░рд┐рдмрдмрд▓ рдереЛрдбрд╝рд╛ рд╕рд╛ рд▓рдЧ рд░рд╣рд╛ рдерд╛ - рддреЛ рдпрд╣рд╛рдВ рдмрд┐рдЯрдмрдХреЗрдЯ рдкрд░ рднрдВрдбрд╛рд░ рд╣реИ ред

Source: https://habr.com/ru/post/In197930/


All Articles