Skip to content

16. Aplicação Web MVC numa arquitetura de 3 camadas – Exemplo 2

16.1. Introdução

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

A camada [dao] implementou a lista de pessoas gerida utilizando um objeto [ArrayList]. Isto permitiu-nos evitar complicar excessivamente as camadas [dao] e [service], para que pudéssemos concentrar-nos na camada [web]. Queremos evoluir a aplicação para um ambiente mais realista, onde a lista de pessoas seria armazenada numa tabela de base de dados. Isto exigirá que alteremos a camada [dao]. Isto terá impacto nas outras duas camadas. Para tirar partido da independência de camadas proporcionada pelo Spring IoC, vamos pegar na aplicação [people-01] e configurá-la com o Spring IoC:

A nova aplicação será chamada [people-02]. Depois de escrita, sabemos que poderemos modificar as camadas [DAO] e [service] sem alterar o código na camada [web]. É exatamente isso que pretendemos.

Criamos um novo projeto Eclipse [people-02] copiando e colando o projeto [people-01], conforme explicado na secção 6.2:

Em [1], vemos aparecer o ficheiro de configuração, no qual iremos definir os beans para as 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>
    <!-- the dao class -->
    <bean id="dao" class="istia.st.mvc.personnes.dao.DaoImpl" init-method="init"/>
    <!-- service class -->
    <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 à 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 {

    // the [dao] layer
    private IDao dao;

    public IDao getDao() {
        return dao;
    }

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

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

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

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
        // dao] layer instantiation
        DaoImpl dao = new DaoImpl();
        dao.init();
        // instantiation of the [service] layer
        service = new ServiceImpl();
        service.setDao(dao);
    }

Na linha 5, tivemos de 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 {
    // instance parameters
    ...

    // service
    private IService service = null;

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
    ...
        // instantiation of the [service] layer
        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], ou seja, do tipo da interface da camada [service]. A camada [web] já não está, portanto, vinculada 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 serem feitas. Vamos integrar esta nova aplicação no Tomcat, iniciá-la e, em seguida, solicitar a URL [http://localhost:8080/personnes-02]:

Image

16.2. Arquivamento da aplicação web

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

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

  • Isto exigirá uma reescrita da camada [DAO]. Isto é fácil de compreender.
  • A camada [service] também será modificada. Atualmente, a sua única função é garantir o acesso sincronizado aos dados geridos pela camada [dao]. Para tal, sincronizámos todos os métodos na 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 do acesso, mas esta será tratada 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 a seguinte, estamos a criar um novo projeto Eclipse [mvc-personnes-02B], uma cópia do projeto anterior [mvc-personnes-02], mas onde as camadas [web, service, dao, entities] foram colocadas em arquivos .jar:

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

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

Implementamos 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, iremos alterar as camadas [service] e [dao]. Pretendemos demonstrar que bastará substituir os arquivos [personnes-dao.jar] e [personnes-service.jar] do projeto anterior pelos novos arquivos para que a nossa aplicação passe a funcionar com uma base de dados. Não será necessário alterar os arquivos da camada [web] nem da camada [entities].