您的位置:首页 > 编程语言 > Java开发

[置顶] maven搭建SpringMVC+Spring+hibernate+JPA

2016-03-27 23:39 567 查看

maven搭建SpringMVC+Spring+hibernate+JPA

JPA Java Persistence API,JPA吸收了很多ORM框架的持久化思想,是在ORM框架的基础上,抽象出来的一层规范。使用JPA你可以随时更换底层支持JPA的ORM框架,而不需要与ORM绑死,同时Spring对JPA的支持,使得JPA写出的代码很精简。

环境搭建

maven 依赖配置

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.jdk>1.6</project.build.jdk>
<spring.version>3.2.2.RELEASE</spring.version>
<spring.data.jpa.version>1.4.3.RELEASE</spring.data.jpa.version>
<junit.version>4.11</junit.version>
<fastjson.version>1.2.7</fastjson.version>
<commonslang3.verison>3.1</commonslang3.verison>
<common.io.version>2.4</common.io.version>
<common.dbcp.version>1.4</common.dbcp.version>
<common.file.version>1.3</common.file.version>
<servlet.api.version>3.0.1</servlet.api.version>
<servlet.jsp.version>2.2</servlet.jsp.version>
<hibernate.jpa.version>1.0.1.Final</hibernate.jpa.version>
<hibernate.core.version>3.5.5-Final</hibernate.core.version>
<hibernate.validator.version>4.3.1.Final</hibernate.validator.version>
<mysql.version>5.1.6</mysql.version>
<quartz.version>1.8.6</quartz.version>
<logback.version>1.1.2</logback.version>
<java.mail.version>1.4.5</java.mail.version>
<asm.version>3.3.1</asm.version>
</properties>

