Spring+SpringMVC+JPA

Spring+SpringMVC+JPA

SpringMVC是越来越火,自己也弄一个Spring+SpringMVC+JPA的简单框架。

1、搭建环境。

1)下载Spring3.1.2的发布包;Hibernate4.1.7的发布包(没有使用hibernate的API,只是使用了它对JPA的实现);下载BoneCP连接池框架及其依赖的jar,下载缓存框架ehcache,全部所用到的jar包如下:  

?

antlr-2.7.7.jar

bonecp-0.7.1.RELEASE.jar

bonecp-provider-0.7.1-rc2.jar

bonecp-spring-0.7.1-rc1.jar

com.springsource.net.sf.cglib-2.2.0.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.apache.commons.logging-1.1.1.jar

com.springsource.org.aspectj.weaver-1.6.12.RELEASE.jar

dom4j-1.6.1.jar

ehcache-core-2.5.2.jar<br>ehcache-spring-annotations-1.2.0.jar

guava-12.0.jar

hibernate-commons-annotations-4.0.1.Final.jar

hibernate-core-4.1.7.Final.jar

hibernate-entitymanager-4.1.7.Final.jar

hibernate-jpa-2.0-api-1.0.1.Final.jar

javassist-3.15.0-GA.jar

jboss-logging-3.1.0.GA.jar

jboss-transaction-api_1.1_spec-1.0.0.Final.jar

log4j-1.2.17.jar

mysql-connector-java-5.1.6-bin.jar

org.springframework.aop-3.1.2.RELEASE.jar

org.springframework.asm-3.1.2.RELEASE.jar

org.springframework.aspects-3.1.2.RELEASE.jar

org.springframework.beans-3.1.2.RELEASE.jar

org.springframework.context-3.1.2.RELEASE.jar

org.springframework.context.support-3.1.2.RELEASE.jar

org.springframework.core-3.1.2.RELEASE.jar

org.springframework.expression-3.1.2.RELEASE.jar

org.springframework.instrument-3.1.2.RELEASE.jar

org.springframework.instrument.tomcat-3.1.2.RELEASE.jar

org.springframework.jdbc-3.1.2.RELEASE.jar

org.springframework.jms-3.1.2.RELEASE.jar

org.springframework.orm-3.1.2.RELEASE.jar

org.springframework.oxm-3.1.2.RELEASE.jar

org.springframework.test-3.1.2.RELEASE.jar

org.springframework.transaction-3.1.2.RELEASE.jar

org.springframework.web-3.1.2.RELEASE.jar

org.springframework.web.portlet-3.1.2.RELEASE.jar

org.springframework.web.servlet-3.1.2.RELEASE.jar

slf4j-api-1.6.1.jar

slf4j-nop-1.6.1.jar

2)建立一个WebProject,引入上述jar包

2.1)web.xml配置如下:

复制代码

<?xmlversion="1.0"encoding="UTF-8"?>

<web-appversion="2.5"

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_2_5.xsd">

<!--配置Log4j-->

<context-param>

<param-name>webAppRootKey</param-name>

<param-value>spring_springmvc_jpa.root</param-value>

</context-param>

<context-param>

<param-name>log4jConfigLocation</param-name>

<param-value>classpath:log4j.properties</param-value>

</context-param>

<listener>

<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>

</listener>

<!--配置编码过滤器-->

<filter>

<filter-name>characterEncodingFilter</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>

</filter>

<filter-mapping>

<filter-name>characterEncodingFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<!--配置Spring监听器-->

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/applicationContext.xml</param-value>

</context-param>

<!--Spring刷新Introspector防止内存泄露-->

<listener>

<listener-class>

org.springframework.web.util.IntrospectorCleanupListener

</listener-class>

</listener>

<!--SpringMVC核心分发器-->

<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/dispatcher-servlet.xml</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<!--映射*.do的请求-->

<servlet-mapping>

<servlet-name>dispatcherServlet</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

复制代码

2.2)在src目录下建立log4j.properties日志配置文件,内容如下:

