Вы находитесь на странице: 1из 10

CAPÍTULO 1

APLICAÇÕES DO MODELO 2

Como explicado na Introdução, o modelo 2 é a arquitetura recomenda-


da para todas aplicações web em Java, exceto as mais simples. Este
capítulo discute o Modelo 2 detalhadamente e fornece duas aplicações
exemplo do Modelo 2. Um grande entendimento deste modelo de projeto
é crucial para entender Struts e construir aplicações Struts efetivas.

VISÃO GERAL DO MODELO 2


O Modelo 2 é baseado no padrão de projeto Model-View-Controller
(MVC), o conceito central por trás da interface de usuário Smalltalk-80.
Como o termo “padrão de projeto” não tinha sido inventado ainda naquele
tempo, foi chamado de paradigma MVC.
Uma aplicação implementando o padrão MVC consiste em três módulos:
a camada de negócios (Model), a camada de apresentação (View) e a
camada de controle (Controller). A camada de apresentação cuida da
exibição da aplicação. A camada de negócios encapsula os dados da
aplicação e a lógica de negócio. A camada de controle (o controlador)
recebe entrada do usuário e comanda o modelo e/ou a aplicação para
alterarem de acordo.
2 STRUTS 2 PROJETO E PROGRAMAÇÃO: UM TUTORIAL

Nota
A publicação entitulada Applications Programming in Smalltalk-80(TM): How to
use Model-View-Controller (MVC) por Steve Burbeck, Ph.D, fala sobre o padrão
MVC. Você pode encontrá-la em http://st-www.cs.uiuc.edu/users/smarch/st-
docs/mvc.html.

No modelo 2, você tem um servlet ou um filtro agindo como o


controlador do padrão MVC. Struts 1 emprega um controlador servlet, ao
passo que o Struts usa um filtro. Geralmente JavaServer Pages (JSP) são
usados como apresentações da aplicação, mesmo que outras tecnologias
de apresentação sejam suportadas. Como os modelos, você utiliza
POJOs (POJO é um acrônimo para Plain Java Old Object). POJOs são
objetos comuns, diferente de Entreprise java Beans ou outros objetos
especiais.
A figura 1.1 mostra o diagrama de uma aplicação do Modelo 2:

Figura 1.1: Arquitetura do Modelo 2

Em uma aplicação do Modelo 2, cada requisição HTTP deve ser


redirecionada ao controlador. A Uniform Request Identifier (URI) da
requisição informa ao controlador qual action (Ação) invocar. O termo
“action” refere-se a uma operação que a aplicação é capaz de desempe-
nhar. O POJO associado a uma action é chamado de objeto action. Em
Struts 2, como você irá descobrir mais tarde, uma classe action pode ser
usada para servir diferentes actions. Em contrapartida, Struts 1 impõe que
você crie uma classe action para cada action individual.
CAPÍTULO 1 – APLICAÇÕES DO MODELO 2 3

Uma função trivial similar pode usar mais de uma action. Por exemplo,
adicionar um produto poderia requerer duas actions:
1. Mostrar o formulário “Adicionar Produto”, para entrar com as
informações do produto.
2. Salvar o dado em uma base de dados.
Como mencionado acima, você usa a URI para informar ao controlador
qual action invocar. Por exemplo, para fazer com que a aplicação envie o
formulário “Adicione Produto”, você deverá usar a seguinte URI:

http://domain/appName/Product_input.action

Para fazer com que a aplicação salve o produto, a URI poderia ser:

http://domain/appName/Product_save.action

O controlador verifica cada URI para decidir qual action invocar. Ele
também armazena o objeto action em um local que possa ser acessado pela
apresentação, tal que valores do lado do servidor possam ser mostrados no
navegador. Finalmente, o controlador usa um objeto RequestDispatcher,
para encaminhar a requisição à camada de apresentação (JSP). No JSP,
você pode usar custom tags para mostrar o conteúdo de um objeto action.
Nas próximas duas seções, eu apresento duas aplicações simples do
Modelo 2. A primeira usa um servlet como o controlador e a segunda usa
um filtro.

