Play Framework Trainning
-
Upload
marcondes-macaneiro -
Category
Documents
-
view
183 -
download
1
Transcript of Play Framework Trainning
Play! Framework
Keuller Magalhães
www.playframework.com.br
2013
2
Agenda
Arquitetura de Componentes
Estrutura da Aplicação
Rotas e Controladores
Modelos
Views
Distribuição
4
Arquitetura de Componentes
HTTP
Routes
Cotroladores
Model ModelHTML XML JSON
Baseada em padrões:
● MVC
● Page Controller
● Separation of Concern
● DRY
● Active Record
● Low Coupling
● High Cohesion
● Single Responsability
● Interface segregation
● Dependency Inversion
● YAGNI
5
Arquitetura de Componentes
● Componentes:● Rotas (URLs)
● Controladores (fluxo)
● Modelos (entidades)
● Templates (views)
● Extensão através de plugins
● Suporte a aplicações modulares
7
Estrutura da Aplicação
Precisa de uma versão do Java 1.6+
Podemos fazer o download do Play!
www.playframework.org
Devemos descompactá-lo numa pasta
Adicionamos o caminho da pasta no classpath do
sistema
8
Estrutura da Aplicação
Acessando o console do Play!$ play
Para compilar nossa aplicação, basta digitar
$ compile
Para executarmos a aplicação, basta digitar:
$ run
Apontamos o navegador para a URL:
http://localhost:9000/
10
Estrutura da Aplicação
Limpando código do projeto
$ clean
Preparando projeto para Eclipse/IDEA
$ eclipse | idea
Executando os testes automatizados
$ test
Preparando a aplicação para implantação
$ clean compile stage
Atualizando as dependências do projeto
$ update
12
Rotas e Controladores
Rotas são mapeamentos entre URL e controladores
O arquivo conf/routes contem a definição de
todas as rotas de sua aplicaçãoGET / controllers.Application.index()
Esse mapeamento nos dá três informações:
Método HTTP usado GET
Caminho da requisição /
Método de ação index() da classe Application
13
Rotas e Controladores
Play suporta todos os métodos HTTP do protocolo GET, POST, PUT, DELETE, OPTIONS, HEAD, etc
Formato da URI
URI estática
GET /list controllers.Cliente.list()
URI dinâmicaGET /edit/:id controllers.Cliente.editar(id: Integer)
URI abrangenteGET /imagem/*arquivo controllers.Util.imagem(arquivo)
14
Rotas e Controladores
URI com parâmetros fixos
GET / controllers.Teste.show(page = “index”)
URI com parâmetros padrãoGET / controllers.Teste.show(page ?= “index”)
Prioridade entre as Rotas As primeiras rotas na declaração terão prioridade perante as
demais
Todas as rotas são compiladas no objeto routes, podendo
acessá-las via código Java, da seguinte forma:
routes.Application.index()
15
Rotas e Controladores
Play! é um framework MVC (baseado em ação)
Um controlador é uma classe Java dentro do pacote
controllers e que estende a classe Controller
Uma ação é um método público estático que retorna
um objeto Result Tipos de Result:
ok()
redirect()
notFound()
badRequest()
status()
16
Rotas e Controladores
Vejamos o controlador padrão:
package controllers;
import play.*;import play.mvc.*;import views.html.*;
public class Application extends Controller { public static Result index() { return ok(index.render("Your new application is ready.")); }}
17
Rotas e Controladores
Vamos definir as rotas para nossa aplicação
# ponto de entrada da aplicacaoGET / controllers.Application.index()
# CRUD tarefasGET /tarefas controllers.TarefaController.lista()POST /tarefas controllers.TarefaController.criar()POST /tarefas/excluir/:idcontrollers.TarefaController.excluir(id: Int)
Temos 3 rotas, sendo que:primeira: lista as tarefas existentes
segunda: cria uma nova tarefa
terceira: remove uma tarefa pelo id
18
Rotas e Controladores
Vamos definir a classe controladora
public class TarefaController extends Controller {
public static Result lista() { return TODO; }
public static Result criar() { return TODO;
}
public static Result excluir(Integer id) { return TODO; }}
TODO é um tipo de retorno 501 Not Implemented, útil durante o desenvolvimento.
20
Agenda
Arquitetura de Componentes
Estrutura da Aplicação
Rotas e Controladores
Modelos
Views
Distribuição
21
Modelos
Um objeto de modelo é na verdade um POJO
O modelo pode ser usado como uma
representação da uma entidade do banco de dados
Play! oferece suporte a dois mecanismos de
persistência (ORM):
Ebean
JPA
A configuração padrão usa Ebean ORM
22
Modelos
Criando nosso objeto de modelo
public class Tarefa {public Integer id;public String descricao;
public static List<Tarefa> readAll() { return new ArrayList<Tarefa>();}
public static void create(Tarefa bean) {}
public static void delete(Integer id) {}
}
23
Modelos
Por padrão Play! usa o banco H2 embarcado
Para utilizarmos o MySQL5, precisamos do driver
Edite o arquivo project/Build.scala
val appDependencies = Seq( “mysql” % “mysqlconnectorjava” % “5.1.25”, javaCore, javaJdbc, JavaEbean)
24
Modelos
Configurando nossa conexão com banco de dados
Edite o arquivo conf/application.conf
db.default.driver=”com.mysql.jdbc.Driver”db.default.url=”jdbc:mysql://localhost/play”db.default.user=rootdb.default.password=”admin123”
Para ativar o controle do Ebean, devemos descomentar
ebean.defaults=”models.*”
Precisamos transformar nosso modelo numa entidade persistente
25
Modelos
Adaptando nossa classe de modelo
@Entitypublic class Tarefa extends Model {
@Idpublic Integer id;
@Column(length=35)public String descricao;
public static Finder<Integer,Tarefa> finder = new Finder(Integer.class, Tarefa.class);
...}
26
Modelos
Implementando os métodos de persistência
@Entitypublic class Tarefa extends Model {
... public static List<Tarefa> readAll() { return finder.all(); }
public static void create(Tarefa bean) { bean.save(); }
public static void delete(Integer id) { finder.ref(id).delete(); }
}
27
Modelos
Para suporte a transações devemos usar a anotação @Transactional
public class TarefaController extends Controller {
@play.db.ebean.Transactional public static void criar() { ... }
}
Devemos usar a anotação @Transactional quando temos operações de escrita Em operações de leitura devemos usar o atributo readOnly=true na anotação @Transactional
28
Agenda
Arquitetura de Componentes
Estrutura da Aplicação
Rotas e Controladores
Modelos
Views
Segurança
Distribuição
29
Views
Uma é um template de página HTML com código de
script Scala
Todo template é compilado em byte code
Todo template deve estar contido na pasta views Todo template deve ter a extensão .scala.html
Play! ainda não possui uma biblioteca de
componentes visuais para criação de interfaces
gráficas
30
Views
Vejamos o template da view →app/views/index.scala.html
@(message: String)
@main(“Welcome Play 2.0”) {
@play20.welcome(message)
}
Neste caso estamos criando uma view, baseada
numa página de layout padrão main.scala.html
31
Views
Templates podem receber parâmetros de qualquer
tipo de dados Usamos o caracter especial @ para informar comando
Scala no template
Em nosso exemplo anterior, estamos passando um
parâmetro do tipo String, na variável message
@(message: String)
32
Views
O mecanismo de templates do Play! nos permite
reutilizar outros templates views bases para as páginas da aplicação
Em nosso exemplo anterior, estamos usando o
template main.scala.html como base da nossa
página
33
Views
Vejamos o código do template index.scala.html@(title: String)(content: Html)<!DOCTYPE html><html><head> <title>@title</title> <link rel="stylesheet" media="screen" href="@routes.Assets.at("css/main.css")"> <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")"> <script type="text/javascript" src="@routes.Assets.at("javascripts/jquery1.9.0.min.js")"></script></head><body> @content</body></html>
34
Views
@(tasks: List[Tarefa], taskForm: Form[Tarefa])
@import helper._
@main("Lista de Tarefas") {
<h1>@tasks.size() tarefa(s)</h1>
<ul>
@for(task < tasks) {
<li>
@task.descricao
@form(routes.TarefaController.excluir(task.id)) {
<input type="submit" value="Delete">
}
</li>
}
</ul>
}
35
Views
No template anterior criamos um código para exibir uma lista de tarefas, bem simples Nosso template recebe dois parâmetros
uma lista de tarefas um objeto Form, baseado em nosso modelo@(tasks: List[Tarefa], taskForm: Form[Tarefa])
Logo após realizamos a importação de helpers @import helper._
Depois usamos um comando @for() padrão para exibir os itens da coleção tasks
36
Views
● Para completar nosso template, adicionamos o código a seguir: <h2>Criar tarefa</h2>
@form(routes.TarefaController.criar()) {
@inputText(taskForm("descricao"))
<input type="submit" value="Create">
}
No trecho acima criamos um formulário usando o helper @form() O helper recebe como argumento a rota da ação que deverá ser invocada, quando o formulário for submetido Também usamos o helper @inputText() para criar uma caixa de texto baseada num campo do formulário
37
Views
Implementando o método de ação lista()
public class TarefaController extends Controller { static Form<Tarefa> taskForm = Form.form(Tarefa.class);
// exibe a pagina index.scala.html passando dois // parametros: List<Tarefa> e Form<Tarefa> public static Result lista() { return ok(views.html.index .render(Tarefa.readAll(), taskForm)); }
...}
38
Views
Implementando o método de ação criar()
public class TarefaController extends Controller {
public static Result criar() { Form<Tarefa> form = taskForm.bindFromRequest(); if (form.hasErrors()) { return badRequest(index.render( Tarefa.readAll(), form)); }
Tarefa.create(form.get()); return redirect(routes.TarefaController.lista()); }
...}
39
Views
Implementando o método de ação excluir()
public class TarefaController extends Controller {
public static Result excluir(Integer id) { Tarefa.delete(id); return redirect(routes.TarefaController.lista()); }
}
40
Views
Podemos utilizar qualquer dado armazenado na sessão
do usuário para renderizar na view
public class TarefaController extends Controller { public static Result showInfo() { session(“usuario”, “Administrador”); session(“email”, “[email protected]”); return ok(views.html.showUserInfo()); }}
// na view teremos@main(“Sample”) { Usuario: @session(“usuario”) <br/> Email.: @session(“email”)}
41
Views
Devemos observar alguns pontos quanto ao uso da sessão numa aplicação Play:
Os dados não são armazenados no servidor Os dados são armazenados localmente via cookie Os coolies são assinados com chave secreta que não
permite visualizar seu conteúdo Só podemos armazenar dados do tipo String A sessão não expira, ou seja, não possui timeout
42
Views
Existem formulários que não estão associados a modelos de dados
Estes formulários são dinâmicos
public static Result authenticate() {
DynamicForm dataForm = Form.form().bindFromRequest();
String username = dataForm.get(“username”);
String password = dataForm.get(“password”);
// alguma validacao
return redirect(views.html.dashboard.render());
}
43
Agenda
Arquitetura de Componentes
Estrutura da Aplicação
Rotas e Controladores
Modelos
Views
Segurança
Distribuição
44
Segurança
Criamos um mecanismo de segurança util e simples
usando a classe Authenticator
import play.mvc.Security;
public class Secured extends Security.Authenticator {
public String getUsername(Context ctx) { return ctx.session().get(“username”); }
public Result onUnauthorized(Context ctx) { return redirect(routes.LoginController.form()); }}
45
Segurança
Usamos a anotação @Authenticated para proteger
nossos controladores ou métodos de ação
import play.mvc.Security;
@Security.Authenticated(Secured.class)public class Application extends Controller { ...}
public class Application extends Controller {
@Security.Authenticated(Secured.class) public static Result admin() { ... }}
46
Agenda
Arquitetura de Componentes
Estrutura da Aplicação
Rotas e Controladores
Modelos
Views
Segurança
Distribuição
47
Distribuição
Play suporta dois tipos de distribuição: Distribuição direta via runtime Distribuição via WAR (container JavaEE)
Para distribuirmos uma aplicação Play de forma direta, precisamos gerar seu runtime, através:
$ play clean compile stage
Posteriormente basta executar o script start$ target/start Xms256m Xmx256m Xss1m
Os parâmetros de memória são opcionais
48
Distribuição
Para implantarmos num contaier JavaEE, devemos utilizar
um plugin chamado play2war
https://github.com/dlecan/play2-war-plugin No arquivo project/plugins.sbt adicione a seguinte linha
addSbtPlugin("com.github.play2war" % "play2warplugin" % "1.0")
No arquivo project/Build.scala adicione a seguinte linha
import com.github.play2war.plugin._
49
Distribuição
Ainda no arquivo project/Build.scala adicione a seguinte
linha, nas configurações do projeto adicioneval main = play.Project(appName, appVersion, appDependencies) .settings(Play2WarPlugin.play2WarSettings: _*) .settings( Play2WarKeys.servletVersion := “2.5”, Play2WarKeys.targetName := Some(“tarefas”)
)
No console do Play, digite$ war
Para deploy dentro do Jboss, requer algumas configurações especiais (veja na doc do plugin)
50
Anexo I – Ebean API
Implementando consultas
1. Lista todos os objetos: Aluno.finder.all()
2. Pesquisa pelo ID: Aluno bean = Aluno.finder.byId(5);
3. Pesquisa condicional:Aluno.finder.where() .ilike(“nome”, “%ana%”) .orderBy(“nascimento desc”) .findList();
4. Pesquisa por propriedade:Aluno bean = Aluno.finder.where() .eq(“status”, Status.ATIVO) .orderBy(“nome asc”) .findList();