复制代码

log4j.rootLogger=INFO,stdout,file

#应用于控制台

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.Target=System.out

log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-ddHH\:mm\:ss,SSS}[%c]-[%p]%m%n

#应用于文件

log4j.appender.file=org.apache.log4j.DailyRollingFileAppender

log4j.appender.file.File=${spring_springmvc_jpa.root}/app.log

log4j.appender.file.layout=org.apache.log4j.PatternLayout

log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss,SSS}[%t][%c][%p]-%m%n

log4j.logger.org.hibernate.tool.hbm2ddl=debug

复制代码

2.3)在src目录下建立缓存的配置文件ehcache.xml,内容如下:

复制代码

<?xmlversion="1.0"encoding="UTF-8"?>

<ehcachexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="ehcache.xsd"

updateCheck="true"monitoring="autodetect"

dynamicConfig="true">

<!--<diskStorepath="java.io.tmpdir"/>-->

<!--配置缓存文件存放路径-->

<diskStorepath="E:/CacheTmpDir"/>

<!--

1.必须要有的属性:

name:cache的名字,用来识别不同的cache,必须惟一。

maxElementsInMemory:内存管理的缓存元素数量最大限值。

maxElementsOnDisk:硬盘管理的缓存元素数量最大限值。默认值为0,就是没有限制。

eternal:设定元素是否持久话。若设为true,则缓存元素不会过期。

overflowToDisk:设定是否在内存填满的时候把数据转到磁盘上。

2.下面是一些可选属性:

timeToIdleSeconds:设定元素在过期前空闲状态的时间,只对非持久性缓存对象有效。默认值为0,值为0意味着元素可以闲置至无限长时间。

timeToLiveSeconds:设定元素从创建到过期的时间。其他与timeToIdleSeconds类似。

diskPersistent:设定在虚拟机重启时是否进行磁盘存储,默认为false.(我的直觉,对于安全小型应用,宜设为true)。

diskExpiryThreadIntervalSeconds:访问磁盘线程活动时间。

diskSpoolBufferSizeMB:存入磁盘时的缓冲区大小,默认30MB,每个缓存都有自己的缓冲区。

memoryStoreEvictionPolicy:元素逐出缓存规则。共有三种,RecentlyUsed(LRU)最近最少使用,为默认。

FirstInFirstOut(FIFO),先进先出。LessFrequentlyUsed(specifiedasLFU)最少使用

-->

<defaultCachemaxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

maxElementsOnDisk="10000000"

diskPersistent="false"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU"/>

<!--Usercache-->

<cachename="userCache"

maxElementsInMemory="10000"

maxElementsOnDisk="1000"

eternal="false"

overflowToDisk="true"

diskSpoolBufferSizeMB="20"

timeToIdleSeconds="300"

timeToLiveSeconds="600"

memoryStoreEvictionPolicy="LFU"/>

</ehcache>

复制代码

2.4)在src目录下建立数据库连接属性配置文件jdbc.properties,内容如下:

复制代码

#mysql数据库用

jdbc.driverClassName=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/spring_springmvc_jpa?useUnicode=true&amp;characterEncoding=UTF-8

jdbc.username=root

jdbc.password=root

##===============BoneCP配置==============##

#检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0#

BoneCP.idleConnectionTestPeriod=60

#连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0#

BoneCP.idleMaxAge=60

#每个分区最大的连接数#

BoneCP.maxConnectionsPerPartition=5

#每个分区最小的连接数#

BoneCP.minConnectionsPerPartition=1

#分区数,默认值2,最小1,推荐3-4,视应用而定#

BoneCP.partitionCount=3

#每次去拿数据库连接的时候一次性要拿几个,默认值:2#

BoneCP.acquireIncrement=2

#缓存preparedstatements的大小,默认值:0#

BoneCP.statementsCacheSize=0

#每个分区释放链接助理进程的数量,默认值:3,除非你的一个数据库连接的时间内做了很多工作,不然过多的助理进程会影响你的性能#

