Você está na página 1de 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

A camada de negócios encapsula os dados da

aplicação e a lógica de negócio. A camada de controle (o controlador)

exibição da aplicação.

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 mostra o diagrama de uma aplicação do Modelo 2: Figura 1.1: Arquitetura do Modelo

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

4 S TRUTS 2 P ROJETO E P ROGRAMAÇÃO : U M T UTORIAL Figura 1.2:

Figura 1.2: O formulário Product

: U M T UTORIAL Figura 1.2: O formulário Product Figura 1.3: Página de detalhes do

Figura 1.3: Página de detalhes do produto

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

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

de diretórios dessa aplicação é mostrada na Figura 1.4 Figura 1.4: Estrutura de diretório app01a Vamos

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>