Tutorial Spring MVC

Neste Tutorial do Spring MVC, aprenderemos como desenvolver uma aplicação web Spring MVC usando o Spring Tool Suite. O framework Spring MVC é amplamente utilizado para aplicações web Java.

Spring MVC

Assim como o Struts Framework, o Spring MVC também é baseado nas tecnologias Java EE Servlet e JSP e implementa o padrão de design ModelViewController.

Tutorial do Spring MVCNeste Tutorial do Spring MVC, aprenderemos como desenvolver uma aplicação web Spring MVC usando o Spring Tool Suite. O framework Spring MVC é amplamente utilizado para aplicações web em Java. Assim como o Framework Struts, o Spring MVC também é baseado nas tecnologias Java EE Servlet e JSP e implementa o padrão de design Model-View-Controller.

Já vimos anteriormente como funciona a Injeção de Dependência do Spring e neste tutorial aprenderemos como criar uma aplicação web simples usando o framework Spring MVC. Podemos usar o Eclipse ou IntelliJ IDE para o desenvolvimento de projetos Spring, mas a SpringSource fornece o Spring Tool Suite (STS), que é um IDE baseado no Eclipse e vem com o VMware vFabric tc Server integrado, que é construído em cima do contêiner Apache Tomcat e otimizado para aplicações baseadas no Spring. Eu vou usar o STS para o tutorial de Spring MVC e outros tutoriais futuros, pois isso facilita a vida do desenvolvedor, fornecendo as seguintes funcionalidades:

  • Suporte para criação de aplicações Spring (MVC, Rest, Batch, etc.) a partir do zero. Veremos em breve neste tutorial de Spring MVC como é fácil criar um projeto Spring MVC.
  • Fornece recursos úteis, como criação de arquivos de configuração do Spring, análise de arquivos de configuração e classes para fornecer informações úteis sobre eles.
  • Validação automática da aplicação Spring
  • Suporte a refatoração para facilitar as alterações no projeto, as alterações são refletidas nos arquivos de configuração também.
  • Suporte de assistência de código não apenas para classes, mas também para arquivos de configuração. Gosto muito desse recurso porque na maioria das vezes precisamos saber o que podemos usar e seus detalhes.
  • Melhor suporte para Programação Orientada a Aspectos (AOP) por meio da integração do AspectJ.

Olhando para todos os recursos que o STS oferece, eu fui convencido por isso e decidi usá-lo para a aplicação Spring e até agora estou muito feliz com isso. Basta baixar o STS da página de download oficial do STS e instalá-lo. Estou usando o STS 3.4.0.RELEASE que é baseado no lançamento do Eclipse 4.3.1. Se você não quiser usar o STS e quiser obter suas funcionalidades no Eclipse existente, então você precisa instalar seu plugin no Eclipse Marketplace. Use a imagem abaixo como referência e certifique-se de escolher a versão correta do STS para instalação. O plugin abaixo é bom para o Eclipse Kepler. Se você não quiser usar o servidor SpringSource, você pode implantar a aplicação em qualquer outro contêiner Java EE, como Tomcat, JBoss etc. Para este tutorial, usarei o servidor que vem com o STS, mas testei a aplicação exportando-a como arquivo WAR para um servidor tomcat separado e está funcionando bem. Agora que nosso ambiente de servidor e IDE está pronto, vamos criar nosso primeiro projeto Spring MVC. Os passos abaixo são válidos tanto para o STS quanto para o Eclipse com plugins do STS.

Criando Aplicação Spring MVC no STS ou Eclipse

