Spring+SpringMVC+JPA

本文详细介绍如何搭建Spring+SpringMVC+JPA的开发框架,包括环境配置、代码编写等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring+SpringMVC+JPA
http://endual.iteye.com/blog/1928295
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)建立一个Web Project,引入上述jar包

    2.1)web.xml配置如下:

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="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-dd HH\: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-dd HH:mm:ss,SSS} [%t] [%c] [%p] - %m%n


log4j.logger.org.hibernate.tool.hbm2ddl=debug
复制代码
    2.3)在src目录下建立缓存的配置文件ehcache.xml,内容如下:

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="true" monitoring="autodetect"
dynamicConfig="true">

<!-- <diskStore path="java.io.tmpdir"/> -->

<!-- 配置缓存文件存放路径 -->
<diskStore path="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: 元素逐出缓存规则。共有三种,Recently Used (LRU)最近最少使用,为默认。
First In First Out (FIFO),先进先出。Less Frequently Used(specified as LFU)最少使用

-->

<defaultCache maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU" />

<!-- User cache -->
<cache name="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&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

#缓存prepared statements的大小,默认值:0#
BoneCP.statementsCacheSize=0

#每个分区释放链接助理进程的数量,默认值:3,除非你的一个数据库连接的时间内做了很多工作,不然过多的助理进程会影响你的性能#
BoneCP.releaseHelperThreads=3
复制代码
    2.5)在WEB-INF目录下建立Spring的配置文件applicationContext.xml,内容如下:<?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: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-scan base-package="cn.luxh.app">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<!-- 属性文件位置 -->
<context:property-placeholder location="classpath:jdbc.properties" />

<!-- 数据源 -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClass" value="${jdbc.driverClassName}" />
<!-- 相应驱动的jdbcUrl-->
<property name="jdbcUrl" value="${jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${jdbc.password}" />
<!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 -->
<property name="idleConnectionTestPeriod" value="${BoneCP.idleConnectionTestPeriod}" />
<!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 -->
<property name="idleMaxAge" value="${BoneCP.idleMaxAge}" />
<!-- 每个分区最大的连接数 -->
<property name="maxConnectionsPerPartition" value="${BoneCP.maxConnectionsPerPartition}" />
<!-- 每个分区最小的连接数 -->
<property name="minConnectionsPerPartition" value="${BoneCP.minConnectionsPerPartition}" />
<!-- 分区数 ,默认值2,最小1,推荐3-4,视应用而定 -->
<property name="partitionCount" value="${BoneCP.partitionCount}" />
<!-- 每次去拿数据库连接的时候一次性要拿几个,默认值:2 -->
<property name="acquireIncrement" value="${BoneCP.acquireIncrement}" />
<!-- 缓存prepared statements的大小,默认值:0 -->
<property name="statementsCacheSize" value="${BoneCP.statementsCacheSize}" />
<!-- 每个分区释放链接助理进程的数量,默认值:3,除非你的一个数据库连接的时间内做了很多工作,不然过多的助理进程会影响你的性能 -->
<property name="releaseHelperThreads" value="${BoneCP.releaseHelperThreads}" />
</bean>

<!-- JPA实体管理器工厂 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceProvider" ref="persistenceProvider"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaDialect" ref="jpaDialect"/>

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

<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">18</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
</bean>
<!-- 用于指定持久化实现厂商类 -->
<bean id="persistenceProvider" class="org.hibernate.ejb.HibernatePersistence"/>
<!-- 用于设置JPA实现厂商的特定属性 -->
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
</bean>
<!-- 用于指定一些高级特性 -->
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<!-- 注解式事务 -->
<tx:annotation-driven transaction-manager="txManager"/>

<!-- 启用缓存注解功能 -->
<ehcache:annotation-driven cache-manager="ehCacheManager" />


<!-- cacheManager工厂类,指定ehcache.xml的位置 -->
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:/ehcache.xml"/>

</beans>
复制代码


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

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-scan base-package="cn.luxh.app.controller"/>


<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

</beans>
复制代码
  2、编写代码

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

    2)创建一个实体。  

复制代码
package cn.luxh.app.entity.privilege;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;


/**
* 用户信息
* @author Luxh
*/

@Entity
@Table(name="t_user_info")
public class UserInfo implements Serializable{

private static final long serialVersionUID = -3838732995856086555L;

@Id
@GeneratedValue
private Long id;

//账号
@Column(length=20,nullable=false)
private String account;
//密码
@Column(length=20,nullable=false)
private String password;
//姓名
@Column(length=32,nullable=false)
private String name;

//getter、setter
//......


}
复制代码
    3)通用DAO,用于其他DAO继承,

      3.1)接口