BoneCP.releaseHelperThreads=3

复制代码

2.5)在WEB-INF目录下建立Spring的配置文件applicationContext.xml,内容如下:<?xmlversion="1.0"encoding="UTF-8"?>

复制代码

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:cache="http://www.springframework.org/schema/cache"

xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.1.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.1.xsd

http://www.springframework.org/schema/cache

http://www.springframework.org/schema/cache/spring-cache-3.1.xsd

    http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring

    http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">

<!--注解支持-->

<context:annotation-config/>

<!--启动组件扫描,排除@Controller组件,该组件由SpringMVC配置文件扫描-->

<context:component-scanbase-package="cn.luxh.app">

<context:exclude-filtertype="annotation"expression="org.springframework.stereotype.Controller"/>

</context:component-scan>

<!--属性文件位置-->

<context:property-placeholderlocation="classpath:jdbc.properties"/>

<!--数据源-->

<beanid="dataSource"class="com.jolbox.bonecp.BoneCPDataSource"destroy-method="close">

<!--数据库驱动-->

<propertyname="driverClass"value="${jdbc.driverClassName}"/>

<!--相应驱动的jdbcUrl-->

<propertyname="jdbcUrl"value="${jdbc.url}"/>

<!--数据库的用户名-->

<propertyname="username"value="${jdbc.username}"/>

<!--数据库的密码-->

<propertyname="password"value="${jdbc.password}"/>

<!--检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0-->

<propertyname="idleConnectionTestPeriod"value="${BoneCP.idleConnectionTestPeriod}"/>

<!--连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0-->

<propertyname="idleMaxAge"value="${BoneCP.idleMaxAge}"/>

<!--每个分区最大的连接数-->

<propertyname="maxConnectionsPerPartition"value="${BoneCP.maxConnectionsPerPartition}"/>

<!--每个分区最小的连接数-->

<propertyname="minConnectionsPerPartition"value="${BoneCP.minConnectionsPerPartition}"/>

<!--分区数,默认值2,最小1,推荐3-4,视应用而定-->

<propertyname="partitionCount"value="${BoneCP.partitionCount}"/>

<!--每次去拿数据库连接的时候一次性要拿几个,默认值:2-->

<propertyname="acquireIncrement"value="${BoneCP.acquireIncrement}"/>

<!--缓存preparedstatements的大小,默认值:0-->

<propertyname="statementsCacheSize"value="${BoneCP.statementsCacheSize}"/>

<!--每个分区释放链接助理进程的数量,默认值:3,除非你的一个数据库连接的时间内做了很多工作,不然过多的助理进程会影响你的性能-->

<propertyname="releaseHelperThreads"value="${BoneCP.releaseHelperThreads}"/>

</bean>

<!--JPA实体管理器工厂-->

<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<propertyname="dataSource"ref="dataSource"/>

<propertyname="persistenceProvider"ref="persistenceProvider"/>

<propertyname="jpaVendorAdapter"ref="jpaVendorAdapter"/>

<propertyname="jpaDialect"ref="jpaDialect"/>

<propertyname="packagesToScan"value="cn.luxh.app.entity"/>

<propertyname="jpaProperties">

<props>

<propkey="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>

<propkey="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>

<propkey="hibernate.max_fetch_depth">3</prop>

<propkey="hibernate.jdbc.fetch_size">18</prop>

<propkey="hibernate.jdbc.batch_size">10</prop>

<propkey="hibernate.hbm2ddl.auto">update</prop>

<propkey="hibernate.show_sql">true</prop>

<propkey="hibernate.format_sql">true</prop>

<propkey="javax.persistence.validation.mode">none</prop>

</props>

</property>

</bean>

<!--用于指定持久化实现厂商类-->

<beanid="persistenceProvider"class="org.hibernate.ejb.HibernatePersistence"/>

<!--用于设置JPA实现厂商的特定属性-->

<beanid="jpaVendorAdapter"class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

<propertyname="database"value="MYSQL"/>

