Vous êtes sur la page 1sur 20

Tutorial Completo de Struts

Neste tutorial irei mostrar como criar um crud utilizando struts, postgres, imprimindo relatrio com ireport, lembrando que estou partindo do ponto de vista que seu jdk,jre estaja configurado em sua mquina. Utilizaremos o netbeans como nossa ide, particularmente eu gosto. Copie esse script para seu postgresql para gerar nossa base de dados. CREATE DATABASE tutorialstruts WITH OWNER = postgres ENCODING = 'UTF8'; CREATE TABLE alunos ( codigo integer NOT NULL, nome character varying(20) NOT NULL, email character varying(50), CONSTRAINT pk_codigo PRIMARY KEY (codigo) ) WITH (OIDS=FALSE); ALTER TABLE alunos OWNER TO postgres; Vamos ento adicionar alguns dados em nossa tabela alunos INSERT INTO alunos (codigo,nome,email) values (1,'aluno1','aluno1@escola.com'); INSERT INTO alunos (codigo,nome,email) values (2,'aluno2','aluno2@escola.com'); INSERT INTO alunos (codigo,nome,email) values (3,'aluno3','aluno3@escola.com'); INSERT INTO alunos (codigo,nome,email) values (4,'aluno4','aluno4@escola.com'); Para criar um projeto voc precisa inicialmente abrir seu netbeans, v em arquivo > novo projeto > em categorias escolha a opo web e em projetos escolha a opo aplicao web> clique em prximo > em nome digite TutorialStruts e escolha o local onde ser salvo seu projeto> clique em prximo > Escolha qual servidor ir usar na sua aplicao irei usar o Tomcat 6.0 > clique em prximo > escolha em framework a opo struts 1.2.9 e clique em finalizar. Seu projeto ser criado e inicializado no netbeans na aba projetos, como escolhemos anteriormente a opo struts 1.2.9 no ser necessrio adicionar nenhuma biblioteca do struts em nossa aplicao. Vamos criar nossar pgina jsp, na pasta pginas web clique com o direito > novo > escolha a opo jsp ira criar uma pgina jsp renomeie ela para index.jsp o cdigo deve ficar como este: <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> <%@ page pageEncoding="UTF-8" %> <html:html> <head> <title>Tutorial de Struts</title> <script type="text/javascript" src="js/geral.js"></script> <head> <body> <html:form action="alunosaction" focus="codigo"> <html:hidden property="operacao" styleId="operacao"/> <table> <tr> <td><bean:message key="label.codigo"/></td> <td><html:text property="codigo"/></td>

</tr> <tr> <td><bean:message key="label.nome"/></td> <td><html:text property="nome"/></td> </tr> <tr> <td><bean:message key="label.email"/></td> <td><html:text property="email"/></td> </tr> </table> <table> <tr> <input type="button" value="<bean:message key="button.gravar"/>" onclick="setOperacao('gravar');AlunosForm.submit();"/> <input type="button" value="<bean:message key="button.alterar"/>" onclick="setOperacao('alterar');AlunosForm.submit();"/> <input type="button" value="<bean:message key="button.excluir"/>" onclick="setOperacao('excluir');AlunosForm.submit();"/> <input type="button" value="<bean:message key="button.consultar"/>" onclick="setOperacao('consultar');AlunosForm.submit();"/> <input type="button" value="<bean:message key="button.listar"/>" onclick="open('/TutorialStruts/listaalunosaction.do','window1','width=500,top=5,left=5,height=500' );"/> </tr> </table> </html:form> </body> </html:html> Crie outro arquivo com o nome listaAlunos.jsp, o cdigo deve ficar assim: <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> <%@ page pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html:html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Lista de Alunos</title> <script type="text/javascript" src="js/geral.js"></script> </head> <body> <center><h1>Lista de Alunos</h1></center> <html:form action="listaalunosaction"> <html:hidden property="operacao" styleId="operacao"/> <table border="1"> <tr> <td>Cdigo</td> <td>Nome</td> <td>E-mail</td>