复制代码
package cn.luxh.app.dao.base;

/**
* 通用的DAO
* @author Luxh
*/
public interface BaseDao {

/**
* 持久化实体
* @param entity
*/
void save(Object entity);

/**
* 根据主键查询实体
* @param <T>
* @param clazz 实体类
* @param id 主键
* @return
*/
<T> T getById(Class<T> clazz,Object id);
}
复制代码
      3.2)实现

复制代码
package cn.luxh.app.dao.base;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

/**
* 通用DAO实现
* @author Luxh
*/

@Repository
public class BaseDaoImpl implements BaseDao{

//注入实体管理器
@PersistenceContext
protected EntityManager em;

public <T> T getById(Class<T> clazz, Object id) {
return em.find(clazz, id);
}

public void save(Object entity) {
em.persist(entity);
}

}
复制代码
    4)UserDao,继承于通用DAO

      4.1)接口  

复制代码
package cn.luxh.app.dao.privilege;

import cn.luxh.app.dao.base.BaseDao;

/**
* User Dao Interface
* @author Luxh
*/
public interface UserDao extends BaseDao{

}
复制代码
      4.2)实现

复制代码
package cn.luxh.app.dao.privilege;

import org.springframework.stereotype.Repository;

import cn.luxh.app.dao.base.BaseDaoImpl;

/**
* User DAO Implement
* @author Luxh
*/

@Repository
public class UserDaoImpl extends BaseDaoImpl implements UserDao{

}
复制代码
  5)通用的业务接口

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

复制代码
package cn.luxh.app.service.base;

/**
* 通用业务接口
* @author Luxh
*/
public interface BaseService {

/**
* 保存实体
* @param entity
*/
void save(Object entity);

/**
* 根据主键获取对象
* @param <T>
* @param clazz 实体类
* @param id 主键
* @return
*/
<T> T getById(Class<T> clazz,Object id);
}
复制代码
    6)用户业务接口UserService,实现通用业务接口的方法,并加上缓存

      6.1)接口

复制代码
package cn.luxh.app.service.privilege;

import cn.luxh.app.service.base.BaseService;

/**
* User Service
* @author Luxh
*/
public interface UserService extends BaseService {

}
复制代码
      6.2)实现

复制代码
package cn.luxh.app.service.privilege;

import org.springframework.beans.factory.annotation.Autowired;
import com.googlecode.ehcache.annotations.TriggersRemove;
import com.googlecode.ehcache.annotations.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.luxh.app.dao.privilege.UserDao;

/**
* User Service Implement
* @author Luxh
*/

@Service
public class UserServiceImpl implements UserService{

@Autowired
private UserDao userDao;

@Cacheable(cacheName="userCache")//缓存数据
public <T> T getById(Class<T> clazz, Object id) {
return userDao.getById(clazz, id);
}

@Transactional(propagation=Propagation.REQUIRED)
@TriggersRemove(cacheName="userCache",removeAll=true)//清除缓存
public void save(Object entity) {
userDao.save(entity);
}

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

复制代码
package cn.luxh.app.controller.privilege;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.luxh.app.entity.privilege.UserInfo;
import cn.luxh.app.service.privilege.UserService;


/**
* User Controller
* @author Luxh
*/

@Controller
@RequestMapping(value="/user")
public class UserController {

private static final Log LOG = LogFactory.getLog(UserController.class);


@Autowired
private UserService userService;//注入业务接口

/**
* 用户列表
*/
@RequestMapping(value="/userList.do")
public String userList(ModelMap modelMap) {
LOG.info("访问用户列表");
//打印一句话测试,不查数据库了
return "user/userList"; //根据SpringMVC配置文件配好的前缀和后缀,自动转为:/WEB-INF/jsp/user/userList.jsp
}

/**
* 根据主键查找用户
*/
@RequestMapping(value="/getUserById.do")
public String getUserById(@RequestParam long id) {
LOG.info("id is :"+id);
UserInfo userInfo = userService.getById(UserInfo.class,id);
LOG.info("user's name is :"+userInfo.getName());
return "user/userList";
}

/**
* 保存用户
*/
@RequestMapping(value="/saveUser.do")
public String saveUser(UserInfo userInfo,RedirectAttributes redirectAttributes) {
LOG.info("保存用户");
userService.save(userInfo);
//重定向后的提示信息,使用RedirectAttributes传递,在JSP页面可以用${message}获取
//提示信息只出现一次,刷新也不会重复提示,
redirectAttributes.addFlashAttribute("message", "操作成功");

//重定向,防止表单重复提交
return "redirect:userList.do";//相对于当前路径
//return "redirect:/user/userList.do";//相对于当前项目根路径
}


}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值