Configuração do Projeto Web com Spring, Hibernate, SpringMVC, Velocity e Maven

Este guia demonstra como configurar uma aplicação web Java utilizando Spring Framework, Hibernate ORM, Spring MVC, Velocity Template Engine e Maven. O foco está na integração dessas tecnologias e na definição de arquivos de configuração essenciais.

Estrutura do Projeto e Configurações Iniciais

A estrutura de diretórios segue o padrão Maven. Os arquivos de configuração devem ser posicionados corretamente, como o arquivo context.xml para a fonte de dados, colocado no diretório META-INF dentro de target/m2e-wtp/web-resources/.

Todas as requisições devem incluir a extensão .html no URL, por exemplo: http://localhost:8080/aplicacao/usuario/index.html.

Arquivos de Configuração

Configuração do Log4j2

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<configuration status="debug">
    <appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
        </Console>
        <RollingFile name="ArquivoRotativo" fileName="logs/app.log"
            filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n" />
            <SizeBasedTriggeringPolicy size="10MB" />
        </RollingFile>
        <File name="Erro" fileName="logs/error.log">
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>
    </appenders>
    <loggers>
        <root level="debug">
            <appender-ref ref="ArquivoRotativo" />
            <appender-ref ref="Console" />
            <appender-ref ref="Erro" />
        </root>
    </loggers>
</configuration>

Configuração do ApplicationContext do Spring

O arquivo applicationContext.xml define beans para fonte de dados, sessão do Hibernate, gerenciamento de transações e integração com Velocity.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:cache="http://www.springframework.org/schema/cache" 
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
    
    <!-- Escaneamento de componentes -->
    <context:component-scan base-package="com.exemplo.principal" />
    
    <!-- Fonte de dados via JNDI -->
    <bean id="fonteDados" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>java:comp/env/jdbc/bancoDadosApp</value>
        </property>
    </bean>

    <!-- Configuração da sessão do Hibernate -->
    <bean id="fabricaSessao"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="fonteDados" />
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.MySQLDialect
                hibernate.hbm2ddl.auto=none
                hibernate.show_sql=true
                hibernate.format_sql=true
                hibernate.cache.use_second_level_cache=false
                hibernate.cache.use_query_cache=false
                hibernate.jdbc.fetch_size=50
                hibernate.jdbc.batch_size=50
                hibernate.connection.autocommit=true
                hibernate.connection.release_mode=auto
                hibernate.current_session_context_class=
                org.springframework.orm.hibernate4.SpringSessionContext
                javax.persistence.validation.mode=none
            </value>
        </property>
        <property name="packagesToScan" value="com.exemplo.modelo" />
    </bean>
    
    <!-- Template do Hibernate -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <property name="sessionFactory" ref="fabricaSessao" />
    </bean>

    <!-- Gerenciador de transações -->
    <bean id="gerenciadorTransacao"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="fabricaSessao" />
    </bean>
    
    <tx:advice id="conselhoTransacao" transaction-manager="gerenciadorTransacao">
        <tx:attributes>
            <tx:method name="salvar*" propagation="REQUIRED" />
            <tx:method name="atualizar*" propagation="REQUIRED" />
            <tx:method name="excluir*" propagation="REQUIRED" />
            <tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="operacaoServico"
            expression="execution(* com.exemplo.servico..*.*(..))" />
        <aop:advisor advice-ref="conselhoTransacao" pointcut-ref="operacaoServico" />
    </aop:config>
    
    <!-- Resolver para upload de arquivos -->
    <bean id="resolvedorMultipart" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"/>
        <property name="maxUploadSize" value="10485760000"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>	
    
    <!-- Configuração do Velocity -->
    <bean id="configuradorVelocity"
        class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath">
            <value>templates</value>
        </property>
        <property name="velocityProperties">
            <props>
                <prop key="file.resource.loader.cache">true</prop>
                <prop key="file.resource.loader.modificationCheckInterval">2</prop>
                <prop key="input.encoding">UTF-8</prop>
                <prop key="output.encoding">UTF-8</prop>
                <prop key="contentType">text/html;charset=UTF-8</prop>
            </props>
        </property>
    </bean>
