Skip to content

16. Aplicativo web MVC em uma arquitetura de três camadas – Exemplo 2

16.1. Introduction

Escrevemos a aplicação [personnes-01] com a seguinte estrutura:

A camada [dao] implementava a lista de pessoas gerenciada por meio de um objeto [ArrayList]. Isso nos permitiu não nos aprofundarmos nas camadas [dao] e [service] para nos concentrarmos na camada [web]. Desejamos evoluir a aplicação para um ambiente mais realista, no qual a lista de pessoas seja armazenada em uma tabela de banco de dados. Isso nos levará a alterar a camada [dao]. Isso afetará as outras duas camadas. Para aproveitar a independência das camadas proporcionada pelo Spring IoC, vamos retomar a aplicação [personnes-01] e configurá-la com o Spring IoC:

A nova aplicação se chamará [personnes-02]. Assim que estiver pronta, sabemos que poderemos alterar as camadas [dao] e [service] sem precisar alterar o código da camada [web]. É exatamente isso que buscamos.

Criamos um novo projeto Eclipse [personnes-02] copiando e colando o projeto [personnes-01], conforme explicado no parágrafo 6.2:

No [1], vemos aparecer o arquivo de configuração no qual definiremos os beans das camadas [dao] e [service]. Seu conteúdo é o seguinte:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- a classe DAO -->
    <bean id="dao" class="istia.st.mvc.personnes.dao.DaoImpl" init-method="init"/>
    <!-- a classe de serviço -->
    <bean id="service" class="istia.st.mvc.personnes.service.ServiceImpl">
        <property name="dao">
            <ref local="dao" />
        </property>
    </bean>
</beans>
  • linha 5: define o bean denominado [dao] como uma instância da classe [DaoImpl]. Após a instanciação, o método [init] da instância é executado.
  • linhas 7-10: definem o bean denominado [service] como uma instância da classe [ServiceImpl].
  • linhas 8-10: a propriedade [dao] da instância [DaoImpl] é inicializada com a referência da camada [dao] criada na linha 5. Vale lembrar que a classe [ServiceImpl] possui, de fato, a propriedade [dao] e o setter correspondente:
public class ServiceImpl implements IService {

     // a camada [dao]
    private IDao dao;

    public IDao getDao() {
        return dao;
    }

    public void setDao(IDao dao) {
        this.dao = dao;
    }
...

É claro que, por si só, esse arquivo não faz nada. O controlador [Application] irá utilizá-lo em seu método [init] para instanciar a camada [service]. Vamos relembrar a versão anterior do método [init] do controlador:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
...
     // serviço
    ServiceImpl service = null;

     // inicialização
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
         // instanciação da camada [dao]
        DaoImpl dao = new DaoImpl();
        dao.init();
         // instanciação da camada [service]
        service = new ServiceImpl();
        service.setDao(dao);
    }

Na linha 5, fomos obrigados a nomear explicitamente a classe de implementação da camada [service] e, na linha 12, a da camada [dao]. Com o Spring IoC, o método [init] passa a ser o seguinte:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
     // parâmetros de instância
    ...

     // serviço
    private IService service = null;

     // inicialização
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
    ...
         // instanciação da camada [service]
        service = (IService) new XmlBeanFactory(new ClassPathResource("spring-config.xml")).getBean("service");
    }
  • linha 7: o campo privado [service] não é mais do tipo [ServiceImpl], mas sim do tipo [IService], c.a.d. do tipo da interface da camada [service]. A camada [web], portanto, não está mais vinculada a uma implementação específica dessa interface.
  • linha 14: inicialização do campo [service] a partir do arquivo de configuração [spring-config.xml].

Essas são as únicas alterações a serem feitas. Vamos integrar essa nova aplicação ao Tomcat, iniciá-lo e, em seguida, acessar a URL [http://localhost:8080/personnes-02]:

Image

16.2. Arquivamento da aplicação web

Desenvolvemos um projeto Eclipse/Tomcat de uma aplicação de três camadas:

Em uma versão futura, o grupo de pessoas será inserido em uma tabela de banco de dados.

  • Isso implicará uma reescrita da camada [dao]. Isso é fácil de entender.
  • A camada [service] também será modificada. Atualmente, sua única função é garantir um acesso sincronizado aos dados gerenciados pela camada [dao]. Para isso, sincronizamos todos os métodos da camada [service]. Já explicamos por que essa sincronização foi colocada nessa camada, em vez de na camada [dao]. Na nova versão, a camada [service] continuará tendo como única função a sincronização dos acessos, mas isso será garantido por transações de banco de dados, em vez de pela sincronização de métodos Java.
  • A camada [web] permanecerá inalterada.

Para facilitar a transição de uma versão para outra, criamos um novo projeto Eclipse [mvc-personnes-02B], cópia do projeto anterior [mvc-personnes-02], mas no qual as camadas [web, service, dao, entites] foram colocadas em arquivos .jar:

A pasta [src] agora contém apenas o arquivo de configuração do Spring [spring-config.xml]. Anteriormente, ele também continha o código-fonte das classes Java. Esses elementos desapareceram, substituídos por suas versões compiladas, colocadas nos arquivos [personnes-*.jar], mostrados em [1]:

O projeto [mvc-personnes-02B] foi configurado para incluir os arquivos [personnes-*.jar ] em seu ClassPath.

Estamos implantando o projeto web [mvc-personnes-02B] no Tomcat:

Para testar o projeto, iniciamos o Tomcat e acessamos a URL [http://localhost:8080/personnes02B]:

Image

O leitor é convidado a realizar testes adicionais.

Na versão com banco de dados, vamos alterar as camadas [service] e [dao]. Queremos mostrar que, para isso, bastará substituir no projeto anterior os arquivos [personnes-dao.jar] e [personnes-service.jar] pelos novos arquivos para que nosso aplicativo passe a funcionar com um banco de dados. Não precisaremos alterar os arquivos da camada [web] e da camada [entites].