O padrão de projeto MVC é um dos mais utilizados na programação, contudo, em Java esse padrão era implementado praticamente na mão ou com o uso de pequenos frameworks. Como era algo que dava muito trabalho e funcionava muito bem em outras linguagens, então logo a comunidade recebeu o Struts e outros frameworks para criar as aplicações com as três camadas: model, view e controller.

O Framework Spring MVC é um framework web MVC desenvolvido pela Spring Source e de código aberto. Ele é projetado em torno de um Servlet, o DispatcherServlet, que despacha pedidos para os controladores. Um controlador padrão do Spring MVC faz uso das anotações @Controller e @RequestMapping, que oferecem uma ampla gama de recursos flexíveis para manipulação das requisições.

Controladores do Spring MVC

Os controladores do Spring MVC dão acesso a parte da aplicação que normalmente é responsável por resolver as questões relacionadas a lógica de negócio e geralmente são denominadas como interfaces de serviços. O DispatcherServlet direciona as requisições dos usuários para os controladores de acordo com o mapeamento realizado nestes últimos. Esses controladores interpretam a entrada do usuário (requisições) e transformam-na em um modelo que no Spring MVC é representado pela Interface Model e suas implementações. O Spring implementa um controlador de uma forma muito abstrata, permitindo criar uma grande variedade de controladores. No Spring 2.5 foi introduzido um modelo de programação baseado em anotações para controladores MVC como, por exemplo, @RequestMapping, @RequestParam, @ModelAttribute.

As anotações @Controller e @RequestMapping

A anotação @Controller indica que uma classe particular serve como um controlador, atuando como um estereótipo para a classe anotada, indicando o seu papel. Já a anotação @RequestMapping é usada para mapear URLs como www.DNS_da_aplicação/cliente para toda uma classe ou para um método manipulador particular. Normalmente, a anotação de nível de classe mapeia um caminho de requisições específico em um controlador de formulário, com anotações adicionais em nível de método, estreitando o mapeamento primário para um método específico de solicitação HTTP ("GET", "POST", etc.) ou uma condição de parâmetro de solicitação HTTP.

Um exemplo do uso das anotações @Controller e @Request será mostrado na Listagem 1, onde a anotação @Controller indica que a classe Cliente é um controlador do Spring MVC. Dessa forma, o DispatcherServlet poderá encaminhar requisições de usuário para serem manipuladas nesta classe.


package br.com.cazuzaneto.cotrolador;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
@Controller
@RequestMapping(value = "/cliente")
public class Cliente {
 
    @RequestMapping(method = RequestMethod.GET)
    public String exibeTodosOsClientes(Model uiModel) {
        // ...
        return "pagina";
    }
 
    @RequestMapping(method = RequestMethod.POST)
    public String persisteNovoCliente(Model uiModel) {
        // ...
        return "pagina";
    }
}
Listagem 1. Uso das anotações

A anotação @RequestMapping indica que o controlador, que neste caso é a classe Cliente, receberá as requisições feitas à URL www.DNS_da_aplicação/cliente. O método exibeTodosOsClientes também está anotado com a anotação @RequestMapping, indicando que esse método irá receber as requisições feitas a URL www.DNS_da_aplicação/cliente sempre que se tratar de uma requisição HTTP GET.

Por sua vez, o método persisteNovoCliente receberá as requisições feitas a URL www.DNS_da_aplicação/cliente usando o método POST. Esse critério é definido através do uso do parâmetro method da anotação @RequestMapping. Um método mapeado com a anotação @RequestMapping deverá ter algum retorno que, por sua vez, será exibido ao usuário. Esse retorno pode ser de vários formatos: uma página de hipertexto, um arquivo (XML, JSON, JPEG, PDF), entre outros. Quando se trata de páginas que serão exibidas ao usuário, estas deverão ser tratadas por algum ViewResolver, que veremos na próxima seção.

ViewResolver

O retorno de um método anotado com @RequestMapping deverá ser tratado por algum ViewResolver. Este permite ao desenvolvedor renderizar modelos de páginas web em um navegador sem amarrá-lo a uma tecnologia específica. Ele deve ser configurado no contexto do DispatcherServlet. Existem muitas opções para ViewResolvers que podem ser usadas no Spring MVC: uma delas é a integração com o projeto Apache Tiles. Neste trabalho será utilizado um ViewResolver do Spring MVC: o InternalResourceViewResolver.

Lembrando que o Apache Tiles permite definir fragmentos de páginas que podem ser montadas em páginas mais completas em tempo de execução. Esses fragmentos, ou tiles, podem ser usados para reduzir a duplicação de elementos de página dentro de outras tiles para desenvolver templates reutilizáveis.