</beans>

Configuração do Dispatcher Servlet

O dispatch-servlet.xml gerencia controladores MVC, conversores de mensagem e resolução de visão com Velocity.

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

    <context:component-scan base-package="com.exemplo.controlador" />
    
    <mvc:annotation-driven>
         <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/x-www-form-urlencoded;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean> 
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">              
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
                <property name="features">
                    <list>
                        <value>WriteMapNullValue</value>
                        <value>WriteNullStringAsEmpty</value>
                        <value>WriteNullNumberAsZero</value>
                        <value>QuoteFieldNames</value>
                        <value>WriteNullListAsEmpty</value>
                        <value>WriteNullBooleanAsFalse</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
	
    <mvc:resources mapping="/recursos/**" location="/recursos/" cache-period="86400" />
    <mvc:resources mapping="/uploads/**" location="/uploads/" cache-period="86400" />

    <bean class="org.springframework.web.servlet.mvc.WebContentInterceptor"
        p:cacheSeconds="0" p:alwaysUseFullPath="true">
        <property name="cacheMappings">
            <props>
                <prop key="/**/*.html">-1</prop>
            </props>
        </property>
    </bean>

    <bean id="resolvedorVisao"
        class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
        <property name="cache" value="false" />
        <property name="dateToolAttribute" value="data" />
        <property name="prefix" value="" />
        <property name="suffix" value=".vm" />
        <property name="contentType" value="text/html;charset=UTF-8" />
        <property name="exposeSpringMacroHelpers" value="true" />
        <property name="exposeRequestAttributes" value="true" />
        <property name="requestContextAttribute" value="ctx" />
        <property name="exposeSessionAttributes" value="true" />
        <property name="allowSessionOverride" value="true" />
        <property name="allowRequestOverride" value="true" />
        <property name="layoutUrl" value="layout/padrao.vm" />
    </bean>
    
    <bean id="resolvedorMultipart"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <property name="maxUploadSize" value="100000000" />
    </bean>
</beans>

Configuração do web.xml

Define listaners, filtros e o servlet do Spring MVC.

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

    <display-name>aplicacaoDemo</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <filter>
        <filter-name>filtroCodificacao</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>filtroCodificacao</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
	
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
	
    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Configuração do context.xml para Fonte de Dados

<?xml version="1.0" encoding="UTF-8"?>  
<Context>  
    <Resource name="jdbc/bancoDadosApp" auth="Container"   
    type="javax.sql.DataSource"  
    driverClassName="com.mysql.jdbc.Driver"  
    url="jdbc:mysql://localhost:3306/appdb"  
    username="admin"  
    password="senha_segura"  
    maxActive="50"  
    maxIdle="30"  
    maxWait="10000" />  
</Context>

Configuração do Maven (pom.xml)

Inclui dependências para Spring, Hibernate, Velocity, Fastjson e outras bibliotecas.

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.exemplo</groupId>
    <artifactId>aplicacao-web</artifactId>
    <packaging>war</packaging>
    <version>1.0.0</version>
    <name>Aplicação Web Demo</name>
    
    <properties>	
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding> 
        
        <versao.hibernate>4.2.21.Final</versao.hibernate>
        <versao.spring>4.2.3.RELEASE</versao.spring>
        <versao.velocity>1.7</versao.velocity>
        <versao.velocity-tools>2.0</versao.velocity-tools>
        <versao.aspectjweaver>1.8.7</versao.aspectjweaver>
        <versao.fastjson>1.2.8</versao.fastjson>
        <versao.fileupload>1.3.1</versao.fileupload>
        <versao.mysql-connector>5.1.37</versao.mysql-connector>
        <versao.servlet>2.5</versao.servlet>
        <versao.jsp-api>2.1</versao.jsp-api>
        <versao.log4j>2.3</versao.log4j>
        <versao.junit>4.12</versao.junit>
    </properties>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <encoding>utf8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${versao.spring}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${versao.spring}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${versao.spring}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${versao.hibernate}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${versao.aspectjweaver}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>${versao.velocity}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-tools</artifactId>
            <version>${versao.velocity-tools}</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>${versao.fileupload}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${versao.log4j}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${versao.fastjson}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${versao.mysql-connector}</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>${versao.servlet}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>${versao.jsp-api}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${versao.junit}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${versao.spring}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Classes Java

