Conhecimentos Essenciais do Struts2

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>

  1. Utilizando método GET:

Acesse no navegador: http://localhost:8080/Struts2Exemplo/saduacao?nome=Joao

  1. 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

  1. Exemplo: Seleção de múltiplos checkboxes e envio dos valores para o backend.
  2. 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:

  1. Acesso a /publico/listaAlunos
  2. Acesso a /admin/listaAlunos

O console exibirá: "Método visualizar da AlunoAdmin executado"

Tags: Struts2 JavaEE MVC ActionSupport Model-Driven

Publicado em 6-26 22:31