Configuração do Spring MVC

A configuração do Spring MVC está focada no arquivo web.xml e na configuração do contexto do DispatcherServlet. Como o Spring MVC é projetado em torno de um Servlet, o DispatcherServlet, este precisa ser registrado e mapeado no arquivo web.xml. Já a configuração do contexto do DispatcherServlet pode ser feita em um arquivo XML. Esse arquivo deve ser carregado junto com a aplicação. Para isso, é necessário indicar no arquivo web.xml do projeto que o arquivo de configuração do Spring deverá ser carregado. Essa não é a única forma de configurar o contexto do DispatcherServlet, mas será a forma utilizada neste trabalho. Na documentação (seção Links) você encontra mais informações, lembrando que a forma vista aqui é a mais recomendada.

Criação e configuração do projeto

O projeto-exemplo criado neste artigo tem apenas fins didáticos, por este motivo será utilizado um cenário simples, que irá utilizar uma pequena parte dos recursos do Spring Framework MVC.

A primeira coisa a se fazer é criar um projeto web Java usando o Maven (vide seção Links). O nome dado ao projeto desenvolvido foi "spring-mvc". A ferramenta Spring Tool Suite (STS) foi utilizada para o desenvolvimento do projeto em questão, porém qualquer IDE Java (Eclipse, NetBeans, etc.) poderá ser utilizada para recriação deste exemplo. A STS pode ser usada tanto em máquinas com Windows, Linux ou MAC. Seu ambiente é baseado no Eclipse e fornece um ambiente completo para o desenvolvimento.

O Apache Tomcat (seção Links) foi o software escolhido para ser o contêiner web desta aplicação, apesar da STS contar com o Pivotal, que é a substituição do Tomcat dentro do Spring.

Configuração do arquivo pom.xml

O arquivo pom.xml deverá conter duas dependências do Spring Framework e as dependências para o uso de Servlet, JSP e JSTL, como mostra a Listagem 2.


spring-context
spring-webmvc
servlet-api
jsp-api
jstl
Listagem 2. Lista de dependências

Assim, a Listagem 3 mostra a configuração do pom.xml.


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
  http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>br.com.cazuzaneto</groupId>
  <artifactId>spring-mvc</artifactId>
  <version>1.0.0-BUILD-SNAPSHOT</version>
  <name>spring-mvc</name>
  <packaging>war</packaging>

  <dependencies>
    <!-- Spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.2.4.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>4.2.4.RELEASE</version>
    </dependency>
    <!-- Servlet -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
Listagem 3. Configuração do pom.xml

Configuração do arquivo web.xml

O arquivo web.XML é usado para realizar a configuração dos servlets da aplicação. Ele é obrigatório desde as versões anteriores a 3.0. Neste exemplo é importante destacar a configuração do servlet do Spring MVC: o Dispatcher Servlet. Ele será responsável por receber todas as requisições feitas à aplicação em questão, como está sendo definido na tag servlet-mapping. Um outro arquivo XML está sendo passado como parâmetro na inicialização do DispatcherServlet: o servlet-context.xml, que é o arquivo de configuração do contexto do DispatcherServlet, como mostra a Listagem 4.


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  <!-- Servlet que irá processar as requisiçoes -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/dispatcherServlet/servlet-context.xml
          </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>
Listagem 4. Configuração do web.xml

Criação e configuração do contexto do DispatcherServlet

O contexto do DispatcherServlet define a infraestrutura do processamento das requisições feitas ao mesmo. Esse contexto pode ser configurado através de um arquivo XML que deverá ser carregado junto com este Servlet. Para isto, será criada uma pasta com o nome “dispatcherServlet” dentro do diretório WEB-INF e, dentro desta pasta será criado um arquivo XML com o nome servlet-context.xml, cuja conteúdo é o mesmo da Listagem 5.


<?xml version="1.0" encoding="UTF-8"?>
  <beans:beans xmlns="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
              http://www.springframework.org/schema/beans 
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context 
              http://www.springframework.org/schema/context/spring-context.xsd">
   
        <!-- Contexto do DispatcherServlet: define a infraestrutura do processamento 
              das requisições feitas ao Servlet (DispatcherServlet) -->
   
        <!-- Ativa o modelo de programação padrão do Spring MVC (@Controller) -->
        <annotation-driven />
   
        <!-- ViewResolver: Resolver as visões retornadas pelos controladores (@Controller) 
              para recursos .jsp que estão do diretório /WEB-INF/views -->
        <beans:bean
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <beans:property name="prefix" value="/WEB-INF/views/" />
              <beans:property name="suffix" value=".jsp" />
        </beans:bean>
   
        <!-- Define o pacote base para o escaneamento das anotações de contexto 
              (@Component, @Repository, @Service, @Controller, etc) -->
        <context:component-scan base-package="br.com.cazuzaneto" />
  </beans:beans>
