SpringMVC+Spring3+hibernate4 开发环境搭建以及一个开发实例教程
刚刚接触了SpringMVC这个框架,因此有必要把它拿过来同hibernate、Spring框架进行集成和开发一个实例,在真正企业从头开发的项目中往往一个稳定的开发环境至关重要,开发一个项目选择什么样的搭建平台也需要有经验才可以,并不是说你会搭建一个开发平台然后公司就会用你搭建的开发平台,一个项目或者一个公司看中的也不是你可以搭出框架,而是在这个框架使用过程中出现的各种问题你可以解决掉。
也就是说呢,无论开发什么项目要做到稳定、环境稳定、开发成本稳定、技术稳定、换句话说就是“风险可控”,你不能说一个新的项目前期开发到一半的时候发现这个开发环境不合适或者出现了啥新的问题你还解决不了,这不是很淡腾的事吗?
对我们而言需要不仅仅可以搭建一个平台而且要掌握它,掌握它可以出现的各种问题或bug,如果你没有掌握到这种程度可以出你只是走马观花似得搭建了一个鸡窝,没有什么实用价值的,个人觉得老板或者面试者也是更注重后者,所以呢,这篇博客也是注重说在搭建过程中遇到的各种问题,这也印证了打江山容易但想要坐稳了不易。
本文思路
首先,看一下已经建好的整个项目目录结构,采用了经典三层在Eclipse里面:
结构很清晰采用了springmvc注解扫描包,里面大部分内容都是通过注解实现的可见通过注解来实现某某个功能也是一种趋势呀,注解操作简单、写的少却能实现同样的功能也是由于这个原因受到人们的欢迎。
SpringMVC与Spring集成
它同spring集成要做的事情是把bean交给spring管理,springmvc自己则不再管理bean它通过注解的方式取得spring实例化好的bean类,想让spring管理其bean就需要实例化Spring自己的WebApplicationContext对象,这个对象是上下对象程序运行所有的参数以及设置都可以从这个对象中取得bean也不列外,我们可以在web.xml文件中设置一个监听器在程序启动的时候得到WebApplicationContext对象,这个对象有它自己的属性,属性就是我们bean的配置文件,所以它才能够正确找到bean并将其实例化,我们看一下配置文件,再看一下监听器类的源码就可以知道原理。
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:config/springAnnotation-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>上面配置是web.xml里配置的bean路径参数以及spring的监听器类,再看一看监听器类的源码
package org.springframework.web.context; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class ContextLoaderListener extends ContextLoader implements ServletContextListener { private ContextLoader contextLoader; public ContextLoaderListener() { } public ContextLoaderListener(WebApplicationContext context) { super(context); } } ………………………………………………………………………略…………………………………………………………………………………这个类是监听类的部分代码,可看到它继承了ContextLoader这个类并将这个类作为成员变量传入进来,进去看一下contextloader这个类。
package org.springframework.web.context; ………………………………………………………………………略………………………………………………………………………………… import ………… import org.springframework.util.StringUtils; public class ContextLoader { public static final String CONTEXT_CLASS_PARAM = "contextClass"; public static final String CONTEXT_ID_PARAM = "contextId"; public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses"; public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation"; public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector"; public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey"; private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties"; private static final Properties defaultStrategies; private static final Map<ClassLoader, WebApplicationContext> currentContextPerThread; private static volatile WebApplicationContext currentContext; private WebApplicationContext context; private BeanFactoryReference parentContextRef; public ContextLoader() { } ……………………………………………………略…………………………………………………………可以看到父类中有这个变量
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";正好是我们配置文件中配置的下面的值,把bean的配置文件值通过contextConfiglocation传入了spring监听器,
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:config/springAnnotation-*.xml</param-value> </context-param>
这就是spring与springmvc集成的原理,看了代码相信大家已经很清楚,可以用一句话概括;将bean交给spring管理。
只有懂了原理在出现错误的时候才方便调试,以后再出现监听器错误,例如空指针了、创建失败了,不用想你就知道可能传入的配置文件没有传入你懂了原理之后也可以自己改它的源码,传入更多参数等,其实,无论是spring还是springmvc他们的监听器都是集成context这个父类而来,再往大了想想web层框架大部分都是集成该类,以后你在学习web框架的时候就会觉得非常简单,你找到了他们的共同点一个网的节点你找到了剩下的就是学习他们的不同点了每个框架都有自己的特色,我理解的也不是很全面在你不理解时候多思考(它的设计思路)、多动手(看代码源码)会逐步理解、逐步深入。
Spring与hibernate4集成
发现现在很多公司也在使用ibatis、mabatis等框架,我们就一起对比着说说他们都是怎么集成,其实都是一样的有着异曲同工的感觉思路和实现方式是一样的。
设计思路;
1.配置数据源
2.配置sessionFactory或者sqlMapclient
3.配置Transaction事务
在同数据库底层集成的框架中大部分也都是这三部,不同之处在于实现类不一样、实现的功能一样但对象不一样,举个例子;我们都知道sessionFactory属于一个对象,但在ibatis里面不是这个对象名但有同样的功能叫做;SqlMapClient.
ibatis这个框架是基于配置文件实现sql语句都写在配置文件里面,通过sqlMapclient对象可以拿到配置信息,它有两个重要的属性即数据源和xml配置文件,其他的是一些辅助参数可有可无。
对于事务也仅仅是管理事务的类不同,但机制一样我配置的这种都是通过代理事务类实现,好处就不多说了。
1.先看看hibernate数据源配置如下;
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/springmvc"></property> <property name="username" value="root"></property> <property name="password" value="123456"></property> </bean>我使用的是mysql数据库,也可以改查oracle数据库,dataSource同ibatis很相似属性也一样,需要注意的是在数据源中往往会加入连接池配置,这个也是在这里进行配置。
2.sessionFactory
下面是hibernate、sessionFactory配置
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hbiernate.format._sql">true</prop> </props> </property> <property name="configLocations"> <list> <value>classpath*:com/tgb/web/controller/hibernate/hibernate.cfg.test.xml</value> </list> </property> </bean>对比ibatis 配置
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>classpath:sql-map-config.xml</value> </property> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="lobHandler" ref="lobHandler"/> </bean>
可以发现仅仅是属性值不一样,属性都是一样的说明他们的实现方式都是一样的但实现类不一样,其中有个lobHandler属性是为了处理超大数据设置的属性,比如一个文件1G存储在数据库字段中就需要用到这个配置,进行特殊处理操作。
一个sessionFactory可以对应于多个数据源即可以对用于多个数据库,这里只是配置了一个数据库,多个数据库又会涉及到分布式事务概念又会稍微复杂一点,以后再介绍怎么配置,它管理着数据库中的表结构和各种表实现对表的操作。
3.事务管理
hibernate配置事务
<bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true" > <property name="transactionManager" ref="transactionManager"></property> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED,-Exception</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="insert*">PROPAGATION_REQUIRED</prop> <prop key="get*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>
该事务使用了代理方式。为某个类配置事务时需要集成该事物类,如下
<bean id="userManagerBase" class="com.tgb.web.controller.service.UserManager"> <property name="userDao" ref="userDao"></property> </bean> <bean id="userManager" parent="transactionBase"> <property name="target" ref="userManagerBase"></property> </bean>
用户管理增加用户
UserAction.java 以下为对用的各层类和方法可以实现简单调用,接口里面还可以加入泛型在下篇博客中会设计接口里面怎么使用泛型操作。
@Controller @RequestMapping("/user") public class UserController { @Resource(name="userManager") private IUserManager service; @RequestMapping("/addUser") public void addUser() { User user=new User(); user.setId("1"); user.setAge("2"); user.setUsername("3"); service.addUser(user); } }IUserDao interface
public interface IUserDao { void addUser(User user); }userDaoImpl
private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override public void addUser(User user) { sessionFactory.getCurrentSession().save(user); }IUserManager interface
public interface IUserManager { void addUser(User user); }userDaoImpl
public class UserManager implements IUserManager { private IUserDao userDao; public void setUserDao(IUserDao userDao) { this.userDao = userDao; } @Override public void addUser(User user) { userDao.addUser(user); } }
代码简单相信不用注释也可以看懂,通过看上面的内容你也会搭建这个搭建并实现简单的实例了