Skip to content

16. Aplicação web MVC numa 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 gerida por meio de um objeto [ArrayList]. Isto permitiu-nos não nos debruçarmos sobre as camadas [dao] e [service], para nos concentrarmos na camada [web]. Pretendemos evoluir a aplicação para um ambiente mais realista, em que a lista de pessoas seja armazenada numa tabela de base de dados. Isto levará a que alteremos a camada [dao], o que terá impacto nas outras duas camadas. Para tirar partido da 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 chamar-se-á [personnes-02]. Assim que estiver desenvolvida, sabemos que poderemos alterar as camadas [dao] e [service] sem alterar o código da camada [web]. É isso que pretendemos.

Criamos um novo projeto Eclipse [personnes-02] através de copiar/colar do projeto [personnes-01], tal como foi explicado no parágrafo 6.2:

No [1], surge o ficheiro de configuração no qual iremos definir os beans das camadas [dao] e [service]. O 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, é executado o método [init] da instância.
  • 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. Recorde-se que a classe [ServiceImpl] possui, de facto, 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ó, este ficheiro não faz nada. O controlador [Application] irá utilizá-lo no seu método [init] para instanciar a camada [service]. Recordemos 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] já não é do tipo [ServiceImpl], mas sim do tipo [IService], c.a.d. do tipo da interface da camada [service]. A camada [web] já não está, portanto, ligada a uma implementação específica desta interface.
  • linha 14: inicialização do campo [service] a partir do ficheiro de configuração [spring-config.xml].

Estas são as únicas alterações a efetuar. Vamos integrar esta nova aplicação no Tomcat, iniciar o servidor e, em seguida, aceder à 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:

Numa versão futura, o grupo de pessoas será inserido numa tabela da base de dados.

  • Isso implicará uma reescrita da camada [dao]. Isto é fácil de compreender.
  • A camada [service] também será alterada. Atualmente, a sua única função é garantir um acesso sincronizado aos dados geridos pela camada [dao]. Para tal, sincronizámos todos os métodos da camada [service]. Já explicámos por que razão esta sincronização foi colocada nesta camada e não na camada [dao]. Na nova versão, a camada [service] continuará a ter como única função a sincronização dos acessos, mas esta será assegurada por transações de base 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], uma cópia do projeto anterior [mvc-personnes-02], mas onde as camadas [web, service, dao, entites] foram colocadas em arquivos .jar:

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

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

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

Para testar o projeto, iniciamos o Tomcat e, em seguida, acedemos à URL [http://localhost:8080/personnes02B]:

Image

Convidamos o leitor a realizar testes adicionais.

Na versão com base de dados, vamos alterar as camadas [service] e [dao]. Pretendemos demonstrar que bastará, então, substituir no projeto anterior os arquivos [personnes-dao.jar] e [personnes-service.jar] pelos novos arquivos para que a nossa aplicação passe a funcionar com uma base de dados. Não teremos de alterar os ficheiros da camada [web] nem da camada [entites].