Listagem 5. Conteúdo do servlet-context.xml

Criação do Controlador

Uma vez configurado o projeto está pronto para ser codificado. Nesta seção será criada uma classe chamada Controlador que irá ser um controlador do Spring MVC. Para isso ela deverá ser anota com @Controller e @RequestMapping. O parâmetro value da anotação @RequestMapping foi preenchido com o carácter "/", indicando que essa classe atenderá as requisições feitas à raiz da aplicação. O método home também está anotado com @RequestMapping e, dessa forma, esse método também receberá requisições tratadas pelo DispatcherServlet. Como o parâmetro value da anotação @RequestMapping do método home não está preenchido, esse método irá receber as anotações feitas à raiz da aplicação que possuam o método GET. Observe o código da Listagem 6.


package br.com.cazuzaneto.cotrolador;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
/**
 * Controla as requisições feitas à raiz da aplicação.
 * 
 * @author Cazuza Neto
 * @version 1.0
 * @since 2016-01-12
 */
@Controller
@RequestMapping(value = "/")
public class Controlador {
 
    /**
     * Atende as requisições GET feitas à raiz da aplicação.
     */
    @RequestMapping(method = RequestMethod.GET)
    public String home(Model model) {
        model.addAttribute("mensagem",
                "Minha primeira aplicação utilizando o Spring Framework MVC!");
        return "home";
    }
 
}
Listagem 6. Classe Controlador

O parâmetro de entrada do método home é uma Interface Model, pois os controladores do Spring MVC interpretam a entrada do usuário (requisições) e transformam-na em um modelo que é representado pela Interface e suas implementações. Dessa forma, pode-se compreender que esta é um recurso do Spring MVC que encapsula a requisição do usuário. Uma Interface Model também é retornada ao usuário.

Observação: A Interface Model é um modelo criado a partir de uma requisição de usuário, porém os métodos mapeados com @RequestMapping podem receber outros parâmetros de entrada, tais como HttpServletRequest, Locale, etc.

Como pode ser visto na Listagem 7, o retorno deste método é uma String. Esse retorno deverá ser tratado por algum ViewResolver, que nesse caso é o InternalResourceViewResolver, bem como foi definido no arquivo servlet-context.xml.


<beans:bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>
Listagem 7. InternalResourceViewResolver

Dessa forma, o InternalResourceViewResolver define que o retorno dos métodos anotados com @RequestMapping serão os recursos .jsp, que estão na página WEB-INF/views e possuem o nome que está sendo retornado como string pelos métodos mapeados. O padrão do Spring MVC é colocar as páginas .jsp dentro da pasta WEB-INF.

Criação da página home.jsp

A página que será retornada ao usuário após a requisição à www.DNS_da_aplicação/cliente será criada na pasta WEB-INF/views. Antes disso, a pasta views deverá ser criada dentro da pasta WEB-INF, seguindo o padrão do Spring. Em seguida a página home.jsp deverá ser criada dentro da pasta views, com o conteúdo da Listagem 8.


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<!DOCTYPE html>
<html>
<head>
<title>Spring MVC</title>
</head>
<body>
  <h1>Olá!</h1>
  <P>${mensagem}</P>
</body>
</html>
Listagem 8. Página home.jsp

A página home.jsp deverá imprimir para o usuário o atributo "mensagem", que foi setado na Interface Model, no método home da classe Controlador.

Executando o projeto

Uma vez configurado e criado, resta apenas usar o Maven para limpeza e criação do projeto. Feito isso, segue a implantação e execução, devendo acessá-la a partir da URL http://localhost:8080/cazuzaneto/.

Imagine criar uma aplicação dessas “no braço” hoje em dia? Cada vez mais precisamos de tempo para agilizar as entregas e perder tempo criando as camadas e os relacionamentos entre elas.

E o que vimos nesse artigo foi apenas um pouco de todo a estrutura do framework Spring MVC. O Container Spring facilita muito, e vimos isso claramente no mapeamento do DispatcherServlet, que é muito flexível, já que pode ser usado com praticamente qualquer fluxo de trabalho, desde que tenha classes adaptadas.