O MODELO 2 COM UM CONTROLADOR SERVLET


A aplicação pode ser usada para entrar informações do produto e é
denominada app01a. O usuário irá preencher um formulário, como o
mostrado na Figura 1.2, e submetê-lo. A aplicação irá, então, enviar uma
página de confirmação ao usuário e irá exibir os detalhes do produto salvo.
(ver Figura 1.3)
4 STRUTS 2 PROJETO E PROGRAMAÇÃO: UM TUTORIAL

Figura 1.2: O formulário Product

Figura 1.3: Página de detalhes do produto

A aplicação é capaz de desempenhar essas duas actions:


1. Mostrar o formulário “Adicione Produto”. Essa action envia o
formulário de entrada na Figura 1.2 ao navegador. A URI para
invocar essa action deve conter a string Product_input.action.
CAPÍTULO 1 – APLICAÇÕES DO MODELO 2 5

2. Salvar o produto e retornar à página de confirmação na Figura 1.3.


A URI a invocar essa action deve conter a string
Product_save.action.
A aplicação consiste dos seguintes componentes:
1. uma classe Product, que é o template para os objetos action. Uma
instância desta classe contém informação do produto.
2. uma classe ControllerServlet, que é o controlador dessa aplicação
do Modelo 2.
3. dois JSPs (ProductForm.jsp e ProductDetails.jsp), como as apre-
sentações.
4. um arquivo CSS que define o estilo das apresentações. Esse é um
recurso estático.
A estrutura de diretórios dessa aplicação é mostrada na Figura 1.4

Figura 1.4: Estrutura de diretório app01a

Vamos dar uma olhada mais detalhada em cada componente de


app01a.

A Classe Action de Product


Uma instância de Product é um POJO que encapsula informação do
produto. A classe Product (mostrada na Listagem 1.1) tem três proprieda-
des: productName, description e price. Ela tem também um método,
save.
6 STRUTS 2 PROJETO E PROGRAMAÇÃO: UM TUTORIAL

Listagem 1.1: a Classe Product

package app01a;
import java.io.Serializable;