Entidade de Modelo

Classe de entidade para representar um usuário no sistema.

package com.exemplo.modelo;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "usuarios")
public class Usuario implements Serializable {
    
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long identificador;

    @Column(name = "nome_usuario")
    private String nomeUsuario;
    
    @Column(name = "senha")
    private String senha;

    public Long getIdentificador() {
        return identificador;
    }

    public void setIdentificador(Long identificador) {
        this.identificador = identificador;
    }

    public String getNomeUsuario() {
        return nomeUsuario;
    }

    public void setNomeUsuario(String nomeUsuario) {
        this.nomeUsuario = nomeUsuario;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }
}

Camada DAO Base com JDBC

Classe base para operações de banco de dados usando JDBC com Spring.

package com.exemplo.dao.base;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class JdbcDaoBase extends JdbcDaoSupport {

    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Autowired
    public void configurarFonteDados(DataSource fonteDados) {
        super.setDataSource(fonteDados);
        namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(fonteDados);
    }

    public List<map :="" atualizarregistro="" buscarporchave="" campos="" campos.entryset="" campos.remove="" campos.size="" catch="" chaveprimaria="" clausulaset="new" clausulaset.append="" colunas="new" colunas.append="" consultacomin="" consultaunica="" contador="0;" deletarregistro="" e="" else="" entrada="" executaratualizacao="" executarconsulta="" for="" hashmap="" if="" inserirregistro="" int="" list="" lista="" map="" mapaparametros="new" mapaparametros.put="" namedparameterjdbctemplate.queryforlist="" null="" object="" object...="" placeholder="" public="" return="" set="" sql="" string="" stringbuilder="" tabela="" this.getjdbctemplate="" try="" valorchave="campos.get(chavePrimaria);" valores="" valores.append="" values="" where=""></map>

Interface DAO Base com Hibernate

package com.exemplo.dao.base;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;

public interface DaoHibernateBase<T, PK extends Serializable> {
    PK salvar(T entidade);
    void salvarOuAtualizar(T entidade);
    void atualizar(T entidade);
    int atualizarOuDeletarHQL(String hql, Object... valores);
    int atualizarOuDeletarSQL(String sql, Object... valores);
    void deletar(T entidade);
    void deletar(PK identificador);
    void deletar(Collection<T> lista);
    List<T> buscarTodos();
    T buscarPorChave(PK identificador);
    List<T> buscarPorExemplo(T entidade);
    List<?> buscarHQL(String hql, Object... valores);
    List<?> buscarSQL(String sql, Object... valores);
    Object buscarUnicoHQL(String hql, Object... valores);
    Object buscarUnicoSQL(String sql, Object... valores);
    List<T> buscarPorPropriedade(String nomePropriedade, Object valor);
    Object buscarUnicoPorPropriedade(String nomePropriedade, Object valor);
    Query criarConsulta(String hql, Object... valores);
    SQLQuery criarConsultaSQL(String sql, Object... valores);
    Criteria criarCriteria(Criterion... criterios);
    boolean propriedadeEhUnica(String nomePropriedade, Object novoValor, Object valorOriginal);
    List<?> buscarPaginaHQL(String hql, int inicio, int tamanho, Object... valores);
    List<?> buscarPaginaSQL(String sql, int inicio, int tamanho, Object... valores);
    List<?> buscarComInHQL(String hql, String placeholder, List<?> valores);
    List<?> buscarComInSQL(String sql, String placeholder, List<?> valores);
    List<T> buscarPorCriteria(Criterion... criterios);
    List<T> buscarPorCriteria(Order[] ordenacoes, Criterion... criterios);
    List<T> buscarPaginaPorCriteria(int inicio, int tamanho, Order[] ordenacoes, Criterion... criterios);
    Integer contarPorCriteria(Criterion... criterios);
}

Implementação DAO Base com Hibernate

package com.exemplo.dao.base;

import java.io.Serializable;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.exemplo.utilitarios.ReflexaoUtilitarios;

public abstract class DaoHibernateBaseImpl<T, PK extends Serializable> {
    
    private static final Logger logger = LogManager.getLogger(DaoHibernateBaseImpl.class);

    protected Class<T> classeEntidade;

    @Autowired
    protected HibernateTemplate templateHibernate;

    public DaoHibernateBaseImpl() {
        this.classeEntidade = ReflexaoUtilitarios.obterTipoGenericoSuperclasse(getClass());
    }

    protected Session obterSessao() {
        return templateHibernate.getSessionFactory().getCurrentSession();
    }

    public void salvar(T entidade) {
        templateHibernate.save(entidade);
    }

    public void atualizar(T entidade) {
        templateHibernate.update(entidade);
    }

    public void salvarOuAtualizar(T entidade) {
        templateHibernate.saveOrUpdate(entidade);
    }

    public void deletar(T entidade) {
        if (entidade != null) {
            templateHibernate.delete(entidade);
        }
    }

    public void deletar(PK identificador) {
        if (identificador != null) {
            deletar(obter(identificador));
        }
    }

    public T obter(PK identificador) {
        return (T) templateHibernate.get(classeEntidade, identificador);
    }

    public List<T> buscarTodos() {
        return buscarPorCriteria();
    }

    public List<T> buscarPorPropriedade(String nomePropriedade, Object valor) {
        Criterion criterio = Restrictions.eq(nomePropriedade, valor);
        return buscarPorCriteria(criterio);
    }

    public T buscarUnicoPorPropriedade(String nomePropriedade, Object valor) {
        Criterion criterio = Restrictions.eq(nomePropriedade, valor);
        return (T) criarCriteria(criterio).uniqueResult();
    }

    public int executarAtualizacao(String hql, Object... valores) {
        return criarConsulta(hql, valores).executeUpdate();
    }

    public List<T> buscar(String hql, Object... valores) {
        return criarConsulta(hql, valores).list();
    }

    public List<T> buscarPagina(String hql, int inicio, int tamanho, Object... valores) {
        return criarConsulta(hql, valores).setFirstResult(inicio).setMaxResults(tamanho).list();
    }

    public List<T> buscarComIn(String hql, String placeholder, List<?> valores) {
        return criarConsultaComIn(hql, placeholder, valores).list();
    }

    public T buscarUnico(String hql, Object... valores) {
        return (T) criarConsulta(hql, valores).uniqueResult();
    }

    public Query criarConsulta(String hql, Object... valores) {
        Query consulta = obterSessao().createQuery(hql);
        if (valores != null) {
            for (int i = 0; i < valores.length; i++) {
                consulta.setParameter(i, valores[i]);
            }
        }
        return consulta;
    }

    public Query criarConsultaComIn(String hql, String placeholder, List<?> valores) {
        Query consulta = obterSessao().createQuery(hql);
        if (valores != null) {
            consulta.setParameterList(placeholder, valores);
        }
        return consulta;
    }

    public List<T> buscarPorCriteria(Criterion... criterios) {
        return criarCriteria(criterios).list();
    }

    public Criteria criarCriteria(Criterion... criterios) {
        Criteria criteria = obterSessao().createCriteria(classeEntidade);
        for (Criterion c : criterios) {
            criteria.add(c);
        }
        return criteria;
    }

    public boolean propriedadeEhUnica(String nomePropriedade, Object novoValor, Object valorOriginal) {
        if (novoValor == null || novoValor.equals(valorOriginal)) {
            return true;
        }
        Object objeto = buscarUnicoPorPropriedade(nomePropriedade, novoValor);
        return (objeto == null);
    }

    public String obterNomeChavePrimaria() {
        ClassMetadata metadados = templateHibernate.getSessionFactory().getClassMetadata(classeEntidade);
        return metadados.getIdentifierPropertyName();
    }

    public SQLQuery criarConsultaSQL(String sql, Object... valores) {
        SQLQuery consultaSQL = obterSessao().createSQLQuery(sql);
        if (valores != null) {
            for (int i = 0; i < valores.length; i++) {
                consultaSQL.setParameter(i, valores[i]);
            }
        }
        return consultaSQL;
    }
}

DAO de Usuário com Hibernate

package com.exemplo.dao;

import java.io.Serializable;
import org.springframework.stereotype.Repository;
import com.exemplo.dao.base.DaoHibernateBaseImpl;
import com.exemplo.modelo.Usuario;

@Repository
public class UsuarioDaoHQL extends DaoHibernateBaseImpl<Usuario, Serializable> {
    
    public Usuario autenticar(String nomeUsuario, String senha) {
        String hql = "FROM Usuario WHERE nomeUsuario = ? AND senha = ?";
        return this.buscarUnico(hql, nomeUsuario, senha);
    }
}

DAO de Usuário com JDBC

package com.exemplo.dao;

import java.util.Map;
import org.springframework.stereotype.Repository;
import com.exemplo.dao.base.JdbcDaoBase;
import com.exemplo.modelo.Usuario;

@Repository
public class UsuarioDaoJDBC extends JdbcDaoBase {
    
    public Usuario autenticar(String nomeUsuario, String senha) {
        String sql = "SELECT * FROM usuarios WHERE nome_usuario = ? AND senha = ?";
        Map<String, Object> resultado = this.consultaUnica(sql, nomeUsuario, senha);
        Usuario usuario = null;
        if (resultado != null) {
            usuario = new Usuario();
            usuario.setIdentificador(resultado.get("identificador") != null ? 
                Long.parseLong(resultado.get("identificador").toString()) : null);
            usuario.setNomeUsuario(resultado.get("nome_usuario") != null ? 
                resultado.get("nome_usuario").toString() : null);
            usuario.setSenha(resultado.get("senha") != null ? 
                resultado.get("senha").toString() : null);
        }
        return usuario;
    }
}

Serviço de Negócio

package com.exemplo.servico;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.exemplo.modelo.Usuario;
import com.exemplo.dao.UsuarioDaoHQL;
import com.exemplo.dao.UsuarioDaoJDBC;

@Transactional(readOnly = false)
@Service("servicoUsuario")
public class ServicoUsuario {

    @Autowired
    private UsuarioDaoHQL daoHQL;
    
    @Autowired
    private UsuarioDaoJDBC daoJDBC;
    
    public Usuario autenticarComHQL(String nomeUsuario, String senha) {
        return daoHQL.autenticar(nomeUsuario, senha);
    }
    
    public Usuario autenticarComJDBC(String nomeUsuario, String senha) {
        return daoJDBC.autenticar(nomeUsuario, senha);
    }
}

Controlador MVC

package com.exemplo.controlador;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.exemplo.modelo.Usuario;
import com.exemplo.servico.ServicoUsuario;

@Controller
@RequestMapping("/usuario")
public class ControladorUsuario {
    
    @Autowired
    private ServicoUsuario servicoUsuario;
    
    @RequestMapping(value = "/pagina-inicial", method = RequestMethod.GET)
    public String exibirPaginaInicial(HttpServletRequest requisicao, HttpServletResponse resposta) {
        return "pagina-inicial";
    }
    
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String exibirFormularioLogin(HttpServletRequest requisicao, HttpServletResponse resposta) {
        return "login";
    }
    
    @RequestMapping(value = "/autenticar", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> processarLogin(Usuario usuario, HttpServletRequest requisicao,
        HttpServletResponse resposta) {
        
        Map<String, String> respostaMap = new HashMap<>();
        
        if (usuario == null || usuario.getNomeUsuario() == null || usuario.getSenha() == null) {
            respostaMap.put("status", "erro");
            respostaMap.put("mensagem", "Credenciais não fornecidas");
            return respostaMap;
        }
        
        Usuario usuarioAutenticado = servicoUsuario.autenticarComJDBC(usuario.getNomeUsuario(), usuario.getSenha());
        
        if (usuarioAutenticado != null) {
            respostaMap.put("status", "sucesso");
            respostaMap.put("mensagem", "Autenticação bem-sucedida");
        } else {
            respostaMap.put("status", "erro");
            respostaMap.put("mensagem", "Falha na autenticação");
        }
        return respostaMap;
    }
}

Classe Utilitária de Reflexão

package com.exemplo.utilitarios;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public final class ReflexaoUtilitarios {

    private static final Logger logger = LogManager.getLogger(ReflexaoUtilitarios.class);

    private ReflexaoUtilitarios() {
    }

    public static Object obterValorCampo(Object objeto, String nomeCampo) {
        Field campo = obterCampoDeclarado(objeto.getClass(), nomeCampo);
        if (campo == null) {
            throw new IllegalArgumentException("Campo não encontrado: " + nomeCampo);
        }
        tornarAcessivel(campo);
        try {
            return campo.get(objeto);
        } catch (IllegalAccessException e) {
            logger.error("Erro ao acessar campo", e);
            return null;
        }
    }

    public static void definirValorCampo(Object objeto, String nomeCampo, Object valor) {
        Field campo = obterCampoDeclarado(objeto.getClass(), nomeCampo);
        if (campo == null) {
            throw new IllegalArgumentException("Campo não encontrado: " + nomeCampo);
        }
        tornarAcessivel(campo);
        try {
            campo.set(objeto, valor);
        } catch (IllegalAccessException e) {
            logger.error("Erro ao definir campo", e);
        }
    }

    protected static Field obterCampoDeclarado(Class<?> classe, String nomeCampo) {
        for (Class<?> classeAtual = classe; classeAtual != Object.class; classeAtual = classeAtual.getSuperclass()) {
            try {
                return classeAtual.getDeclaredField(nomeCampo);
            } catch (NoSuchFieldException e) {
                // Continua para a superclasse
            }
        }
        return null;
    }

    protected static void tornarAcessivel(Field campo) {
        if (!Modifier.isPublic(campo.getModifiers()) || !Modifier.isPublic(campo.getDeclaringClass().getModifiers())) {
            campo.setAccessible(true);
        }
    }

    @SuppressWarnings("unchecked")
    public static Class<?> obterTipoGenericoSuperclasse(Class<?> classe) {
        return obterTipoGenericoSuperclasse(classe, 0);
    }

    @SuppressWarnings("unchecked")
    public static Class<?> obterTipoGenericoSuperclasse(Class<?> classe, int indice) {
        Type tipoGenerico = classe.getGenericSuperclass();
        if (!(tipoGenerico instanceof ParameterizedType)) {
            logger.warn("Superclasse não é parametrizada: " + classe.getSimpleName());
            return Object.class;
        }
        Type[] argumentos = ((ParameterizedType) tipoGenerico).getActualTypeArguments();
        if (indice < 0 || indice ≥ argumentos.length) {
            logger.warn("Índice inválido para tipo genérico: " + indice);
            return Object.class;
        }
        if (argumentos[indice] instanceof Class) {
            return (Class<?>) argumentos[indice];
        }
        logger.warn("Tipo genérico não é classe: " + classe.getSimpleName());
        return Object.class;
    }

    public static List<?> extrairPropriedadesParaLista(Collection<?> colecao, String nomePropriedade) throws Exception {
        List<Object> lista = new ArrayList<>();
        for (Object objeto : colecao) {
            lista.add(PropertyUtils.getProperty(objeto, nomePropriedade));
        }
        return lista;
    }

    public static String extrairPropriedadesParaString(Collection<?> colecao, String nomePropriedade, String separador) throws Exception {
        List<?> lista = extrairPropriedadesParaLista(colecao, nomePropriedade);
        return StringUtils.join(lista, separador);
    }
}

Esta configuração fornece uma base completa para uma aplicação web Java moderna, integrando Spring para injeção de dependência e transações, Hibernate para persistência, Spring MVC para camada web, Velocity para renderização de templates e Maven para gerenciamento de dependências e build.

Tags: Spring Framework Hibernate ORM Spring MVC Velocity Template Engine maven

Publicado em 6-17 00:49