Passo 1: Crie um Novo Projeto Spring no menu. Passo 2: Na nova janela do projeto, dê o nome de “SpringMVCExample” e escolha o modelo “Projeto Spring MVC”. Se estiver usando este modelo pela primeira vez, o STS irá baixá-lo do site da SpringSource. Se desejar, pode adicionar o projeto a qualquer conjunto de trabalho. Passo 3: Quando o modelo for baixado, na próxima tela você precisará fornecer o nome do pacote de nível superior. Este pacote será usado como pacote base para os componentes Spring. Passo 4: Assim que o projeto for criado pelo modelo Spring MVC, ele ficará como na imagem abaixo. Não se preocupe se não ver a classe User.java, os arquivos login.jsp e user.jsp, eles foram adicionados por mim mais tarde. Se o seu projeto não estiver compilado e você ver alguns erros, execute Maven/Atualizar Projeto. Certifique-se de marcar as opções “Forçar atualização de Snapshots/Lançamentos”, consulte a imagem abaixo. No geral, o projeto se parece com qualquer outra aplicação web baseada em Maven com alguns arquivos de configuração do Spring. Agora é hora de analisar as diferentes partes do projeto e estendê-lo um pouco.

Dependências do Spring MVC

Nosso arquivo pom.xml gerado parece o seguinte.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>SpringMVCExample</artifactId>
	<name>SpringMVCExample</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>4.0.0.RELEASE</org.springframework-version>
		<org.aspectj-version>1.7.4</org.aspectj-version>
		<org.slf4j-version>1.7.5</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</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>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>        
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

O artifactId será o servlet-context para a aplicação web, então você pode alterá-lo se quiser algo diferente. Existem algumas propriedades definidas para as versões do Spring Framework, AspectJ e SLF4j, percebi que elas não refletiam as últimas versões, então as alterei para a versão estável mais recente até hoje. As dependências do projeto que me interessam são;

  • spring-context: Dependência do Spring Core. Observe a exclusão do commons logging em favor do SLF4J.
  • spring-webmvc: Artefato Spring para suporte MVC
  • aspectjrt: Referência API do AspectJ
  • SLF4J e Log4j: Para fins de registro, o Spring é muito fácil de configurar para log4j ou API de Log do Java por causa da integração com SLF4J.
  • javax.inject – API JSR330 para injeção de dependência

Há outras dependências adicionadas, como Servlet, JSP, JSTL e API JUnit, mas para aplicativos iniciantes, podemos ignorá-las.

Tutorial do Spring MVC – Configuração do Log4j

O arquivo log4j.xml gerado parece com o seguinte.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="https://jakarta.apache.org/log4j/">

	<!-- Appenders -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p: %c - %m%n" />
		</layout>
	</appender>
	
	<!-- Application Loggers -->
	<logger name="com.journaldev.spring">
		<level value="info" />
	</logger>
	
	<!-- 3rdparty Loggers -->
	<logger name="org.springframework.core">
		<level value="info" />
	</logger>
	
	<logger name="org.springframework.beans">
		<level value="info" />
	</logger>
	
	<logger name="org.springframework.context">
		<level value="info" />
	</logger>

	<logger name="org.springframework.web">
		<level value="info" />
	</logger>

	<!-- Root Logger -->
	<root>
		<priority value="warn" />
		<appender-ref ref="console" />
	</root>
	
</log4j:configuration>

Observe que está imprimindo tudo no console; podemos facilmente adicionar anexadores para redirecionar o log para arquivos.

Tutorial do Spring MVC – Configuração do Descritor de Implantação

Vamos analisar nosso web.xml.

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

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

ContextLoaderListener vincula o ciclo de vida do ApplicationContext ao ciclo de vida do ServletContext e automatiza a criação do ApplicationContext. ApplicationContext é o local para os beans do Spring, e podemos fornecer sua configuração por meio do parâmetro de contexto contextConfigLocation. O arquivo root-context.xml fornece os detalhes de configuração para o WebApplicationContext. DispatcherServlet é a classe controladora para aplicativos Spring MVC, e todas as solicitações do cliente são manipuladas por este servlet. A configuração está sendo carregada do arquivo servlet-context.xml.

Tutorial do Spring MVC – Arquivos de Configuração

Arquivo root-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
		
</beans>

Aqui podemos definir beans compartilhados, por enquanto não há nada nele. Código do arquivo servlet-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<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>
	
	<context:component-scan base-package="com.journaldev.spring" />	
	
</beans:beans>