public class Product implements Serializable {


private String productName;
private String description;
private String price;

public String getProductName() {


return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String save() {
// add here code to save the product to the database
return “success”;
}
}

A Classe ControllerServlet
A classe ControllerServlet (apresentada na Listagem 1.2) estende a
classe javax.servlet.http.HttpServlet. Ambos os métodos, doGet e doPost,
chamam o método process, que é o cérebro do controlador servlet. Sei que
é um pouco estranho que a classe para um controlador servlet deva ser
chamada ControllerServlet, mas estou seguindo a convenção que diz que
todas as classes de servlet devam terminar com Servlet.
CAPÍTULO 1 – APLICAÇÕES DO MODELO 2 7

Listagem 1.2: a Classe ControllerServlet

package app01a;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ControllerServlet extends HttpServlet {


public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
process(request, response);
}

public void doPost(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {
process(request, response);
}

private void process(HttpServletRequest request,


HttpServletResponse response)
throws IOException, ServletException {

String uri = request.getRequestURI();


/*
* uri está na forma: /contextName/resourceName,
* por exemplo: /app01a/Product_input.action.
* Entretanto, no caso de um contexto default, o
* nome do contexto está vazio, e uri tem essa forma
* /resourceName, e.g.: /Product_input.action
*/
int lastIndex = uri.lastIndexOf(“/”);
String action = uri.substring(lastIndex + 1);
// executa uma action
if (action.equals(“Product_input.action”)) {
// não há nada a ser feito
} else if (action.equals(“Product_save.action”)) {
// instancia a classe action
Product product = new Product();
// preenche as propriedades da action
product.setProductName(
request.getParameter(“productName”));
8 STRUTS 2 PROJETO E PROGRAMAÇÃO: UM TUTORIAL

product.setDescription(
request.getParameter(“description”));
product.setPrice(request.getParameter(“price”));
// executa o método action
product.save();
// armazena action numa variável de escopo para a cama-
da de apresentação
request.setAttribute(“product”, product);
}

// encaminha para a camada de apresentação


String dispatchUrl = null;
if (action.equals(“Product_input.action”)) {
dispatchUrl = “/jsp/ProductForm.jsp”;
} else if (action.equals(“Product_save.action”)) {
dispatchUrl = “/jsp/ProductDetails.jsp”;
}
if (dispatchUrl != null) {
RequestDispatcher rd =
request.getRequestDispatcher(dispatchUrl);
rd.forward(request, response);
}
)
}

O método process na classe ControllerServlet processa todas as


requisições que chegam. Ele começa obtendo a requisição URI e o nome
da action.

String uri = request.getRequestURI();


int lastIndex = uri.lastIndexOf(“/”);
String action = uri.substring(lastIndex + 1);

O valor de action na aplicação tanto pode ser Product_input.action


quanto Product_save.action.

Nota
A extensão.action em cada URI é a extensão default usada em Struts 2 e, portanto,
usada aqui.
CAPÍTULO 1 – APLICAÇÕES DO MODELO 2 9

O método process, então, continua a desempenhar estes passos:


1. Instancia a classe action relevante, se existe.
2. Se existe um objeto action, ele preenche as propriedades de action
com parâmetros da requisição. Há três propriedades na action
Product_save: productName, description, e price.
3. Se um objeto action existe, chama o método action. Neste exemplo,
o método save no objeto Product é o método de action para a action
Product_save.
4. Encaminha a requisição para a camada de apresentação (JSP).
A parte do método process que determina qual action desempenhar
está no bloco if abaixo:

// executa uma action


if (action.equals(“Product_input.action”)) {
// não há nada a ser feito
} else if (action.equals(“Product_save.action”)) {
// instancia classe action
...
}

Não há classe action para instanciar para a action Product_input. Para


Product_save, o método process cria um objeto Product, preenche suas
propriedades, e chama seu método save.

Product product = new Product();


// preenche as propriedades de action
product.setProductName(
request.getParameter(“productName”));
product.setDescription(
request.getParameter(“description”));
product.setPrice(request.getParameter(“price”));
// executa o método action
Product.save();
// armazena action em uma variável de escopo para a camada
de apresentação
request.setAttribute(“product”, product);
}

O objeto Product é então armazenado no objeto HttpServletRequest,


para que, então, a camada de apresentação possa acessá-lo.
10 STRUTS 2 PROJETO E PROGRAMAÇÃO: UM TUTORIAL

O método process conclui ao encaminhar para a uma camada de


apresentação. Se action é o mesmo que Product_input.action, o controle
é encaminhado à página ProductForm.jsp. Se action é
Product_save.action, o controle é encaminhado à página
ProductDetails.jsp.

// encaminha a uma camada de apresentação forward to a view


String dispatchUrl = null;
if (action.equals(“Product_input.action”)) {
dispatchUrl = “/jsp/ProductForm.jsp”;
} else if (action.equals(“Product_save.action”)) {
dispatchUrl = “/jsp/ProductDetails.jsp”;
}
if (dispatchUrl != null) {
RequestDispatcher rd =
request.getRequestDispatcher(dispatchUrl);
rd.forward(request, response);
}

As Camadas de Apresentação
A aplicação utiliza duas JSPs para as camadas de apresentação da
aplicação. O primeiro JSP, ProductForm.jsp, é exibido se a action for
Product_input.action. A segunda página, ProductDetails.jsp, é mostra-
da para Product_save.action. ProductForm.jsp é dado na Listagem 1.3
e ProductDetails.jsp, na Listagem 1.4.

Listagem 1.3: a Página ProductForm.jsp

<html>
<head>
<title>Add Product Form</title>
<style type=”text/css”>@import url(css/main.css);</style>
</head>
<body>
<div id=”global”>
<h3>Add a product</h3>
<form method=”post” action=”Product_save.action”>
<table>
<tr>
<td>Product Name:</td>
<td><input type=”text” name=”productName”/></td>
</tr>

Вам также может понравиться