Um. Ligação Automática de Dados Get/Set no Struts2
O Struts2 fornece uma funcionalidade conveniente que liga automaticamente os parâmetros da solicitação às propriedades da Action. Vamos explorar como isso funciona na prática.
Considere a seguinte Action de exemplo:
package org.example.actions;
import com.opensymphony.xwork2.ActionSupport;
public class SaudacaoAction extends ActionSupport{
private String nome;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
@Override
public String execute() throws Exception {
System.out.println("Método padrão da Action executado");
return SUCCESS;
}
}
E o arquivo JSP correspondente:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Página de Saudação</title>
</head>
<body>
${nome } seja bem-vindo!!
</body>
</html>
- Utilizando método GET:
Acesse no navegador: http://localhost:8080/Struts2Exemplo/saduacao?nome=Joao
- Utilizando método POST:
Crie uma página index.jsp:
<body>
<form action="saudacao" method="post">
nome: <input type="text" name="nome"/>
<input type="submit" value="enviar" />
</form>
</body>
Dois. Introdução à Classe ActionSupport
A classe ActionSupport oferece funcionalidades adicionais em comparação com a interface Action básica. É recomendado estendê-la em vez de implementar direttamente a interface Action.
package org.example.actions;
import com.opensymphony.xwork2.ActionSupport;
public class SaudacaoActionAvancada extends ActionSupport{
private static final long serialVersionUID = 1L;
private String nome;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
@Override
public String execute() throws Exception {
System.out.println("Método padrão da SaudacaoActionAvancada executado");
return SUCCESS;
}
}
No arquivo de configuração struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<struts>
<package name="saudacoes" extends="struts-default">
<action name="saudacao" class="org.example.actions.SaudacaoActionAvancada">
<result name="success">saudacao.jsp</result>
</action>
</package>
</struts>
Três. Configuração de Dados na Action
Vamos implementar um exemplo de sistema de autenticação de usuário, onde o login é bem-sucedido se o nome de usuário for "admin" e a senha for "senha123".
A. Atributos de tipos primitivos:
package org.example.actions;
import org.example.modelo.Usuario;
import org.example.servico.UsuarioServico;
import com.opensymphony.xwork2.ActionSupport;
public class AutenticacaoAction extends ActionSupport{
private static final long serialVersionUID = 1L;
private UsuarioServico usuarioServico = new UsuarioServico();
private nomeUsuario;
private senha;
public String getNomeUsuario() {
return nomeUsuario;
}
public void setNomeUsuario(String nomeUsuario) {
this.nomeUsuario = nomeUsuario;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
@Override
public String execute() throws Exception {
System.out.println("Método padrão da AutenticacaoAction executado");
Usuario usuario = new Usuario();
usuario.setNomeUsuario(nomeUsuario);
usuario.setSenha(senha);
if(usuarioServico.autenticar(usuario)){
return SUCCESS;
}else{
return ERROR;
}
}
}
Classe Usuario:
package org.example.modelo;
public class Usuario {
private String nomeUsuario;
private String senha;
public String getNomeUsuario() {
return nomeUsuario;
}
public void setNomeUsuario(String nomeUsuario) {
this.nomeUsuario = nomeUsuario;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
}
Classe UsuarioServico:
package org.example.servico;
import org.example.modelo.Usuario;
public class UsuarioServico {
public boolean autenticar(Usuario usuario){
if("admin".equals(usuario.getNomeUsuario()) && "senha123".equals(usuario.getSenha())){
return true;
}else{
return false;
}
}
}
struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<struts>
<package name="autenticacao" extends="struts-default">
<action name="login" class="org.example.actions.AutenticacaoAction">
<result name="success">sucesso.jsp</result>
<result name="error">falha.jsp</result>
</action>
</package>
</struts>
Página de login login.jsp:
<body>
<form action="login" method="post">
Usuário: <input type="text" name="nomeUsuario"/><br>
Senha: <input type="password" name="senha"/><br>
<input type="submit" value="Entrar" />
</form>
</body>
Página de sucesso sucesso.jsp:
<body>
Login bem-sucedido!
</body>
Página de falha falha.jsp:
<body>
Falha no login!
</body>
B. Atributos do tipo JavaBean:
Agora vamos modificar a AutenticacaoAction para usar um objeto Usuario diretamente:
package org.example.actions;
import org.example.modelo.Usuario;
import org.example.servico.UsuarioServico;
import com.opensymphony.xwork2.ActionSupport;
public class AutenticacaoActionBean extends ActionSupport{
private static final long serialVersionUID = 1L;
private UsuarioServico usuarioServico = new UsuarioServico();
private Usuario usuario;
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
@Override
public String execute() throws Exception {
System.out.println("Método padrão da AutenticacaoActionBean usando JavaBean");
if(usuarioServico.autenticar(usuario)){
return SUCCESS;
}else{
return ERROR;
}
}
}
A página de login precisa ser modificada:
<body>
<form action="login" method="post">
Usuário: <input type="text" name="usuario.nomeUsuario"/><br>
Senha: <input type="password" name="usuario.senha"/><br>
<input type="submit" value="Entrar" />
</form>
</body>
Segunda abordagem: Model-Driven:
package org.example.actions;
import org.example.modelo.Usuario;
import org.example.servico.UsuarioServico;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class AutenticacaoActionModelo extends ActionSupport implements ModelDriven<Usuario>{
private static final long serialVersionUID = 1L;
private UsuarioServico usuarioServico = new UsuarioServico();
private Usuario usuario = new Usuario();
@Override
public String execute() throws Exception {
System.out.println("Método padrão da AutenticacaoActionModelo usando Model-Driven");
if(usuarioServico.autenticar(usuario)){
return SUCCESS;
}else{
return ERROR;
}
}
@Override
public Usuario getModel() {
return usuario;
}
}
A página de login com Model-Driven:
<body>
<form action="login" method="post">
Usuário: <input type="text" name="nomeUsuario"/><br>
Senha: <input type="password" name="senha"/><br>
<input type="submit" value="Entrar" />
</form>
</body>
Quatro. Processamento de Múltiplos Valores no Struts2
- Exemplo: Seleção de múltiplos checkboxes e envio dos valores para o backend.
- Exemplo: Envio em lote de múltiplos objetos Aluno para o backend.
AcaoHobby.java:
package org.example.actions;
import com.opensymphony.xwork2.ActionSupport;
public class AcaoHobby extends ActionSupport{
private String[] hobbies;
public String[] getHobbies() {
return hobbies;
}
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
@Override
public String execute() throws Exception {
System.out.println("Método padrão da AcaoHobby executado");
for(String h : hobbies){
System.out.println(h);
}
return SUCCESS;
}
}
AcaoAluno.java:
package org.example.actions;
import java.util.List;
import org.example.modelo.Aluno;
import com.opensymphony.xwork2.ActionSupport;
public class AcaoAluno extends ActionSupport{
private List<Aluno> alunos;
public List<Aluno> getAlunos() {
return alunos;
}
public void setAlunos(List<Aluno> alunos) {
this.alunos = alunos;
}
@Override
public String execute() throws Exception {
System.out.println("Método padrão da AcaoAluno executado");
for(Aluno a : alunos){
System.out.println(a);
}
return SUCCESS;
}
}
Classe Aluno:
package org.example.modelo;
public class Aluno {
private String nome;
private String genero;
private int idade;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getGenero() {
return genero;
}
public void setGenero(String genero) {
this.genero = genero;
}
public int getIdade() {
return idade;
}
public void setIdade(int idade) {
this.idade = idade;
}
@Override
public String toString() {
return "Aluno [nome=" + nome + ", genero=" + genero + ", idade=" + idade + "]";
}
}
Configuração struts.xml:
<struts>
<package name="dadosMultiplos" extends="struts-default">
<action name="hobbies" class="org.example.actions.AcaoHobby">
<result name="success">sucesso.jsp</result>
</action>
<action name="alunos" class="org.example.actions.AcaoAluno">
<result name="success">sucesso.jsp</result>
</action>
</package>
</struts>
Página hobbies.jsp:
<body>
<form action="hobbies" method="post">
Hobbies:
<input type="checkbox" name="hobbies" value="cantar"/>Cantar
<input type="checkbox" name="hobbies" value="dançar"/>Dançar
<input type="checkbox" name="hobbies" value="dormir"/>Dormir
<input type="checkbox" name="hobbies" value="jogar"/>Jogar
<input type="submit" value="Enviar"/>
</form>
</body>
Página adicionarAlunos.jsp:
<body>
<form action="alunos" method="post">
| Nome | Gênero | Idade |
|---|---|---|
| <input name="alunos[0].nome" type="text"></input> | <input name="alunos[0].genero" type="text"></input> | <input name="alunos[0].idade" type="text"></input> |
| <input name="alunos[1].nome" type="text"></input> | <input name="alunos[1].genero" type="text"></input> | <input name="alunos[1].idade" type="text"></input> |
| <input type="submit" value="Enviar"></input> |
</form>
</body>
Cinco. Configuração do struts.xml
- Atributo name do package: utilizado para distinguir diferentes módulos. Não tem funcionalidade prática, apenas serve como identificador.
- Namespace: ao adicionar um namespace como "/publico" ao package, a URL para acessar as actions deve incluir este prefixo, como "/publico/acao".
- abstract: por padrão é false. Quando definido como true, o package não pode conter actions diretamente, mas pode ser herdado por outros packages.
- method: por padrão, é executado o método execute() da Action. Ao especificar method="listar", será executado o método listar().
Exemplo de arquivo struts.xml:
<struts>
<package name="frontend" namespace="/publico" extends="struts-default">
<action name="listaAlunos" class="org.example.actions.AlunoPublico">
<result name="success">${pageContext.request.contextPath}/sucesso.jsp</result>
</action>
</package>
<package name="backend" namespace="/admin" extends="struts-default">
<action name="listaAlunos" class="org.example.actions.AlunoAdmin" method="visualizar">
<result name="success">${pageContext.request.contextPath}/sucesso.jsp</result>
</action>
</package>
<!-- Pacote abstrato para ser herdado, por exemplo para filtrar conteúdo inadequado -->
<package name="filtroConteudo" abstract="true"></package>
</struts>
Classe AlunoPublico.java:
package org.example.actions;
import com.opensymphony.xwork2.ActionSupport;
public class AlunoPublico extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("Método padrão da AlunoPublico executado");
return SUCCESS;
}
}
Classe AlunoAdmin.java:
package org.example.actions;
import com.opensymphony.xwork2.ActionSupport;
public class AlunoAdmin extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("Método padrão da AlunoAdmin executado");
return SUCCESS;
}
public String visualizar() throws Exception{
System.out.println("Método visualizar da AlunoAdmin executado");
return SUCCESS;
}
}
Testes:
- Acesso a /publico/listaAlunos
- Acesso a /admin/listaAlunos
O console exibirá: "Método visualizar da AlunoAdmin executado"