quarta-feira, 4 de setembro de 2013

Struts

  7.3 Struts  

   

 Front Controller: A classe ActionServlet atua como o Front Controller do Struts. Ele deve ser configurado no arquivo web.xml.  

 Web.xml  

 <servlet>  

   <servlet-name>action</servlet-name>  

   <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>  

 </servlet>  

 <init-param>  

    <param-name>config</param-name>  

    <param-value>/WEB-INF/struts-config.xml</param-value>  

 </init-param>  

 <servlet-mapping>  

   <servlet-name>action</servlet-name>  

   <url-pattern>*.do</url-pattern>  

 </servlet-mapping>  

 <taglib>  

   <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>  

   <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>  

 </taglib>  

   

 Action Form: Logo após o recebimento da requisição o ActionServlet delega ao RequestProcessor a responsabilidade de extrair os parâmetros da requisição e popular um ActionForm.  

 •    Os ActionForms são responsáveis por validar se os atributos da requisição são sintaticamente corretos e eventualmente disparar exceções avisando o usuário final.  

 •    O desenvolvedor deve especializar um ActionForm e sobrescrever os métodos reset e validade.  

 •    Além disso, a sua classe de ActionForm deve conter os atributos que correspondem aos campos do form html.  

   

 package br.com.softech;  

 import org.apache.struts.action.*;  

 public class FuncionarioForm extends ActionForm {  

     private String nome;  

     private Integer idade;  

     //Setters and getters;  

     public void reset( ActionMapping mapping, HttpServletRequest req ) {  

         this.nome = null;  

         this.idade = null;  

     }  

     public ActionErrors validate( ActionMapping mapping, HttpServletRequest req ) {  

         ActionErrors errors = new ActionErrors( );  

         if( nome == null || idade == null ) {  

             errors.add( “errNomeIdade”, new ActionError(“nomeIdade.required”) );  

         }  

         return errors;  

 }}  

 No struct-config  

     <struts-config>  

     <form-beans>  

         <form-bean name="funcionarioForm" type="br.com.softech.FuncionarioForm“ />  

     </form-beans>  

     </struts-config>  

   

 Action: Após criar e validar os parâmetros via ActionForm o RequestProcessor acessa o método execute do objeto  

 Action relacionado a requisição (Command Pattern).  

 •    As Actions são responsáveis por ativar os objetos de negócio, tratar eventuais exceções e redirecionar dados e  

 conteúdo para a próxima página.  

 •    O desenvolvedor deve especializar a classe Action e sobrescrever o método execute.  

 •    As classes Action são reutilizadas por todas as requisições, deste modo tais classes devem ser threadsafe.  

   

     public class NovoFuncAction extends Action {  

         public ActionForward execute(ActionMapping mapping, ActionForm form,  

             HttpServletRequest request,    HttpServletResponse response)  

         throws IOException, ServletException {  

             //Acessando ActionForm  

             FuncionarioForm funcForm = (FuncionarioForm) form;  

             String nome = funcForm.getNome( );  

             Integer idade = funcForm.getIdade( );  

             //Lógica do Negócio para cadastrar um novo funcionário  

             //....  

             //Redirecionamento  

             return mapping.findForward("sucesso");  

         }}  

   

 O mapeamento entre as requisições e as ações (Action) é feito de forma declarativa no arquivo struts-config.xml.  

 <action-mappings>  

     <action path="/listaFunc" type=“br.com.softech.ListaFuncAction“ input="/listaFunc.jsp“ />  

     <action path="/novoFunc" type=“br.com.softech.NovoFuncAction"  

         name=“funcionarioForm" scope="request" input="/novoFunc.jsp">  

         <forward name="sucesso" path="/listaFunc.do" redirect="true“ />  

     </action>  

 </action-mappings>  

   

 ActionForward: A classe ActionFoward é responsável pelo mapeamento lógico das páginas do sistemas, evitando assim, o uso do nome físico (URI) dento do código.  

 •    O uso eficiente do ActionFoward facilita a manutenção do sistema.  

 •    ActionFowards são declaradas dentro do strutsconfig.xml em dois níveis (Global e Action), sendo que as  

 declaradas dentro das ações tem maior precedência.  

     <global-forwards>  

         <forward name="error" path="/error.jsp"/>  

     </global-forwards>  

     <action-mappings>  

         <action path="/login" type=“acme.actions.LoginCheckAciton"  

             name="LoginForm" scope="request" input="/login.jsp">  

             <forward name="success" path="/main.jsp" redirect="true"/>  

         </action>  

     </action-mappings>  

   

 ActionError e ActionMessages: Responsáveis pelo armazenamento de informações sobre mensagens de erro, anomalias do sistema (ActionError) e avisos (ActionMessage).  

 •    Geralmente é utilizada dentro de ActionForm’s (erros de sintaxe) e Action’s (erros de sistema).  

 •    Possuem grande integração com os serviços de internacionalização e tag libraries  

   

     public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {  

         ActionErrors errors = new ActionErrors();  

         if ((this.nome == null) || (this.nome.lenght()<1)) {  

             errors.add(“nome”, new ActionError(“nome.required”));  

         }  

         return errors;  

     }  

   

   

 Internacionalização:  

 •    O Struts oferece suporte a internacionalização através da classe MessageResources.  

 •    A classe MessageResources é populada em tempo de execução pelo RequestProcessor de acordo com as informações registradas no struts-config e a língua/região utilizada pelo usuário final.  

 •    Largamente utilizadas pelos ActionErrors e tag libraries do Struts.  

 •    A implementação padrão usa arquivos .properties, mas especializações podem ser adicionadas para atender outros cenários.  

 •    Configurando a I18N no arquivo struts-config.xml:  

         <message-resources parameter=“ApplicationResources"/>  

 •    Configuração do arquivo ApplicationResources.properties:  

         nomeIdade.required=Nome e Idade são requeridos.  

         label.nome=Nome  

         label.idade=Idade  

 •    Acessando as mensagens do JSP:  

         <bean:message key=“label.nome” />  

 •    Acessando as mensagens do Action:  

         msg = getResources( request ).getMessage( "nomeIdade.requerido“ );  

 Exceptions Handling:  

 •    Mecanismo adicionado na versão 1.1.  

 •    Tem por finalidade implementar o tratamento de exceções de forma declarativa.  

 •    Utiliza a classe ExceptionHandler para interceptar as exceções e redirecioná-las para as suas páginas de erro ou respectivas ações de controle.  

 •    Impedem que o usuário veja exceções de sistema não tratadas:  

 ◦     NullPointerException, Internal Error  

 •    Podem ser globais ou relativas a uma ação (Action).  

 •    Configuração no struts-config.xml  

     <global-exceptions>  

     <exception type=“br.com.softech.MinhaException"    path="/error.jsp“ key=“exception.minha.exception" scope="request"/>  

     </global-exceptions>  

   

 Passos:  

     1 – HTTP request  

     2 – acesso ao struts-config.xml. Lido pelo ActionServlet na inicializaão da aplicação. Nesse arquivo são definidos os Actions.  

     3 – Lê as informações do ActionForm. Passa os filtos  

     4 – Retorna as informações do ActionForm para o ActinServlet.  

     5 – O ActionServlet poassa as informações para o Action, implementado pelo desenvolvedor.  

     6-7- Regras de negócio.  

     8 – Volta ao ActionServlet.  

     9 – Faz o foward para o JSP ou HTML através do ActionForward.  

     10 – HTTP response  

 Os detalhes são definidos no ActionMapping  

   

   

   

 @Action(value="adicionaTarefa", results = {  

 @Result(name="ok", location="/tarefa-adicionada.jsp")  

 @Result(name="ok", type="redirectAction", params= {"actionName", "listaTarefas"})  

   

 <interceptors>  

 <interceptor name="autorizador"  

 class="br.com.caelum.tarefas.interceptor.AutorizadorInterceptor"></interceptor>  

 </interceptors>  

   

   

 Struts-config.xlm  

 <struts-config>  

 <form-beans>  

 <form-bean name="userFormBean" type="coreservlets.UserFormBean"/>  

 </form-beans>  

 <action-mappings>  

 <action path="/actions/register4" type="coreservlets.RegisterAction3"  

 name="userFormBean" scope="request">  

 <forward name="bad-address" path="/WEB-INF/results/bad-address4.jsp"/>  

 <forward name="bad-password" path="/WEB-INF/results/bad-password4.jsp"/>  

 <forward name="success" path="/WEB-INF/results/result4.jsp"/>  

 </action>  

 </action-mappings>  

 <message-resources parameter="resources.application" null="false"/>  

 </struts-config>  

 ´  

  7.3.1 DispatchAction functionality  

 package vaannila;  

 import com.opensymphony.xwork2.ActionSupport;  

 public class UserAction extends ActionSupport{  

   private String message;  

   public String execute()  {  

     message = "Inside execute method";    return SUCCESS;  }  

   public String add()  {  

     message = "Inside add method";    return SUCCESS;  }  

   public String getMessage() {   return message;  }  

   public void setMessage(String message) { this.message = message;  }  

 }  

   

 <struts>  

   <package name="default" extends="struts-default">  

     <action name="User" class="vaannila.UserAction">  

       <result name="success">/success.jsp</result>  

     </action>  

     <action name="addUser" method="add" class="vaannila.UserAction">  

       <result name="success">/success.jsp</result>  

     </action>  

   </package>  

 </struts>  

   

 <%@taglib uri="/struts-tags" prefix="s" %>  

 <html><head>  

 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  

 <title>Insert title here</title>  

 </head>  

 <body>  

 <s:form action="User" >  

   <s:submit />  

   <s:submit action="addUser" value="Add" />  

 </s:form>  

 </body></html>  

   

 Se o “User” for clicado no request, o método execute() na classe UserAction é chamado. Se o requet for “addUser”, o método add() será chamado .  

   

  7.3.2 Validação  

 http://viralpatel.net/blogs/2009/12/struts2-validation-framework-tutorial-example.html  

   

 Validator.xml: Quais rotinas de validação são incluídas e como elas devem ser aplicadas.  

 Validator-rules.xml. Validações no lado do cliente, podem enviar JavaScript.  

 Tipos:  

 Field Validators: Age sobre campos simples acessível pela action.  

 <validators>  

  <field name="bar">  

    <field-validator type="required">  

      <message>You must enter a value for bar.</message>  

    </field-validator>  

  </field>  

 </validators>  

   

 Non-field validators: Específico para o domínio. Um exemplo é o ExpressionValidator.  

 <validators>  

    <validator type="expression">  

       <param name="expression">foo lt bar</param>  

    </validator>  

 </validators>  

   

 Criar a Action  

 public class CustomerAction extends ActionSupport{  

   private String name;  

   public String addCustomer() {    return SUCCESS;    }  

   public String getName() {        return name;    }      

 }  

 No struts.xml:  

 <action name="customer"    ---- Associa essa action ao nome “customer”  

   class="net.viralpatel.struts2.CustomerAction">  

   <result name="success">SuccessCustomer.jsp</result>  

   <result name="input">Customer.jsp</result>  

 </action>  

 No Customer.jsp:  

 <%@ page contentType="text/html; charset=UTF-8"%>  

 <%@ taglib prefix="s" uri="/struts-tags"%>  

 <html>    <head>        <title>Customer Form - Struts2 Demo | ViralPatel.net</title>    </head>  

 <body>        <h2>Customer Form</h2>  

     <s:form action="customer.action" method="post">  

       <s:textfield name="name" key="name" size="20" />  

       <s:submit method="addCustomer" key="label.add.customer" align="center" />  

     </s:form>  

 </body>    </html>  

 No SuccessCustomer.jsp  

 <%@ page contentType="text/html; charset=UTF-8"%>  

 <%@ taglib prefix="s" uri="/struts-tags"%>  

 <html>        <head>        <title>Customer Page - Struts2 Demo | ViralPatel.net</title>    </head>  

 <body>  <h2>Customer Added Successfully.</h2>    </body>    </html>  

 No /resources/ApplicationResources.properties   

 name= Name  

 label.add.customer=Add Customer  

 errors.invalid=${getText(fieldName)} is invalid.  

 errors.required=${getText(fieldName)} is required.  

 errors.number=${getText(fieldName)} must be a number.  

 errors.range=${getText(fieldName)} is not in the range ${min} and ${max}.  

 CustomerAction-validation.xml - CustomerAction = nome da Action. Deve estar no mesmo pacote da Action.  

 <validators>  

   <field name="name">  

     <field-validator type="requiredstring">  

       <param name="trim">true</param>  

       <message key="errors.required" />  

     </field-validator>  

   </field>  

   <field name="age">  

     <field-validator type="int">  

       <param name="min">1</param>  

       <param name="max">100</param>  

       <message key="errors.range"/>  

     </field-validator>  

   </field>  

 </validators>  

 Client Side Validator  

 No jsp, apenas coloca o parâmtro validate = true  

 <s:form action="customer.action" method="post" validate="true">  

   …  

 </s:form>  

  7.3.3 Interceptors  

 Eles interceptão ou agente sobre o request dos usuários. Três usos principais: Antes da action, entre a action e a view ou depois da view.  

   

   

   

 public class AuthorizationInterceptor extends AbstractInterceptor {  

     private static final String USER_KEY = "user";  

     public String intercept(ActionInvocation invocation) throws Exception {  

         Map session = invocation.getInvocationContext().getSession();  

         if(session.get(USER_KEY) == null) {  

             addActionError(invocation, "You must be authenticated ");  

             return Action.ERROR;     }  

   

         return invocation.invoke();        }  

   

     public String intercept(ActionInvocation invocation) throws Exception {  

       //Pre processing  

       logMessage(invocation, START_MESSAGE);  

       String result = invocation.invoke();  

       //Post processing  

       logMessage(invocation, FINISH_MESSAGE);  

       return result;  

     }  

     private void addActionError(ActionInvocation invocation, String message) {  

         Object action = invocation.getAction();  

         if(action instanceof ValidationAware) {  

             ((ValidationAware) action).addActionError(message);  

         }    }    }  

   

 Adding an Interceptor to your struts.xml:  

 <package name="example" extends="struts-default">  

  <interceptors>  

   <!--  

    One possible use of an interceptor is to send the user to special version of the .jsp  

      view if they are using a Blackberry as shown above.  

   -->  

   <interceptor name="wireless" class="com.lumidant.tutorial.struts2.interceptor.WirelessInterceptor">  

   

   <interceptor-stack name="wirelessStack">  

    <interceptor-ref name="exception" />  

    <interceptor-ref name="servlet-config" />  

    <interceptor-ref name="i18n" />  

    <interceptor-ref name="chain" />  

    <interceptor-ref name="params" />  

    <interceptor-ref name="wireless" />  

   </interceptor-stack>  

  </interceptors>  

   

  <default-interceptor-ref name="wirelessStack" />  

 </package>  

   

 Na configuração do Action  

 <action name="*Sample" method="{1}" class="vaannila.SampleAction">  

    <interceptor-ref name="exampleStack" />  

    <result name="populate">/first.jsp</result>  

    <result name="success">/success.jsp</result>  

 </action>  

  7.3.4 Tiles  

 http://javafree.uol.com.br/artigo/2157/Tiles-com-Struts.html  

   

 Solução para Templates de Layout, por exemplo, Foot e Header. Evita a repetição de código e controle do layout.  

 Solução 1: Inconveniente: Ao mudar o layout da aplicação, tem que modificar todas as páginas.   

     <html>   

      <body>   

        <jsp:include page="/header.jsp" />   

            a's body...   

       <p>   

        <jsp:include page="/footer.jsp" />   

       </body>   

     </html>   

   

 Solução 2: Com tile, mas parecido com a solução 1.  

 No web.xml  

     <taglib>  

        <taglib-uri>/tags/struts-tiles</taglib-uri>  

        <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>  

     </taglib>   

 Página.jsp  

     <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>   

     <html>   

         <body>   

             <tiles:insert page="/header.jsp" flush="true"/>   

             <tiles:insert page="bBody.jsp" flush="true"/>   

             <tiles:insert page="/footer.jsp" flush="true"/>   

         </body>   

     </html>   

 Solução 3: Solução com Templates para a definição de layouts. Insere-se marcadores ao invés de dar includes.  

 Layout.jsp  

     <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>   

     <html>   

      <body>   

       <tiles:insert attribute="header"/>   

       <tiles:insert attribute="body"/>   

       <tiles:insert attribute="footer"/>   

      </body>   

     </html>   

 Página.jsp  

     <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>   

     <tiles:insert page="/layout.jsp" flush="true">   

       <tiles:put name="header" value="/header.jsp"/>   

       <tiles:put name="body" value="/aBody.jsp"/>   

       <tiles:put name="footer" value="/footer.jsp"/>   

     </tiles:insert>    

 Solução 4: Configurar o Struts e Tiles em um arquivo XML. Ex: tileDefinitions.xml  Nesse caso, nem tem um aquivo principal com o jsp, só fragmentos.  

   

     <?xml version="1.0" encoding="ISO-8859-1"?>   

     <component-definitions>   

       <definition name="aDef" path="/layout.jsp">   

         <put name="header" value="/header.jsp"/>   

         <put name="footer" value="/footer.jsp"/>   

         <put name="body" value="/aBody.jsp"/>   

       </definition>   

     </component-definitions>   

   

     <?xml version="1.0" encoding="ISO-8859-1"?>   

     <component-definitions>   

       <definition name="baseDef" path="/layout.jsp">   

         <put name="header" value="/header.jsp"/>   

         <put name="footer" value="/footer.jsp"/>   

         <put name="body" value=""/>   

       </definition>   

    

       <definition name="aDef" extends="baseDef">   

         <put name="body" value="/aBody.jsp"/>   

       </definition>   

      </component-definitions>   

 No web.xml  

       <init-param>   

         <param-name>definitions-config</param-name>   

         <param-value> /WEB-INF/tileDefinitions.xml </param-value>   

       </init-param>   

   

 No action:  

 public class DoFirst extends Action {   

    

   public ActionForward perform( ActionMapping aMapping, ActionForm aForm,   

     HttpServletRequest aRequest, HttpServletResponse aResponse ) {   

     return aMapping.findForward("success"); } }   

   

 No struts-config:  

     <action path="/a" type="com.malani.struts.action.DoFirst">   

       <forward name="success" path="aDef"/>   

     </action>    

   

  7.3.5 Struts com AJAX  

 http://viralpatel.net/blogs/2010/01/struts-2-ajax-tutorial-example-drop-down.html  

 O Struts 2 usa o AJAX using Dojo Toolkit: http://viralpatel.net/blogs/2009/02/introduction-to-dojo-toolkit-javascript-framework.html  

 1.    Incluir no classpath: struts2-dojo-plugin.jar. Jogar no WEB-INF/lib   

 2.    Criar a classe AJAX action:  

     import com.opensymphony.xwork2.  

     public class AjaxAutocomplete extends ActionSupport {  

       private String data = "Afghanistan, Zimbabwe, India, United States, Germany, China";  

       private List<String> countries;  

       private String country;  

       public String execute() {  

         countries = new ArrayList<String>();  

         StringTokenizer st = new StringTokenizer(data, ",");  

         while (st.hasMoreTokens()) {          countries.add(st.nextToken().trim());    }  

         return SUCCESS;  

       }  

       public String getCountry() {    return this.country;          }  

       public void setCountries(List<String> countries) {    this.countries = countries;  }  

       public void setCountries(List<String> countries) {    this.country = country;    }  

     }  

 3.    Criar a Jsp. Com a inclusão da taglib e o taglib <sx:head/> que será usada na para habilitar as tags AJAX. Colocar entre <head> … </head>   

 <%@ page contentType="text/html; charset=UTF-8"%>  

 <%@ taglib prefix="s" uri="/struts-tags"%>  

 <%@ taglib prefix="sx" uri="/struts-dojo-tags"%>  

 <html><head>  <title>Welcome</title>  

   <sx:head />  

 </head>  

 <body>  

   <h2>Struts 2 Autocomplete (Drop down) Example!</h2>  

   Country:  

   <sx:autocompleter size="1" list="countries" name="country"></sx:autocompleter> Tag que renderiza o auto complete drop down  

   </action>  

 </body>    </html>  

 4.    struts.xml  

 <action name="ajaxdemo" class="net.viralpatel.struts2.AjaxAutocomplete">  

   <interceptor-ref name="loggingStack"></interceptor-ref>  

   <result name="success" type="tiles">/ajaxdemo.tiles</result>  //está usando tiles. Maspoderia apontar diretamente para o jsp.  

   <result type="tiles">/ajaxdemo.tiles</result>        com <result name="success">/ajaxDemo.jsp</result>  

 </action>   

   

Nenhum comentário:

Postar um comentário