<dependencies>
<!-- asm begin -->
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>${asm.version}</version>
</dependency>
<!-- asm end -->
<!-- mail begin -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${java.mail.version}</version>
</dependency>
<!-- mail end -->
<!-- logback begin -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- logback end -->
<!-- database begin -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${common.dbcp.version}</version>
</dependency>
<!-- database end -->
<!-- common begin -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commonslang3.verison}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${common.io.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${common.file.version}</version>
</dependency>
<!-- common end -->

<!-- SPRING BEGIN -->
<!-- 引用此类会自动加载spring的core(其它组件要都要使用到这个包里的类,是其它组件的基本核心,外部依赖Commons Logging)、beans(包含访问配置文件、创建和管理bean
以及进行DI AOP 操作相关的所有类)、aop(提供AOP(面向切面编程)的实现 )、context包(为Spring 核心提供了大量扩展。可以找到使用Spring
ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 提供对事务的支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 对JUNIT等测试框架的简单封装 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- 这个jar 文件包含Spring MVC 框架相关的所有类。包括框架的Servlets,Web MVC框架,控制器和视图支持。当然,如果你的应用使用了独立的MVC
框架,则无需这个JAR 文件里的任何类。 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 这个jar是spring扩展 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring 对jpa的支持 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring.data.jpa.version}</version>
</dependency>
<!-- SPRING END -->
<!-- hibernate start -->
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>${hibernate.jpa.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.core.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.core.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
<!-- hibernate end -->

<!-- fastJson start -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- fastjson end -->

<!-- quartz start -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
<!-- quartz end -->

<!-- junit start -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- junit end -->
<!--servlet start -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${servlet.jsp.version}</version>
<scope>provided</scope>
</dependency>
<!--servlet end -->
</dependencies>


WEB配置文件

<!-- spring的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 加载配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext.xml
classpath*:/applicationContext-poj.xml
</param-value>
</context-param>
<!-- 解决字符串乱码问题 -->
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- sping mvc 配置 所有.do的请求都经过spingmvc的servlet -->
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>


spring的applicationContext配置文件

<!-- 使用annotation 自动注册bean, 并保证@Required、@Autowired的属性被注入 -->
<context:component-scan base-package="com">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>

<!-- 将配置统一提取到properties中管理 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>

<!-- 数据源配置, 使用DBCP数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- Connection Info -->
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- Connection Pooling Info -->
<property name="maxActive" value="${dbcp.maxActive}" />
<property name="maxIdle" value="${dbcp.maxIdle}" />
<property name="defaultAutoCommit" value="false" />
<!-- 连接Idle一个小时后超时 -->
<property name="timeBetweenEvictionRunsMillis" value="3600000" />
<property name="minEvictableIdleTimeMillis" value="3600000" />
</bean>

<!--指定实现JPA的适配器-->
<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>

<!-- JPA实体管理工厂的配置 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
<property name="packagesToScan" value="com"/><!--待扫描的实体类包,不再需要persistence.xml了-->
<property name="jpaProperties">
<props>
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<!-- Jpa 事务配置 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<!-- Spring Data Jpa配置 -->
<jpa:repositories base-package="com.durd"  transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/>

<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

<!-- JSR303 Validator定义 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />


spring mvc配置文件

<!-- 自动扫描且只扫描@Controller -->
<context:component-scan base-package="com" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!--
<mvc:annotation-driven/>
-->
<!-- 将无法mapping到Controller的path交给default servlet handler处理 -->
<!--
<mvc:default-servlet-handler/>
-->

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

<!-- 定义JSP文件的位置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>


问题总结

parent里是dependencies还是dependencyManagement

之前看到很多项目把dependency都定义在了dependencyManagement中,这样有一个好处就是我再dependencyManagement中定义的依赖并不会被项目module加载,如果module需要加载这些依赖,只需要在module中dependencies中声明下groupId跟artifactId即可,不需要再声明version。但在我们的项目中依赖的jar包比较单一,没有使用dependencyManagement而是直接使用的dependencies,这样管理jar包比较统一,否则还需要两个地方维护jar包。

项目里jar包依赖版本冲突

在引用jar的过程中,开始只是定义了一些基础的jar包。但是一保存pom发现很多依赖的jar都被引入近来了,这里很多框架都是依赖很多相同的基础包,有些会存在jar包冲突问题,但是maven的依赖的传递性,并不会帮我们自动解决这些版本冲突问题,只会遵守maven的传递性规则(第一原则:路径最近者优先(A->B->C->D(1.0),A->E->D(2.0)那么A的依赖应该是D2.0而不是D1.0)

第二原则:路径相等时,第一声明者优先。)所以这里需要我们自己去解决这些问题。建议先声明基础jar包,在去声明框架级jar包,这样对项目的基础jar包就有比较清晰的了解。同时借助maven提供的依赖分析命令可以很容易的解决这些问题。

profiles配置没有编译到.properties配置文件中

刚开始也是自己大意了,在application.xml中使用了很都${username}标识符把配置项都提到了application.properties配置文件中。

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>


在application.properties中也使用了替换符号,所有的配置文件都弄到了maven提供的profiles中。

<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>profiles/dev.properties</filter>
</filters>
</build>
</profile>
<profile>
<id>test</id>
<build>
<filters>
<filter>profiles/test.properties</filter>
</filters>
</build>
</profile>
<profile>
<id>online</id>
<build>
<filters>
<filter>profiles/pro.properties</filter>
</filters>
</build>
</profile>
</profiles>


但是在编译中发现application.properties中的配置没有被dev.properties替换,原因是maven编译时没有指定配置文件的目录,并开始filter。

<build>
<finalName>web</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
<include>**/*.conf</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.ftl</include>
<include>**/*.sql</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>


启动报错

class path resource [com/mchange/v2/c3p0/QueryConnectionTester.class] cannot be opened because it does not exist


这个问题太奇怪了,我在项目里用的连接池是dbcp但是不知道为什么会需要引用c3p0的jar包,排查了一下,发现

spring data jpa配置时

<jpa:repositories base-package="com"  transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"/>


com的级别太大了,可能引入了其他的类,导致提示c3p0的类找不到错误。

需要注意的一点,自动扫描

一般spring的配置文件跟springMVC的配置文件都会分开配置,扫描时,会利用include-filter跟exclude-filter进行控制,一般spring配置文件会配置成

<!-- 使用annotation 自动扫描bean, 并保证@Required、@Autowired的属性被注入 -->
<context:component-scan base-package="com.xxx">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>


而springMVC则配置为

<!-- 自动扫描且只扫描@Controller -->
<context:component-scan base-package="com.xxx.xxx" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>


如何2个扫描器有重合的类,可能会引起问题是事务不起作用,解决的方法是添加use-default-filters=”false”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: