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