450 likes | 575 Views
Java para Web com Struts. Danilo Toshiaki Sato dtsato@ime.usp.br Treinamento ALESP – SPL Módulo II. Agenda - Módulo II. Recapitulando... Construindo o Model JavaBeans e escopo ActionForm DTO Lógica de negócio Construindo o Controller O ActionServlet O ActionMapping
E N D
Java para Web com Struts Danilo Toshiaki Sato dtsato@ime.usp.br Treinamento ALESP – SPL Módulo II
Agenda - Módulo II • Recapitulando... • Construindo o Model • JavaBeans e escopo • ActionForm • DTO • Lógica de negócio • Construindo o Controller • O ActionServlet • O ActionMapping • O ActionForward • A Action Copyleft 2006 Danilo Sato
Recapitulando... • Fluxo Básico de Controle Model Controller Copyleft 2006 Danilo Sato
Construindo o Model • JavaBeans e escopo: • Numa aplicação web, os JavaBeans podem ser armazenados em diferentes escopos: • page: Beans visíveis apenas na página JSP (Variáveis locais no service()) • request: Beans visíveis na página JSP e qualquer outra página ou Servlet incluído ou encaminhado a partir dessa página (atributos do HttpServletRequest) • session: Beans visíveis em todos os Servlets e JSPs que participam de uma determinada sessão de usuário (atributos da HttpSession) Copyleft 2006 Danilo Sato
Construindo o Model • application: Beans visíveis em todos os Servlets e JSPs de uma mesma aplicação web (atributos do ServletContext) • Exemplo: • Bean armazenado no request pelo Servlet: • Pode ser usado imediatamente num JSP encaminhado pelo Servlet: MyCart myCart = new MyCart(...); request.setAttribute("cart", myCart); <jsp:useBeanid="cart"scope="request"class="com.mycompany.myApp.MyCart"/> Copyleft 2006 Danilo Sato
Construindo o Model • ActionForm • É um tipo especial de JavaBeans • Utilizado para armazenar os dados de entrada digitados pelo usuário num formulário HTML • Pode ser usado pelas Tags do Struts para mostrar os valores previamente digitados pelo usuário no caso de erro • Validação automática dos campos • Populado automaticamente pelo Struts Copyleft 2006 Danilo Sato
Construindo o Model • Para criar um ActionForm você deve: • Estender a classe org.apache.struts.action.ActionForm • Definir uma propriedade pública para cada campo do formulário HTML que será enviado na requisição HTTP • OBS: Nesse contexto, considere “propriedade pública” como uma propriedade JavaBean (métodos getter e setter) Copyleft 2006 Danilo Sato
Construindo o Model • Ao criar um ActionForm você pode: • Sobrescrever o método validate() para validação dos campos de entrada do formulário • Sobrescrever o método reset() para limpar e inicializar os dados de um ActionForm Copyleft 2006 Danilo Sato
Construindo o Model • O papel do ActionForm no ciclo de uma requisição: • O controlador do Struts recebe uma requisição HTTP com parâmetros do formulário HTML • O controlador busca o ActionMapping associado à URL requisitada • O ActionMapping define o ActionForm e o Action associados à requisição • O controlador verifica se uma instância do ActionForm já existe no escopo configurado • Se a instância não existe, ela é criada e armazenada no escopo correspondente Copyleft 2006 Danilo Sato
Construindo o Model • O método reset() é chamado (implementação padrão não faz nada) • Para cada parâmetro HTTP cujo nome corresponde à uma propriedade do Bean, o método setter correspondente será chamado • O método validate() é chamado se o valor do atributo "validate" não for "false" no ActionMapping • Caso o ActionForm encontre erros de validação, ActionErrors são armazenados no request e o controle é encaminhado para o formulário de entrada (atributo "input" do ActionMapping) • Caso não haja erros, o fluxo é encaminhado para a Action atrávés do método execute() Copyleft 2006 Danilo Sato
Construindo o Model • Exemplo: ActionForm simples package app; import org.apache.struts.action.*; public class MeuForm extends ActionForm { private String nome = null; public String getNome() { returnthis.nome; } public void setNome(String nome) { this.nome = nome; } // Método validate() ... // Método reset() ... } Copyleft 2006 Danilo Sato
Construindo o Model • Exemplo: Método validate() // (...) // Valida se nome não é nulo nem vazio public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (nome == null || nome.trim().length() == 0) { errors.add("nome", new ActionError("erro.nome.invalido"); } return errors; } // (...) Copyleft 2006 Danilo Sato
Construindo o Model • Exemplo: Método reset() • Arquivo de Configuração // (...) // Inicializa o valor do nome com o valor nulo publicvoid reset(ActionMapping mapping, HttpServletRequest request) { this.nome = null; } // (...) (...) <form-bean name="meuForm"type="app.MeuForm"/> (...) Copyleft 2006 Danilo Sato
Construindo o Model • Outras características do ActionForm: • Permitem acesso à propriedades aninhadas: • Suporte à propriedades de mapeamento (Map) <html:text property=“valores.telefoneFormatado"/> aForm.getValores().getTelefoneFormatado() public void setEndereco(String nome, Object valor) public Object getEndereco(String nome) <html:text property="endereco(nome)"/> Copyleft 2006 Danilo Sato
Construindo o Model • DynaActionForm • Uma forma de definir um ActionForm sem escrever uma classe • Propriedades são declaradas no arquivo de configuração • Baseado no componente DynaBean do Jakarta Commons • Desvantagem: você não tem controle sobre o método reset(), os campos serão atualizados para os valores padrão Copyleft 2006 Danilo Sato
Construindo o Model • Exemplo: DynaActionForm • Arquivo de Configuração: (...) <form-bean name="meuForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="nome" type="java.lang.String"/> </form-bean> (...) Copyleft 2006 Danilo Sato
Construindo o Model • DTO = Data Transfer Object • É um padrão de projeto que define um objeto responsável por levar dados entre as diferentes camadas e/ou componentes de um sistema • Diminui a quantidade de chamadas de método entre as camadas • Também conhecido como Value Object na comunidade Java Copyleft 2006 Danilo Sato
Construindo o Model • Um pouco sobre lógica de negócio: • Dentre as responsabilidades do Model de um sistema, podemos destacar: • Armazenar o estado do sistema • Executar a lógica e regras de negócio • No contexto da nossa discussão, o Model no Struts refere-se à uma representação do estado do sistema numa aplicação web • Podemos enxergar os ActionForms como DTOs • Os dados do ActionForms geralmente são mapeados para mais de uma entidade persistida pelo sistema Copyleft 2006 Danilo Sato
Construindo o Model • Um pouco sobre lógica de negócio: • Apesar do Struts não colocar nenhuma restrição, recomenda-se que a lógica de negócio esteja desacoplada da camada de apresentação • Uma camada de negócio desacoplada pode ser reutilizada em outras aplicações (inclusive não-web) • Validações simples são permitidas no View (Exemplo: scripts JavaScript) • Recomendação: Não colocar lógica de negócio no Action Copyleft 2006 Danilo Sato
Construindo o Controller • O Struts fornece um Servlet (ActionServlet) que atua como controlador central para: • Processar requisições de usuários • Determinar os objetivos do usuário para aquela requisição • Obter dados do Model para disponibilizar na View • Escolher a View apropriada para exibição ao usuário Copyleft 2006 Danilo Sato
Construindo o Controller • Grande parte do trabalho do ActionServlet é delegado para o RequestProcessor • O ActionServlet é responsável por: • Inicialização e limpeza de recursos • Determinar qual módulo responsável pelo tratamento da requisição • Encaminhar a requisição para o RequestProcessor do módulo Copyleft 2006 Danilo Sato
Construindo o Controller • O RequestProcessor é responsável pela maior parte do trabalho do Controller • Extensível através de métodos “gancho” (hook methods) – Exemplo: setUp() no JUnit • Responsabilidades básicas: • Encontrar a Action responsável pela URL • Popular e validar o ActionForm • Tratamento de erros • Tratamento de permissões e segurança • Encaminhar processamento para a Action Copyleft 2006 Danilo Sato
RequestProcessor Action ActionForm Construindo o Controller <action-mappings> <action .../> ... </action-mappings> findMapping() ActionServlet HttpRequest process() execute() findFormBean() <form-beans> <form-bean .../> ... </form-beans> Copyleft 2006 Danilo Sato
Construindo o Controller • Um ActionMapping representa uma configuração de mapeamento entre uma URI e uma classe Action • Propriedades mais importantes: • type: Nome da classe da Action • name: Nome do ActionForm a ser utilizado • path: a URI requisitada • unkown: deve ser "true" para a Action default • validate: deve ser "true" se o ActionForm deve ser validado • forward: uma URI para onde a requisição será encaminhada Copyleft 2006 Danilo Sato
Construindo o Controller • ActionMappings são definidas no arquivo de configuração do Struts • Possíveis configurações de mapeamento: • Um Action, Um ActionForm • Somente ActionForm • Somente Action • Somente JSP • Dois Actions, Um ActionForm • Dois Actions, Dois ActionForms Copyleft 2006 Danilo Sato
Construindo o Controller • Um Action, Um ActionForm <action path = "/fullAction" type = "com.acme.struts.MyAction" name = "myForm" input = "/jsp/dataError.jsp"> <forward name="OK"path="/jsp/viewResult.jsp"/> <forward name="ERROR"path="/jsp/busError.jsp"/> </action> Copyleft 2006 Danilo Sato
Construindo o Controller • Um Action, Um ActionForm Copyleft 2006 Danilo Sato
Construindo o Controller • Somente ActionForm <action path ="/formOnlyAction" type ="org.apache.struts.actions.ForwardAction" name ="myForm" input ="/jsp/error.jsp" parameter="/jsp/viewResult.jsp"/> Copyleft 2006 Danilo Sato
Construindo o Controller • Somente Action <action path ="/actionOnlyAction" type ="com.acme.struts.MyAction" input ="/jsp/error.jsp"> <forward name="OK"path="viewResult.do"/> <forward name="ERROR"path="/jsp/error.jsp"/> </action> Copyleft 2006 Danilo Sato
Construindo o Controller • Somente JSP <action path ="/JSPOnlyAction" type ="org.apache.struts.actions.ForwardAction" parameter="/jsp/viewResult.jsp"/> Copyleft 2006 Danilo Sato
Construindo o Controller • Dois Actions, Um ActionForm <action path = "/sourceAction" type = "com.acme.struts.MyAction1" name = "myForm" input = "/jsp/error1.jsp"> <forward name="OK"path="/targetAction.do"/> </action> <action path = "/targetAction" type = "com.acme.struts.MyAction2" name = "myForm" input = "/jsp/error2.jsp"> <forward name="OK"path="/jsp/viewTarget.jsp"/> </action> Copyleft 2006 Danilo Sato
Construindo o Controller • Dois Actions, Um ActionForm Copyleft 2006 Danilo Sato
Construindo o Controller • Dois Actions, Dois ActionForms <action path = "/inputAction" type = "com.acme.struts.MyAction1" name = "inputForm" input = "/jsp/error1.jsp"> <forward name="OK“ path="/outputAction.do" redirect="true"/> </action> <action path = "/outputAction" type = "com.acme.struts.MyAction2" name = "outputForm" input = "/jsp/error2.jsp"> <forward name="OK"path="/jsp/viewTarget.jsp"/> </action> Copyleft 2006 Danilo Sato
Construindo o Controller • Dois Actions, Dois ActionForms Copyleft 2006 Danilo Sato
Construindo o Controller • Um ActionForward representa uma URI sob um nome lógico • Definidos no arquivo de configuração do Struts • Utilizados na Action para definir para onde a requisição deve ser encaminhada • Vantagens: • Evitam URIs “hardcoded” na aplicação • Estrutura de navegação declarativa, documentada no struts-config.xml Copyleft 2006 Danilo Sato
Construindo o Controller • Diferença entre forward e redirect: • forward: mantém a requisição HTTP no contexto da aplicação no servidor • redirect: instrui o cliente (navegador) a fazer uma nova requisição HTTP • ActionForwards podem ser globais (<global-forwards>) ou locais a um ActionMapping (corpo da tag <action>) • Para buscar um ActionForward na Action: • mapping.findForward("nome.do.forward"); • Recomendação: redirecionar a página inicial para uma Action Copyleft 2006 Danilo Sato
Construindo o Controller • Exemplos: <global-forwards> <!-- ActionForward Global --> <forward name="erro.generico" path="/jsp/genericError.jsp"/> </global-forwards> <action-mappings> <action (...)> <!-- ActionForward Local --> <forward name="OK" path="viewResult.do" redirect="true"/> </action> </action-mappings> Copyleft 2006 Danilo Sato
Construindo o Controller • As classes Action implementam a lógica específica de cada aplicação • Seu objetivo é processar uma requisição e retornar um ActionForward indicando para onde o controle deve ser encaminhado • É o centro da arquitetura do Struts • Analogia: “mini-servlet” Copyleft 2006 Danilo Sato
Construindo o Controller • Algumas das funcionalidades implementadas na Action: • Validar o estado atual da sessão (Ex: login) • Validação das propriedades do ActionForm necessárias • Chamar métodos com lógica de negócio • Atualizar o estado do sistema • Atualizar objetos no servidor para utilização nos próximos passos do processamento (escopo de request e session, geralmente) • Tratar erros no processamento • Determinar a página de exibição e retornar o ActionForward correspondente Copyleft 2006 Danilo Sato
Construindo o Controller • Para implementar um Action: • Estender a classe org.apache.struts.action.Action ou uma de suas subclasses disponibilizadas do Struts • Implementar o método: public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception; Copyleft 2006 Danilo Sato
Construindo o Controller • Exemplo: Action package app; // Import Struts classes ... public class MeuAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { MeuForm meuForm = (MeuForm) form; String usuario = validaUsuario(meuForm); HttpSession session = request.getSession(); session.setAttribute("USUARIO", usuario); return mapping.findForward("OK"); } // Método validaUsuario() ... } Copyleft 2006 Danilo Sato
Construindo o Controller • Exemplo: Método validaUsuario() // (...) // Valida se usuário existe com o nome informado private String validaUsuario(MeuForm form) throws UsuarioInvalidoException { String nome = form.getNome(); try { LDAPDirectory auth = LDAPDirectory.getInstance(); return auth.validateUser(nome); catch (Exception e) { throw new UsuarioInvalidoException(nome); } // (...) Copyleft 2006 Danilo Sato
Construindo o Controller • Exemplo: struts-config.xml <action path = "/login" type = "app.MeuAction" name = "meuForm" input = "/jsp/validateError.jsp"> <forward name="OK"path="/jsp/viewResult.jsp"/> <exception key="erro.usuario.invalido" type="app.UsuarioInvalidoException" path="/jsp/loginError.jsp"/> </action> Copyleft 2006 Danilo Sato
Construindo o Controller • Algumas recomendações: • Pense na concorrência quando escrever uma Action • Trate erros. Evite mostrar exceções para o usuário • Evite usar o método perform() do Struts 1.0 • O Struts 1.1 define o método execute() que lança Exception e facilita o tratamento de erros declarativo Copyleft 2006 Danilo Sato
Dúvidas ou Sugestões? Copyleft 2006 Danilo Sato