</bean>

<!--用于指定一些高级特性-->

<beanid="jpaDialect"class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

<!--事务管理器-->

<beanid="txManager"class="org.springframework.orm.jpa.JpaTransactionManager">

<propertyname="entityManagerFactory"ref="entityManagerFactory"/>

</bean>

<!--注解式事务-->

<tx:annotation-driventransaction-manager="txManager"/>

<!--启用缓存注解功能-->

<ehcache:annotation-drivencache-manager="ehCacheManager"/>

<!--cacheManager工厂类,指定ehcache.xml的位置-->

<beanid="ehCacheManager"class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"

p:configLocation="classpath:/ehcache.xml"/>

</beans>

复制代码

2.6)在WEB-INF目录下建立SpringMVC的配置文件dispatcher-servlet.xml,内容如下:

复制代码

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:mvc="http://www.springframework.org/schema/mvc"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.1.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

<mvc:annotation-driven/>

<context:component-scanbase-package="cn.luxh.app.controller"/>

<beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver">

<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>

<propertyname="prefix"value="/WEB-INF/jsp/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

</beans>

复制代码

2、编写代码

1)在WEB-INF目录下建立名叫jsp的文件夹,用于放置jsp页面,和SpringMVC配置文件中的<propertyname="prefix"value="/WEB-INF/jsp/"/>相对应。

2)创建一个实体。  

复制代码

packagecn.luxh.app.entity.privilege;

importjava.io.Serializable;

importjavax.persistence.Column;

importjavax.persistence.Entity;

importjavax.persistence.GeneratedValue;

importjavax.persistence.Id;

importjavax.persistence.Table;

/**

*用户信息

*@authorLuxh

*/

@Entity

@Table(name="t_user_info")

publicclassUserInfoimplementsSerializable{

privatestaticfinallongserialVersionUID=-3838732995856086555L;

@Id

@GeneratedValue

privateLongid;

//账号

@Column(length=20,nullable=false)

privateStringaccount;

//密码

@Column(length=20,nullable=false)

privateStringpassword;

//姓名

@Column(length=32,nullable=false)

privateStringname;

//getter、setter

//......

}

复制代码

3)通用DAO,用于其他DAO继承,

3.1)接口

复制代码

packagecn.luxh.app.dao.base;

/**

*通用的DAO

*@authorLuxh

*/

publicinterfaceBaseDao{

/**

*持久化实体

*@paramentity

*/

voidsave(Objectentity);

/**

*根据主键查询实体

*@param<T>

*@paramclazz实体类

*@paramid主键

*@return

*/

<T>TgetById(Class<T>clazz,Objectid);

}

复制代码

3.2)实现

复制代码

packagecn.luxh.app.dao.base;

importjavax.persistence.EntityManager;

importjavax.persistence.PersistenceContext;

importorg.springframework.stereotype.Repository;

/**

*通用DAO实现

*@authorLuxh

*/

@Repository

publicclassBaseDaoImplimplementsBaseDao{

//注入实体管理器

@PersistenceContext

protectedEntityManagerem;

public<T>TgetById(Class<T>clazz,Objectid){

returnem.find(clazz,id);

}

publicvoidsave(Objectentity){

em.persist(entity);

}

}

复制代码

4)UserDao,继承于通用DAO

4.1)接口  

复制代码

packagecn.luxh.app.dao.privilege;

importcn.luxh.app.dao.base.BaseDao;

/**

*UserDaoInterface

*@authorLuxh

*/

publicinterfaceUserDaoextendsBaseDao{

}

复制代码

4.2)实现

复制代码

packagecn.luxh.app.dao.privilege;

importorg.springframework.stereotype.Repository;

importcn.luxh.app.dao.base.BaseDaoImpl;

/**

*UserDAOImplement

*@authorLuxh

*/

@Repository

publicclassUserDaoImplextendsBaseDaoImplimplementsUserDao{

}

复制代码

5)通用的业务接口

这里只写一个接口,留给其他Service实现。