</tr> <logic:present name="list"> <logic:iterate id="Alunos" name="list"> <tr> <td> <bean:write name="Alunos" property="codigo"/> </td> <td> <bean:write name="Alunos" property="nome"/> </td> <td> <bean:write name="Alunos" property="email"/> </td> </tr> </logic:iterate> </logic:present> </table> <input type="button" value="GERAR RELATRIO" onclick="setOperacao('gerarRelatorios');ListaAlunosForm.submit();"/> </html:form> </body> </html:html> Dentro da pasta pginas web clique com o direito e escolha a opo novo > pacote java, renomeie para js, neste pacote ficar nossos arquivos javascript. Crie dentro do pacote js um arquivo do tipo script para fazer esta opo clique com o direito em cima do pacote js > novo > escolha a opo Arquivo JavaScript, renomeie para geral.js, o cdigo deve ficar assim: function setOperacao(acao){ document.getElementById('operacao').value = acao; } At o momento foi criado duas pginas do tipo jsp e um arquivo do tipo script onde ficar nossas functions, o processo ser da seguinte maneira: o usurio ao clicar no boto ser ativada a function setOperacao(acao) que por sua vez passar um nome que ser o mesmo nome do boto, o mtodo ser executado passando a ao para dentro de um campo do tipo hidden que logo ser submitado levando seu valor para a ActionForm e executado pela action. Dentro do pacote de cdigos-fonte por default tem um pacote com o nome com dentro dela crie os seguinte pacotes: conexao, persistencia, web. Aps criado os pacotes dentro do pacote web, crie os seguinte pacotes: action,form,vo. Iremos agora criar na classe Alunos que nela ter os atributos codigo,nome,email e os mtodos gets e sets de cada atributo, ento dentro do pacote vo, crie um arquivo do tipo classe java renomeie para Alunos.java o cdigo de ficar assim: package com.web.vo; import java.io.Serializable; /** * * @author diogo.soares */ public class Alunos implements Serializable{

private Integer codigo; private String nome; private String email; public Alunos(){} public Integer getCodigo() { return codigo; } public void setCodigo(Integer codigo) { this.codigo = codigo; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } } Criaremos ento o ActionForm que tem a funcionalidade de pegar os valores digitados na pgina aps ser submetida pelo usurio. Dentro do pacote form crie um arquivo do tipo classe java, renomeie para AlunosForm, o cdigo de ficar assim: package com.web.form; import com.web.vo.Alunos; import org.apache.struts.action.ActionForm; /** * * @author diogo.soares */ public class AlunosForm extends ActionForm{ private Alunos alunos; private Integer codigo; private String nome; private String email; private String operacao;

public Alunos getAlunos() { return alunos; } public void setAlunos(Alunos alunos) { this.alunos = alunos; } public Integer getCodigo() { return codigo; } public void setCodigo(Integer codigo) { this.codigo = codigo; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getOperacao() { return operacao; } public void setOperacao(String operacao) { this.operacao = operacao; } } Repita o passo solicitado acima renomeando o arquivo para ListaAlunosForm, o cdigo deve ficar assim: package com.web.form; import com.web.vo.Alunos; import org.apache.struts.action.ActionForm; /** * * @author diogo */

public class ListaAlunosForm extends ActionForm{ private Integer codigo; private String nome; private String email; private String operacao; Alunos alunos; public Alunos getAlunos() { return alunos; } public void setAlunos(Alunos alunos) { this.alunos = alunos; } public Integer getCodigo() { return codigo; } public void setCodigo(Integer codigo) { this.codigo = codigo; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getOperacao() { return operacao; } public void setOperacao(String operacao) { this.operacao = operacao; } } Criaremos agora nossas actions que serve como engrenagem principal para nossa aplicao, action geralmente existente para cada form, seguindo no necessariamente uma ordem

de: vo > form > action > para cada jsp (isso no padro). Crie dentro do pacote action uma classe java, renomeie para AlunosAction, o cdigo deve ficar assim: package com.web.action; import com.conexao.Conexao; import com.persistencia.service.AlunosService; import com.web.form.AlunosForm; import com.web.vo.Alunos; import java.sql.SQLException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; /** * * @author diogo.soares */ public class AlunosAction extends org.apache.struts.action.Action { private final static String SUCCESS = "success"; private Conexao con = new Conexao(); private Alunos alunos = new Alunos(); @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { con.getConnection(); AlunosForm alunosForm = (AlunosForm) form; BeanUtils.copyProperties(alunos, alunosForm); if(alunosForm.getOperacao().equals("gravar")){ gravar(); } if(alunosForm.getOperacao().equals("alterar")){ alterar(); } if(alunosForm.getOperacao().equals("excluir")){ excluir(); } if(alunosForm.getOperacao().equals("consultar")){ BeanUtils.copyProperties(alunosForm,consultar()); } con.Commit(); con.closeConnection();

return mapping.findForward(SUCCESS); } public String gravar(){ AlunosService alunosService = new AlunosService(); Alunos alunosVO = alunosService.insertAlunos(alunos); return SUCCESS; } public String alterar(){ AlunosService alunosService = new AlunosService(); Alunos alunosVO = alunosService.alterarAlunos(alunos); return SUCCESS; } public String excluir(){ AlunosService alunosService = new AlunosService(); Alunos alunosVO = alunosService.excluirAlunos(alunos); return SUCCESS; } public Alunos consultar() throws SQLException{ AlunosService alunosService = new AlunosService(); Alunos alunosVO = alunosService.consultarAlunos(alunos); return alunosVO; } } Faa o mesmo renomeando o arquivo para ListaAlunosAction, o cdigo deve ficar assim: package com.web.action; import com.conexao.Conexao; import com.persistencia.service.AlunosService; import com.web.form.ListaAlunosForm; import com.web.vo.Alunos; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.jasperreports.engine.JasperExportManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.data.JRBeanArrayDataSource; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; /** * * @author diogo */ public class ListaAlunosAction extends Action{ private final static String SUCCESS = "success"; private Conexao con = new Conexao(); private Alunos alunos = new Alunos(); @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ListaAlunosForm listaAlunosForm = (ListaAlunosForm) form; con.getConnection(); AlunosService alunosService = new AlunosService(); List<Alunos> list = alunosService.selectAlunos(alunos); request.setAttribute("list", list); if(listaAlunosForm.getOperacao() != null){ /////////////////////////////Relatorios///////////////////////////// String pathJasper = getServlet().getServletContext().getRealPath("/relatorios/") + "/"; String pathImages = getServlet().getServletContext().getRealPath("/relatorios/") + "/"; String path = getServlet().getServletContext().getRealPath("/"); Map parametros = new HashMap(); parametros.put("SUBREPORT_DIR", pathJasper); parametros.put("IMAGES_URI", pathJasper); try { JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(list); JasperPrint impressao = JasperFillManager.fillReport(pathJasper + "/Alunos.jasper", parametros, ds); byte[] bytes = JasperExportManager.exportReportToPdf(impressao); byte[] arquivo = bytes; String nomeDoArquivo = "Alunos.pdf"; response.setContentType("application/x-msdownload"); response.setHeader("Content-Disposition", "attachment;

filename=".concat(nomeDoArquivo)); response.setContentLength(arquivo.length); ServletOutputStream sos = response.getOutputStream(); sos.write(arquivo, 0, arquivo.length); sos.flush(); sos.close(); } catch (Exception e) { if(e.getClass().getSimpleName().equals("AbortException")){ System.out.println("Documento cancelado"); } else{ System.out.println("Outros"); } } } con.closeConnection(); return mapping.findForward(SUCCESS); } } Para que nossa aplicao possa rodar sem problemas teremos que configurar os famosos struts-config.sml e o web.xml. Dentro da pasta WEB-INF altere o contedo do struts-config para: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="AlunosForm" type="com.web.form.AlunosForm"/> <form-bean name="ListaAlunosForm" type="com.web.form.ListaAlunosForm"/> </form-beans> <global-exceptions> </global-exceptions> <global-forwards> </global-forwards> <action-mappings> <action input="/index.jsp" name="AlunosForm" path="/alunosaction" scope="request" type="com.web.action.AlunosAction"> <forward name="success" path="/index.jsp"/> <forward name="error" path="/error.jsp"/> </action> <action input="/listaAlunos.jsp" name="ListaAlunosForm" path="/listaalunosaction" scope="request" type="com.web.action.ListaAlunosAction"> <forward name="success" path="/listaAlunos.jsp"/> <forward name="error" path="/error.jsp"/> </action> </action-mappings> <controller processorClass="org.apache.struts.tiles.TilesRequestProcessor"/> <message-resources parameter="com/myapp/struts/ApplicationResource"/> <plug-in className="org.apache.struts.tiles.TilesPlugin" >

<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /> <set-property property="moduleAware" value="true" /> </plug-in> <!-- ========================= Validator plugin ================================= --> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in> </struts-config> E altere tambm o web.xml para: <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/webapp_2_5.xsd"> <resource-ref> <res-ref-name> jdbc/tutorialstruts </res-ref-name> <res-type> javax.sql.DataSource </res-type> <res-auth> Container </res-auth> </resource-ref> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>

<session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> Aproveitando o embalo dento da pasta META-INF altere o contedo do context.xml que servir para conectarmos nosso banco de dados, este tipo de conexao chama-se JNDI: <?xml version="1.0" encoding="UTF-8"?> <Context path="/TutorialStruts"> <Resource auth="Container" name="jdbc/tutorialstruts" type="javax.sql.DataSource" url="jdbc:postgresql://localhost:5432/tutorialstruts" driverClassName="org.postgresql.Driver" username="postgres" password="postgres" maxActive="20" maxIdle="5"/> </Context> Abra o pacote com > conexao > crie um arquivo do tipo classe java, renomeie para Conexao.java, o contedo deve ficar assim: package com.conexao; import java.sql.Connection; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.InitialContext; import javax.sql.DataSource; /** * * @author diogo.soares */ public class Conexao { public static Connection con public Conexao(){} public void getConnection(){ try{ // Obtm a raiz da hierarquia de nomes InitialContext contexto = new InitialContext(); = null;

// Obtm a origem dos dados DataSource ds = (DataSource)contexto.lookup("java:comp/env/jdbc/tutorialstruts"); // Obtm uma conexo con = ds.getConnection(); // Retorna a conexo }catch(Exception e){ System.out.println("Erro na conexao " +e); } } public void Commit(){ if (con != null){ try { con.commit(); } catch (SQLException ex) { Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex); } } } public void Rollback(){ if (con != null){ try { con.rollback(); } catch (SQLException ex) { Logger.getLogger(Conexao.class.getName()).log(Level.SEVERE, null, ex); } } } public void closeConnection() { try { System.out.print(" Closing Connection...\n"); con.close(); } catch (SQLException e) { e.printStackTrace(); } } } Dentro do pacote com > myapp > struts > altere o contedo do arquivo ApplicationResource para: #########LABELS########### label.codigo=CODIGO: label.nome=NOME: label.email=E-MAIL: #########BUTTONS########## button.gravar=GRAVAR button.alterar=ALTERAR button.excluir=EXCLUIR

button.consultar=CONSULTAR button.listar=LISTAR Dentro do pacote com > persistencia > crie outro pacote com o nome service, dentro do service crie um arquivo do tipo classe java, renomeie para AlunosService, o contedo deve ficar assim: package com.persistencia.service; import com.conexao.Conexao; import com.persistencia.AlunosPersistence; import com.web.vo.Alunos; import java.sql.Connection; import java.util.List; /** * * @author diogo.soares */ public class AlunosService { Conexao conexao = new Conexao(); public Connection connection = Conexao.con; private AlunosPersistence alunosPersistence = new AlunosPersistence(connection); public Alunos insertAlunos(Alunos alunos){ return alunosPersistence.insertAlunos(alunos); } public Alunos alterarAlunos(Alunos alunos){ return alunosPersistence.alterarAlunos(alunos); } public Alunos excluirAlunos(Alunos alunos){ return alunosPersistence.excluirAlunos(alunos); } public Alunos consultarAlunos(Alunos alunos){ return alunosPersistence.consultarAlunos(alunos); } public List<Alunos> selectAlunos(Alunos alunos){ return alunosPersistence.selectAlunos(alunos); } } Dentro da pasta com > persistencia > crie um aquivo do tipo classe java, renomeie para AlunosPersistence, o conteudo deve ficar assim: package com.persistencia; import com.web.vo.Alunos; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet;

import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * * @author diogo.soares */ public class AlunosPersistence { private PreparedStatement ps; private Connection con; public AlunosPersistence(Connection connection){ this.con = connection; } public Alunos insertAlunos(Alunos alunos){ try { ps = con.prepareStatement( "INSERT INTO alunos (codigo,nome,email) values (?,?,?)" ); ps.setInt(1, alunos.getCodigo()); ps.setString(2, alunos.getNome()); ps.setString(3, alunos.getEmail()); ps.execute(); ps.close(); } catch (SQLException e) { e.printStackTrace(); } return alunos; } public Alunos alterarAlunos(Alunos alunos){ try { ps = con.prepareStatement( "UPDATE alunos SET nome = ?, email = ? WHERE codigo = ?" ); ps.setString(1, alunos.getNome()); ps.setString(2, alunos.getEmail()); ps.setInt(3, alunos.getCodigo()); ps.execute();

ps.close(); } catch (SQLException e) { e.printStackTrace(); } return alunos; } public Alunos excluirAlunos(Alunos alunos){ try { ps = con.prepareStatement( "DELETE FROM alunos WHERE codigo = ?" ); ps.setInt(1, alunos.getCodigo()); ps.execute(); ps.close(); } catch (SQLException e) { e.printStackTrace(); } return alunos; } public Alunos consultarAlunos(Alunos alunos){ ResultSet listaAlunos = null; Alunos a = new Alunos(); try { ps = con.prepareStatement( "SELECT * FROM alunos WHERE codigo = ?" ); ps.setInt(1, alunos.getCodigo()); listaAlunos = ps.executeQuery(); while(listaAlunos.next()){ a.setCodigo(listaAlunos.getInt(1)); a.setNome(listaAlunos.getString(2)); a.setEmail(listaAlunos.getString(3)); } ps.close();

} catch (SQLException e) { e.printStackTrace(); } return a; } public List<Alunos> selectAlunos(Alunos alunos){ ResultSet listaAlunos = null; List<Alunos> list = new ArrayList<Alunos>(); try { ps = con.prepareStatement( "SELECT * FROM alunos" ); listaAlunos = ps.executeQuery(); while(listaAlunos.next()){ Alunos a = new Alunos(); a.setCodigo(listaAlunos.getInt(1)); a.setNome(listaAlunos.getString(2)); a.setEmail(listaAlunos.getString(3)); list.add(a); } ps.close(); } catch (SQLException e) { e.printStackTrace(); } return list; } } Para finalizar vou mostrar como fazer um relatrio usando o ireport 3.0. Crie um pacote dentro de Pginas web e renomeie para relatorios neste pacote vc deve salvar o arquivo do ireport com extenso .jrxml e as compilaes do .jasper. Abrindo o ireport v no menu data > conexoes / banco de dados > Crie uma nova conexao com os dados do nosso banco postgresql(tutorialstruts). Vamos criar nosso relatrio, v no menu arquivo > novo documento > coloque o nome do relatrio para Alunos e salve dentro da pasta relatorios criada no netbeans anteriomente. Aps criado a nossa pgina v no menu data > query do relatorio digite SELECT * FROM alunos, logo abaixo mostrar as colunas criadas no banco de dados que so codigo,nome,email, clique em ok. Na esquerda da tela na aba Estrutura do documento clique em campos, voc ver as colunas do banco depois s arrastar para a pgina e pronto, clique no menu criar(build) > compilar se no houver nenhum erro mostrar abaixo da tela a mensagem de sucesso, clique no menu criar(build) > executar relatrio (usar conexao ativa), depois s visualizar a lista de dados na tela.

Em nossa action ListarAlunosAction tem o mtodo que faz o java se conectar com o ireport, convertendo os dados em bytes e gerando um pdf podendo abrir ou salvar em sua mquina, no esquecendo de adicionar no projeto as bibliotecas commons-beanutils, commons-collections, commons-logging-api, iReport, jasperreports que se encontram dentro da pasta do ireport no diretrio C:\Arquivos de programas\JasperSoft\iReport-3.0.0\lib o .jar do postgresql deve estar dentro desta pasta para perfeito funcionamento do relatrio. Clique com o direito no projeto e escolha a opo Desimplantar e implantar, rode o sistema digitando no browser http://localhost:8080/TutorialStruts/.

Galera neste tutorial no visei explicar conceitos e sim mostrar como criar um crud rpido usando tcnicas do struts gerando um relatrio com ireport, listando dados em uma tabela abrir uma pgina estilo pop-up. Este o meu primeiro tutorial ento peo a compreenso de todos vocs pelos erros ou falta de detalhes, peo a sugesto para melhorar os demais. Muito obrigado pela oportunidade e at a prxima.

Vous aimerez peut-être aussi