Assim é como o arquivo de configuração padrão do Spring se parece, apenas imagine escrever tudo isso por conta própria e você começará a gostar da ferramenta STS. O elemento annotation-driven é usado para informar ao servlet do Controlador que serão usadas anotações para configurações de beans. O elemento resources define o local onde podemos colocar arquivos estáticos, como imagens, páginas HTML etc., que não queremos que passem pelo framework Spring. InternalResourceViewResolver é o resolvedor de visualização, podemos fornecer o local das páginas de visualização por meio das propriedades de prefixo e sufixo. Portanto, todas as nossas páginas JSP devem estar no diretório /WEB-INF/views/. O elemento context:component-scan é usado para fornecer a localização do pacote base para escanear classes de Controlador. Lembre-se do valor do pacote de nível superior fornecido no momento da criação do projeto, é o mesmo valor que está sendo usado aqui.

Classe Controladora do Spring MVC

HomeController é criado automaticamente com o método home(), embora eu tenha estendido um pouco adicionando os métodos loginPage() e login().

package com.journaldev.spring;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
	
	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
	
	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! The client locale is {}.", locale);
		
		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
		
		String formattedDate = dateFormat.format(date);
		
		model.addAttribute("serverTime", formattedDate );
		
		return "home";
	}
	
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String loginPage(Locale locale, Model model) {
		return "login";
	}
	
	@RequestMapping(value = "/home", method = RequestMethod.POST)
	public String login(@Validated User user, Model model) {
		model.addAttribute("userName", user.getUserName());
		return "user";
	}
}

@Controller é usada para indicar que é uma classe de controlador da web. @RequestMapping é usada com classes e métodos para redirecionar a solicitação do cliente para um método manipulador específico. Observe que os métodos manipuladores estão retornando String, que deve ser o nome da página de visualização a ser usada como resposta. Como você pode ver, estamos tendo três métodos retornando strings diferentes, então precisamos criar páginas JSP com o mesmo nome. Observe que o método login() será chamado com o método HTTP como POST, então estamos esperando alguns dados de formulário aqui. Portanto, temos a classe de modelo User e ela é marcada para validação usando a anotação @Validated . Cada método contém Model como argumento e podemos definir atributos para serem usados posteriormente nas páginas de resposta JSP.

Classes de Modelo Spring MVC

As classes de modelo são usadas para armazenar variáveis de formulário, nosso bean de modelo de usuário parece abaixo.

package com.journaldev.spring;

public class User {

	private String userName;

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
	
}

A simple java bean with the variable name and its getter and setter methods.

Tutorial Spring MVC – Páginas de Visualização

Temos três páginas JSP como abaixo. Código de home.jsp:

<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world!  
</h1>

<P>  The time on the server is ${serverTime}. </P>
</body>
</html>

Observe o uso da Linguagem de Expressão JSP para obter os valores dos atributos. Código de login.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
</head>
<body>
<form action="home" method="post">
<input type="text" name="userName"><br>
<input type="submit" value="Login">
</form>
</body>
</html>

A simple JSP page for the user to provide the userName as input. Notice that form variable name is same as User class variable name. Also, form action is “home” and method is “post”. It’s clear that HomeController login() method will handle this request. user.jsp code:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User Home Page</title>
</head>
<body>
<h3>Hi ${userName}</h3>
</body>
</html>

Página inicial simples para o usuário onde o nome de usuário é exibido, observe que estamos definindo este atributo no método de login.

Exemplo de Aplicação de Teste Spring MVC

Nossa aplicação está pronta para execução, basta executá-la no VMware tc Server ou em sua escolha de qualquer outro contêiner de servlet, você obterá as páginas abaixo como resposta. Isso é tudo para o Tutorial Spring MVC, você pode ver como é fácil criar uma aplicação Spring MVC usando os plugins do STS. O tamanho do código é muito pequeno e a maioria das configurações é tratada pelo Spring MVC para que possamos focar na lógica de negócios. Baixe o projeto de exemplo Spring MVC no link abaixo e brinque com ele.

Baixar Projeto Spring MVC

Source:
https://www.digitalocean.com/community/tutorials/spring-mvc-tutorial