Upload
heiko-seeberger
View
2.691
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Lift - Das Web-Framework für Scala
Citation preview
Copyright WeigleWilczek 2009
Das Web-Framework für ScalaHeiko Seeberger
2
“Lift is the only new framework in the last four years to offer fresh and innovative approaches to web development. It's not just some
incremental improvements over the status quo, it redefines the state of the art. If you are a web developer, you should learn Lift ...”
WARUM SIND WIR EIGENTLICH HIER?
Michael Galpin, Developer, eBay
WARUM NOCH EIN WEB-FRAMEWORK?
3
Lift pickt Rosinen von anderen Frameworks
Lift bringt eigene innovative Ansätze
DEMO: CHAT MIT 20 ZEILEN SCALA CODE
4
FÜR’S PROTOKOLL
5
• Projekt generieren mit mvn archetype:generate ...
• ChatServer.scala anlegen
• Chat.scala anlegen
• chat.xhtml Template anlegen
• In Boot.scala neues Menu zur SiteMap hinzufügen
DIE ANFÄNGE
6
2006
David Pollak Einfach zu benutzen
Sicher
Einfach zu deployenKeep the meaning
with the bytes
Scala with Sails
HEUTE
7
Lift 1.1 vor der Tür Sehr rege Community
Etliche Sites powered by Lift 32 Committer
FEATURES IM ANGEBOT
8
Templates
Persistenz
AJAX
Comet
User Management
Sitemap
“MUSTERLÖSUNG”
9
WEITERE FEATURES (UNVOLLSTÄNDIG)
10
JSON
JPA und JTA
Textile
Wizards
PayPay
AMPQ
OpenID
OSGi
TEMPLATES
11
<html> <head> <title>kix</title> ... <body> <div class="container"> ... <div class="span-18 last"> <lift:Msgs showAll="true"/> <lift:bind name="content"/> ... </div> <div class="span-12" style="text-align: center;"> <img src="/images/pbww.png"/> </div> ...
mit Lift-Tags
WIE SCHREIBEN WIR TEMPLATES?
12
In XHTML
TEMPLATES VERSCHACHTELN
13
<lift:surround ...>
<lift:bind ... />
class Games { def upcoming5(xhtml: NodeSeq) = bind("games", xhtml, "list" -> bindGames(Game upcoming 5, xhtml))
<lift:surround with="default" at="content"> ... <lift:Games.upcoming5> <games:list> <tr game:class=""> <td><span game:id=""><game:action/></span></td> <td><game:date/></td> <td><game:group/></td> <td><game:location/></td> <td><game:teams/></td> ...
SNIPPETS EINBINDEN
14
Snippet-Tag
Platzhalter imNamespace game
Snippet
class Games {
def upcoming5(xhtml: NodeSeq) = bind("games", xhtml, "list" -> bindGames(Game upcoming 5, xhtml))
private def bindGames(games: List[Game], xhtml: NodeSeq) = { val oddOrEven = OddOrEven() games flatMap { game => bind("game", chooseTemplate("games", "list", xhtml), "date" -> format(game.date.is, locale), "group" -> game.group.is.toString, "location" -> game.location.is, ...
SNIPPETS UND BINDING
15
Platzhalter ersetzen
LIVE DEMO
16
SITEMAP
17
MENÜS UND ZUGRIFFSKONTROLLE
18
SITEMAP ANLEGEN
19
val ifAdmin = If(() => User.superUser_?, () => RedirectResponse("/index"))
val homeMenu = Menu(Loc("home", ("index" :: Nil) -> false, "Home"))...val adminMenu = Menu(Loc("admin", ("admin" :: Nil) -> true, "Admin", ifAdmin), adminSubMenu: _*)
val menus = homeMenu :: ... adminMenu :: User.sitemap
LiftRules setSiteMap SiteMap(menus : _*)
MENÜS ANZEIGEN
20
<html> <head> <title>kix</title> ... <body> <div class="container"> ... <div class="span-5"> <div class="menu"> <lift:Menu.builder/> </div> ...
LIVE DEMO
21
PERSISTENZ
22
MAPPER
23
class Game extends LongKeyedMapper[Game] with IdPK {
object group extends MappedEnum(this, Group) { override def displayName = ?("Group") }
object team1 extends MappedTeam(this, "Team 1")
object team2 extends MappedTeam(this, "Team 2")
object date extends MappedDateTime(this) { override def displayName = ?("Date") }
object location extends MappedString(this, 100) { override def displayName = ?("Location") } ... Keep the meaning
with the bytes
CRUD SUPPORT
24
... with CRUDify[Long, Game]
SCHEMA ANLEGEN
25
val dbVendor = new StandardDBVendor(Props get "db.driver" openOr "org.h2.Driver", Props get "db.url" openOr "jdbc:h2:kix", Empty, Empty) { override def maxPoolSize = Props getInt "db.pool.size" openOr 3}DB.defineConnectionManager(DefaultConnectionIdentifier, dbVendor)Schemifier.schemify(true, Log.infoF _, Team, Game, Result, Tip, User)
LIVE DEMO
26
USER MANAGEMENT
27
CLAUSTHALER-PRINZIP
28
MORE THAN JUST CRUD
29
class User extends MegaProtoUser[User] {
override def shortName = { val s = super.shortName val i = s indexOf "@" if (i == -1) s else s.substring(0, i) }
override def firstNameDisplayName = ?("Name")
object points extends MappedInt(this)}
LIVE DEMO
30
AJAX SUPPORT
31
BEISPIEL: LISTEN-ELEMENTE LÖSCHEN
32
SCALA API FÜR AJAX
33
def editDelete(tip: Tip) = { def delete = { Tip delete_! tip SetHtml(tip.id.is.toString, NodeSeq.Empty) } renderEditDelete(tip, delete _)}
private def renderEditDelete(tip: Tip, jsCmd: () => JsCmd) = link("/tips/edit", () => currentTip(Full(tip)), editImg) ++ Text("") ++ ajaxDeleteImg(ajaxInvoke(jsCmd))
LIVE DEMO
34
COMET SUPPORT
35
CHATTEN LEICHT GEMACHT
36
FRAGEN / DISKUSSION
37