复制代码

packagecn.luxh.app.service.base;

/**

*通用业务接口

*@authorLuxh

*/

publicinterfaceBaseService{

/**

*保存实体

*@paramentity

*/

voidsave(Objectentity);

/**

*根据主键获取对象

*@param<T>

*@paramclazz实体类

*@paramid主键

*@return

*/

<T>TgetById(Class<T>clazz,Objectid);

}

复制代码

6)用户业务接口UserService,实现通用业务接口的方法,并加上缓存

6.1)接口

复制代码

packagecn.luxh.app.service.privilege;

importcn.luxh.app.service.base.BaseService;

/**

*UserService

*@authorLuxh

*/

publicinterfaceUserServiceextendsBaseService{

}

复制代码

6.2)实现

复制代码

packagecn.luxh.app.service.privilege;

importorg.springframework.beans.factory.annotation.Autowired;

importcom.googlecode.ehcache.annotations.TriggersRemove;

importcom.googlecode.ehcache.annotations.Cacheable;

importorg.springframework.stereotype.Service;

importorg.springframework.transaction.annotation.Propagation;

importorg.springframework.transaction.annotation.Transactional;

importcn.luxh.app.dao.privilege.UserDao;

/**

*UserServiceImplement

*@authorLuxh

*/

@Service

publicclassUserServiceImplimplementsUserService{

@Autowired

privateUserDaouserDao;

@Cacheable(cachename="userCache")//缓存数据

public<T>TgetById(Class<T>clazz,Objectid){

returnuserDao.getById(clazz,id);

}

@Transactional(propagation=Propagation.REQUIRED)

@TriggersRemove(cachename="userCache",removeAll=true)//清除缓存

publicvoidsave(Objectentity){

userDao.save(entity);

}

}

复制代码

7)控制层,暂时还没有写一个公共的Controller用于被继承,就直接写UserController吧

复制代码

packagecn.luxh.app.controller.privilege;

importorg.apache.commons.logging.Log;

importorg.apache.commons.logging.LogFactory;

importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.stereotype.Controller;

importorg.springframework.ui.ModelMap;

importorg.springframework.web.bind.annotation.RequestMapping;

importorg.springframework.web.bind.annotation.RequestParam;

importorg.springframework.web.servlet.mvc.support.RedirectAttributes;

importcn.luxh.app.entity.privilege.UserInfo;

importcn.luxh.app.service.privilege.UserService;

/**

*UserController

*@authorLuxh

*/

@Controller

@RequestMapping(value="/user")

publicclassUserController{

privatestaticfinalLogLOG=LogFactory.getLog(UserController.class);

@Autowired

privateUserServiceuserService;//注入业务接口

/**

*用户列表

*/

@RequestMapping(value="/userList.do")

publicStringuserList(ModelMapmodelMap){

LOG.info("访问用户列表");

//打印一句话测试,不查数据库了

return"user/userList";//根据SpringMVC配置文件配好的前缀和后缀,自动转为:/WEB-INF/jsp/user/userList.jsp

}

/**

*根据主键查找用户

*/

@RequestMapping(value="/getUserById.do")

publicStringgetUserById(@RequestParamlongid){

LOG.info("idis:"+id);

UserInfouserInfo=userService.getById(UserInfo.class,id);

LOG.info("user'snameis:"+userInfo.getName());

return"user/userList";

}

/**

*保存用户

*/

@RequestMapping(value="/saveUser.do")

publicStringsaveUser(UserInfouserInfo,RedirectAttributesredirectAttributes){

LOG.info("保存用户");

userService.save(userInfo);

//重定向后的提示信息,使用RedirectAttributes传递,在JSP页面可以用${message}获取

//提示信息只出现一次,刷新也不会重复提示,

redirectAttributes.addFlashAttribute("message","操作成功");

//重定向,防止表单重复提交

return"redirect:userList.do";//相对于当前路径

//return"redirect:/user/userList.do";//相对于当前项目根路径

}

}

复制代码

相关推荐