Springmvc+Hibernate+JPA Maven环境搭
2015-07-11 14:50
579 查看
所需要依赖包如下:
spring-beans-4.1.2.RELEASE.jarspring-context-4.1.2.RELEASE.jar
spring-core-4.1.2.RELEASE.jar
spring-jdbc-4.1.2.RELEASE.jar
spring-orm-4.1.2.RELEASE.jar
spring-web-4.1.2.RELEASE.jar
spring-webmvc-4.1.2.RELEASE.jar
spring-tx-4.1.2.RELEASE.jar
spring-expression-4.1.2.RELEASE.jar
spring-aop-4.1.2.RELEASE.jar
jboss-logging-3.1.3.GA.jar
jboss-transaction-api_1.2_spec-1.0.0.Final.jar
hibernate-commons-annotations-4.0.5.Final.jar
hibernate-entitymanager-4.3.6.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final
hibernate-core-4.3.6.Final.jar
jackson-annotations-2.2.3
jackson-core-2.2.3.jar
jackson-databind-2.2.3.jar
jandex-1.1.0.Final.jar
javassist-3.18.1-GA.jar
aopalliance-1.0.jar
aspectjrt-1.8.4.jar
aspectjweaver-1.8.4.jar
commons-logging-1.1.3.jar
ezmorph-1.0.6.jar
c3p0-0.9.1.2.jar
dom4j-1.6.1.jar
mysql-connector-java-5.1.33
本项目是采用Springmvc搭建业务逻辑框架,使用JPA进行数据库实体映射,使用Hibernate进行数据操作,数据库使用的是Mysql。以上共计29个jar,应该是最精简的依赖包组合了。基本上涵盖了Springmvc所有常用模块所需要的依赖包。好,装备已齐全,下面开始搭建框架。
首先创建一个Maven项目,没听说过Maven的童鞋,请自行百度。本项目结构图如下:
然后,在项目的WEB-INF下创建applicationContext.xml,springWebmvc.xml。为显得有条理,在WEB-INF创建文件夹config/spring ,将这两个文件移动到spring中。然后,就可以配置了。总共需要配置3个文件,web.xml 、applicationContext.xml、springWebmvc.xml 文件。下面从web.xml文件开始,一 一介绍。
配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" 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_3_0.xsd"> <!--************* spring start************ --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/config/spring/applicationContext.xml, </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- *********************** 字符过滤开始 *********************** --> <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> <!-- *********************** 字符过滤结束 *********************** --> <!-- OpenEntityManagerInViewFilter 有点类似于SSH框架中的OpenSessionInViewFilter 由于Hibernate引入了Lazy Load特性,使得脱离Hibernate的Session周期的对象,如果再想通过getter方法取到其关联对象的值,Hibernate会抛出一个LazyLoad的Exception。所以为了解决这个问题,Spring引入了这个Filter,使得Hibernate的Session的生命周期变长 --> <filter> <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>Spring OpenEntityManagerInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- ******** springmvc start ******* --> <!-- 本项目的DispatcherServlet,为了实现REST风格,拦截了所有请求,这样的话*.js,*.css等静态文件都会被拦截,而这些静态文件,并不像ctroller,在Springmvc中有映射,所以,访问会报404找不到。故需要激活Tomcat的defaultServlet,在请求还没进入DispatcherServlet时提前处理这些静态文件。 --> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.bmp</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.gif</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.png</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet> <servlet-name>springWebmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/spring/springWebmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springWebmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- ******** springmvc end ******* --> <!-- ************* spring end *************** --> <session-config> <session-timeout>60</session-timeout> </session-config> </web-app>
web.xml配置,总体来说分两步。一加载spring的配置文件,二加载springmvc的配置文件。springmvc其实也是基于spring的。注释已经非常详细了,不再赘述。下面着重介绍下Springmvc配置文件重命名的问题。默认的命名规则是[servletName-名称]-servlet.xml servletName为DispatcherServlet 的映射名称,生成路径为WEB-INF下,也就是说,程序默认会去加载WEB-INF/[servletName-名称]-servlet.xml,但是如果你改变了该配置文件的名称和生成路径,一定要用用init-param重新申明,告知程序该文件的加载路径。比如本案例,告知程序去/WEB-INF/config/spring/springWebmvc.xml寻找配置文件。
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:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd "> <!-- ******** 自动扫描注解 ******** --> <context:component-scan base-package="com.test.service,com.test.dao" > <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- ******* 导入外部数据库的properties文件 *****--> <context:property-placeholder location="classpath:db.properties"/> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!-- ******* 数据库配置信息 ****** --> <property name="jdbcUrl" value="${jdbcUrl}"></property> <property name="driverClass" value="${driverClass}"></property> <property name="user" value="${user}"></property> <property name="password" value="${password}"></property> <!-- 其他配置 --> <!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> <property name="initialPoolSize" value="3"></prope 12478 rty> <!--连接池中保留的最小连接数。Default: 3 --> <property name="minPoolSize" value="5"></property> <!--连接池中保留的最大连接数。Default: 15 --> <property name="maxPoolSize" value="20"></property> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> <property name="acquireIncrement" value="2"></property> <!-- 控制数据源内加载的PreparedStatements数量。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 --> <property name="maxStatements" value="8"></property> <!--maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 --> <property name="maxStatementsPerConnection" value="5"></property> <!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> <property name="maxIdleTime" value="1800"></property> </bean> <!--配置实体管理对象 --> <bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" /> <!-- 定义entity实体扫描路径 --> <property name="packagesToScan" value="com.test.model" /> <!-- jpaVendorAdapter 用于设置实现厂商JPA实现的特定属性,如设置Hibernate的是否自动生成DDL的属性generateDdl;这些属性是厂商特定的,因此最好在这里设置 --> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="generateDdl" value="true"></property> <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"></property> </bean> </property> <!--指定JPA属性 如: Hibernate中指定是否显示SQL的--> <property name="jpaProperties"> <props> <prop key="hibernate.show_sql">true</prop> <!-- 设置控制台是否显示sql true 显示 false 不显示 --> </props> </property> </bean> <!--添加JPA事务管理器--> <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="dataSource" ref="dataSource"/> <property name="entityManagerFactory" ref="entityManager" /> <property name="jpaDialect"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> </property> </bean> <!-- 开启事务注解支持,这样子,在类中添加@Transactional 才会起做作用 --> <tx:annotation-driven transaction-manager="txManager" /> <!-- 测试所用Dao --> <bean id="simpleJpaDao" class="com.test.base.dao.impl.SimpleJpaDaoImpl"/> </beans>
applicationContext.xml 配置总的来说,也是两步。一 扫描包 二配置数据库。
springmvc优势就是基于注解的,该框架下的实体映射,service层,dao层几乎都是基于注解的。 applicationContext.xml 就是自动扫描注解,装配需要的bean。需要强调的是,
<context:component-scan>标签在扫描时,用
<context:exclude-filter>排除了对controller的扫描,因为这个是留给SpringWebmvc.xml 做的。
接下来就是配置数据源和整合JPA了。数据源配置大家应该都比较了解,就不多说了。下面着重介绍下JPA的整合.
在整合JPA时,需要在项目编译路径下,新建一个persistence.xml,路径结构为:classpath:META-INF/persistence.xml.因为我是Maven项目,所以,放到了resources资源文件夹下。详情见项目结构图。persistence.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <!-- name 持久化单元命名 RESOURCE_LOCAL 使用JDBC驱动管理的本地事务 --> <persistence-unit name="springjpa" transaction-type="RESOURCE_LOCAL"> </persistence-unit> </persistence>
配置完成后,将persistence.xml配置到LocalContainerEntityManagerFactoryBean的persistenceXmlLocation属性中,如上所示。其他JPA配置,注解已经标注的非常清楚,这里不再多说。
springWebmvc.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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- ***注解驱动**** --> <context:component-scan base-package="com.test.controller"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <!--context:exclude-filter 把 Service注解给去掉 因为spring的context是父子容器(applicationContext.xml 父容器,SpringWebmvc.xml是子容器),所以,会产生冲突。 由ContextLoaderListener产生的是父容器,由springmvc产生的是子容器,子容器扫描controller时,controller中装配了 @Service注解实例,而该实例是由父容器进行初始化的以保证事务的增强处理,所以,此时如果直接加载的话,得到的是原样的 Service,它没有经过事务加强处理,故而没有事务能力。 --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan> <mvc:annotation-driven> <mvc:message-converters> <!-- HTTP 请求和响应是基于文本的,意味着浏览器和服务器通过交换原始文本进行通信。Spring controller类中的方法返回纯String类型或者 域模型(其他java内建模型对象),需要StringHttpMessageConverter将对象序列化或反序列化成原始文本。 --> <!-- 以下两个converter不能颠倒,否则如果返回String的话会加引号 --> <bean class="org.springframework.http.converter.StringHttpMessageConverter" /> <!-- 使用 Jackson 的 ObjectMapper 读取/编写 JSON 数据。它转换媒体类型为 application/json 的数据 --> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> </mvc:message-converters> </mvc:annotation-driven> <!-- **** 前缀+ viewName +后缀 *** --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- webroot到某一指定的文件夹的路径 --> <property name="prefix" value="/WEB-INF/views/"></property> <!-- 视图名称的后缀 --> <property name="suffix" value=".jsp"></property> </bean> </beans>
注解包扫描时,排除了对service层的扫描,原因见注释。
<mvc:message-converters>主要是用来配置对ajax返回结果的支持,详情见注释。
以上便完成了三大配置文件的相关配置,下面从MVC三层结构介绍下,从model→dao→service→Controller的相关配置,还是以贴代码为主。
Model → JPA 实体映射
package com.test.model; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; //采用hibernate-jpa 进行关系映射 @Entity @Table(name="test_user") public class User { private String id; private String userName; private String password; private List<LoginHistory> loginHistories; /*ID生成规则为uuid *如果ID为数字类型可采用如下配置 @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name ="id") */ @Id @GeneratedValue(generator = "uuid-gen") @GenericGenerator(name = "uuid-gen", strategy = "uuid") @Column(name ="id",length=32) public String getId() { return id; } public void setId(String id) { this.id = id; } @Column(name="user_name",length=20) public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } @Column(name="password",length=20) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user") public List<LoginHistory> getLoginHistories() { return loginHistories; } public void setLoginHistories(List<LoginHistory> loginHistories) { this.loginHistories = loginHistories; } }
简单来说,就是在类头部用@Entity标注为实体,@Table配置实体和表的映射,然后,在所有的getter方法上配置属性和字段的映射。本例子,先做简单介绍,后期,会对映射关系一对多,多对多,多对一配置进行详解。
Dao层配置
package com.test.dao.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.test.base.dao.impl.SimpleJpaDaoImpl; import com.test.model.LoginHistory; import com.test.model.User; @Repository public class UserDaoImpl implements com.test.dao.UserDao { @Autowired private SimpleJpaDaoImpl simpleJpaDao; @Override public List<LoginHistory> getLoginHistoryList(String userName) { String sql="select tlh.* from test_login_history tlh ,test_user tu where tu.id=tlh.user_id and tu.user_name=?1"; return (List<LoginHistory>)simpleJpaDao.queryBySQL(sql, userName); } @Override public void addUser(User user) { simpleJpaDao.add(user); } @Override public void addLoginHistory(LoginHistory loginHistory) { simpleJpaDao.add(loginHistory); } @Override public List<Object[]> getUserByUserName(String userName) { String sql="select * from test_user where user_name=?1"; Object[] paramlist=new Object[2]; paramlist[0]=userName; return simpleJpaDao.queryBySQL(sql,userName ); } }
Dao层,只需要对impl即实现层,做相关的配置即可。如上,对UserDaoImpl 加注解@Repository,将该类识别为Bean,同时将该类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。 Spring本身提供了一个丰富的并且是与具体的数据访问技术无关的数据访问异常结构,用于封装不同的持久层框架抛出的异常,使得异常独立于底层的框架。@Autowired 动态注入bean,类似于SSH框架的setter/getter 方法。
Service 配置
package com.test.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.test.dao.UserDao; import com.test.model.LoginHistory; import com.test.model.User; import com.test.service.UserService; @Service @Transactional public class UserServiceImpl implements UserService { @Autowired UserDao userDao; @Override public List<LoginHistory> getLoginHistoryList(String userName) { return userDao.getLoginHistoryList(userName); } @Override public void addUser(User user) { userDao.addUser(user); } @Override public void addLoginHistory(LoginHistory loginHistory) { userDao.addLoginHistory(loginHistory); } @Override public List<Object[]> getUserByUserName(String userName) { return userDao.getUserByUserName(userName); } }
Service层同Dao相似,也是只需要在实现层加注解。如上在Service实现层加@Service,标注该类为业务层组件,并添加事务管理@Transactional。
注意,必须在applicationContext.xml中配置对事务注解的支持,此处配置的@Transactional才会起作用。具体配置前面已经讲过。
Controller 配置
package com.test.controller; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; 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.ResponseBody; import com.test.model.LoginHistory; import com.test.model.User; import com.test.service.UserService; @Controller public class LoginController { @Autowired UserService userService; @RequestMapping("login") public String login(User user,ModelMap map){ LoginHistory loginHistory=new LoginHistory(); Date d=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String datestr=sdf.format(d); loginHistory.setUser(user); loginHistory.setLoginDate(datestr); loginHistory.setLoginIP("127.0.0.1"); List<LoginHistory> lhlist=new ArrayList<LoginHistory>(); lhlist.add(loginHistory); user.setLoginHistories(lhlist); userService.addUser(user); map.put("status", "success"); return "welcome"; } //Ajax 请求使用@ResponseBody @RequestMapping("loginHistory-get") @ResponseBody public Map getLoginHistory(String userName){ Map map =new HashMap(); List<LoginHistory> hlist=userService.getLoginHistoryList(userName); map.put("hlist", hlist); return map; } }
@controller 标示该类为控制层,@Autowired注入相关Service开始实现业务逻辑。在方法前面添加@RequestMapping(“”)实现相关的调用映射。注意,Ajax调用要另外再添加一个@ResponseBody标示该方法为Ajax调用。Ajax方法,可以直接返回任何类型,不一定非要是JSON格式的数据。Springmvc会自动将其转化为json格式的数据。这就要归功于我们前面在SpringWebmvc.xml中的
<mvc:message-converters>配置的内容。
好了,以上已经完成了对Springmvc+Hibernate+JPA的框架搭建了,是不是觉得很简单呢。欢迎大家吐槽!
demo下载地址:http://download.csdn.net/detail/chrisjingu/9713537
相关文章推荐
- java 正则表达式String.replaceAll( "\\s+ ", "| ")
- Java基础 Day14 泛型
- 如何利用 JConsole观察分析Java程序的运行,进行排错调优
- java中final关键字
- Java多线程当中的violate
- 在Eclipse中新建Maven项目
- SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现
- java中static关键字
- java中的集合与队列
- SpringMVC源码剖析(三)- DispatcherServlet的初始化流程
- SpringMVC源码剖析(二)- DispatcherServlet的前世今生
- SpringMVC源码剖析(一)- 从抽象和接口说起
- 分享非常有用的Java程序(关键代码)(七)---抓屏程序
- Day15 Java基础 IO流
- 分享非常有用的Java程序 (关键代码)(六)---解析/读取XML 文件(重要)
- JDK设置环境变量(classpath)时:dt.jar ,tool.jar,rt.jar的作用
- 深入理解JDK、JRE(两套)、JVM、以及不同目录下的java.exe
- 分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map
- 分享非常有用的Java程序 (关键代码)(四)---动态改变数组的大小
- 分享非常有用的Java程序 (关键代码) (三)---创建ZIP和JAR文件