一.spring和hibernate进行整合
创建web项目,引入所需要的jar包
创建对应的数据库
创建数据库对应的实体类以及映射文件
Teacher实体类
public class Teacher { private Integer tId; //编号 private Integer tage; //年龄 private String tName;//姓名 private Date tDate; @Override public String toString() { return "Teacher [tId=" + tId + ", tage=" + tage + ", tName=" + tName + ", tDate=" + tDate + "]"; } public Teacher() { super(); } public Teacher(Integer tId, Integer tage, String tName, Date tDate) { super(); this.tId = tId; this.tage = tage; this.tName = tName; this.tDate = tDate; } public Integer gettId() { return tId; } public void settId(Integer tId) { this.tId = tId; } public Integer getTage() { return tage; } public void setTage(Integer tage) { this.tage = tage; } public String gettName() { return tName; } public void settName(String tName) { this.tName = tName; } public Date gettDate() { return tDate; } public void settDate(Date tDate) { this.tDate = tDate; } }
Teacher.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.bdqn.bean"> <class name="Teacher"> <id name="tId"> <generator class="increment"></generator> </id> <property name="tName"/> <property name="tage"/> <property name="tDate"/> </class> </hibernate-mapping>
创建对应的dao层文件
TeacherDao
public interface TeacherDao { //新增 void addTeacher(Teacher teacher); //删除 void deleteTeacher(Teacher teacher); //修改 void updateTeacher(Teacher teacher); //查询 List<Teacher> findTeachers(); }
TeacherDaoImpl
/** * HibernateDaoSupport:是spring为hibernate提供的工具类 * getHibernateTemplate()是获取模版! * 什么时候给它赋值的???? * spring容器 通过setHibernateTemplate! */ public class TeacherDaoImpl extends HibernateDaoSupport implements TeacherDao { // 新增 public void addTeacher(Teacher teacher) { getHibernateTemplate().save(teacher); } // 删除 public void deleteTeacher(Teacher teacher){ getHibernateTemplate().delete(teacher); } // 修改 public void updateTeacher(Teacher teacher){ getHibernateTemplate().update(teacher); } // 查询 public List<Teacher> findTeachers(){ return getHibernateTemplate().find("from Teacher"); } }
创建对应的service层文件
TeacherService
public interface TeacherService { // 新增 void addTeacher(Teacher teacher); // 删除 void deleteTeacher(Teacher teacher); // 修改 void updateTeacher(Teacher teacher); // 查询 List<Teacher> findTeachers(); }
TeacherServiceImpl
public class TeacherServiceImpl implements TeacherService { private TeacherDao dao; //新增 public void addTeacher(Teacher teacher) { dao.addTeacher(teacher); } //删除 public void deleteTeacher(Teacher teacher) { dao.deleteTeacher(teacher); } //修改 public void updateTeacher(Teacher teacher) { dao.updateTeacher(teacher); } //查询所有 public List<Teacher> findTeachers() { return dao.findTeachers(); } public TeacherDao getDao() { return dao; } public void setDao(TeacherDao dao) { this.dao = dao; } }
创建spring的配置文件以及需要的properties文件
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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 配置数据源 dbcp数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${driverClass}" /> <property name="url" value="${jdbcUrl}" /> <property name="username" value="${user}" /> <property name="password" value="${password}"/> </bean> <!-- 使用配置文件 加载 数据库需要的4要素 经常使用 --> <context:property-placeholder location="classpath:jdbc.properties" /> <!--配置sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- 读取hibernate配置文件<property name="configLocation" value="classpath:hibernate.cfg.xml"/> --> <!-- 配置数据源 --> <property name="dataSource" ref="dataSource"></property> <!-- 配置映射文件 Teacher.hbm.xml --> <property name="mappingDirectoryLocations" value="cn/bdqn/bean"/> <property name="hibernateProperties"> <props> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> </props> </property> </bean> <!--配置dao层 --> <bean id="teacherDao" class="cn.bdqn.dao.impl.TeacherDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!--配置service层 --> <bean id="teacherService" class="cn.bdqn.service.impl.TeacherServiceImpl"> <property name="dao" ref="teacherDao"></property> </bean> <!-- 配置action层 --> <!-- ==========================事务======================================= --> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 设置事务的通知 --> <tx:attributes> <!-- 对连接点上的方法进行事务属性的配置 --> <tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED"/> <tx:method name="find*" read-only="true" isolation="DEFAULT" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <aop:config> <!-- 指定切入点 --> <aop:pointcut expression="execution(* *..service.*.*(..))" id="myPoint"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint"/> </aop:config> </beans>
创建对应的测试类
TeacherTest
public class TeacherTest { //新增 @Test public void testAdd(){ ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); TeacherService service= (TeacherService) context.getBean("teacherService"); service.addTeacher(new Teacher(1, 50, "xxxx", new Date())); } //删除 @Test public void testDel(){ ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); TeacherService service= (TeacherService) context.getBean("teacherService"); Teacher teacher=new Teacher(); teacher.settId(3); service.deleteTeacher(teacher); } //修改 @Test public void testUpdate(){ ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); TeacherService service= (TeacherService) context.getBean("teacherService"); Teacher teacher=new Teacher(); teacher.settId(2); teacher.setTage(50); service.updateTeacher(teacher); } //查询所有 @Test public void testFind(){ ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); TeacherService service= (TeacherService) context.getBean("teacherService"); List<Teacher> teachers = service.findTeachers(); for (Teacher teacher : teachers) { System.out.println(teacher); } } }
与hibernate整合 不使用 hibernate模版 这种方式 推荐使用
底层代码
更改之后的TeacherDaoImpl
/** * */ package cn.bdqn.dao.impl; import java.util.List; import org.hibernate.SessionFactory; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import cn.bdqn.bean.Teacher; import cn.bdqn.dao.TeacherDao; /** * HibernateDaoSupport:是spring为hibernate提供的工具类 * getHibernateTemplate()是获取模版! * 什么时候给它赋值的???? * spring容器 通过setHibernateTemplate! * * * * 我们发现 在底层 其实 还是默认调用了 getCurrentSession * 所以我们 直接创建我们自己的SessionFactory * */ public class TeacherDaoImpl implements TeacherDao { private SessionFactory sessionFactory; // 新增 public void addTeacher(Teacher teacher) { sessionFactory.getCurrentSession().save(teacher); } // 删除 public void deleteTeacher(Teacher teacher){ sessionFactory.getCurrentSession().delete(teacher); } // 修改 public void updateTeacher(Teacher teacher){ sessionFactory.getCurrentSession().update(teacher); } // 查询 public List<Teacher> findTeachers(){ return sessionFactory.getCurrentSession().find("from Teacher"); } public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } }
getCurrentSession
/* getCurrentSession 和 OpenSession的区别 01.getCurrentSession创建的session会绑定到当前的线程!OpenSession不会 每次都是创建一个新的session 02.getCurrentSession创建的session 在事务回滚或者提交的时候,都会自动或关闭 OpenSession不会 在sessionFactory创建的时候。hibernate会根据配置创建响应的CurrenSessionContext 在getCurrentSession的时候,实际被执行的是CurrenSessionContext.currentSession() 如果CurrenSessionContext.currentSession()为空,则调用sessionFactory的OpenSession! */
底层代码片段
在applicationContext.xml文件中增加currentSession的配置
需要更改的代码块
<!--配置sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- 读取hibernate配置文件<property name="configLocation" value="classpath:hibernate.cfg.xml"/> --> <!-- 配置数据源 --> <property name="dataSource" ref="dataSource"></property> <!-- 配置映射文件 Teacher.hbm.xml --> <property name="mappingDirectoryLocations" value="classpath:cn/bdqn/bean"/> <property name="hibernateProperties"> <props> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <!-- 当前的事务线程内 使用session --> <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate3.SpringSessionContext</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> </props> </property> </bean>
二.spring与struts的整合
创建一个注册界面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="AddServlet" method="post"> 用户名:<input type="text" name="name" /> 年龄:<input type="text" name="age" /> <button type="submit">注册</button> </form> </body> </html>
创建对应的servlet处理
public class AddServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); //解决乱码问题 String age = request.getParameter("age"); String name = request.getParameter("name"); Teacher teacher = new Teacher(); teacher.settAge(Integer.parseInt(age)); teacher.settName(name); /* * 创建Spring容器 这种方式 性能低下! 每次访问servlet都会创建一个容器对象 放在当前新增servlet的init方法中 修改 * 删除 查询 等。。。。。 这样一来 有几个servlet就会有几个spring容器! * ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); * * 怎么能保证 在整个应用程序中 只有一个容器对象! ServletContextListener 整个应用程序的监听器 */ WebApplicationContext context = (WebApplicationContext) this .getServletContext() .getAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); System.out.println(context); // 从容器获取service TeacherService service = (TeacherService) context .getBean("teacherService"); // 调用新增的方法 service.addTeacher(teacher); // 转发到成功界面 request.getRequestDispatcher("success.jsp").forward(request, response); } }
修改后的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"> <display-name></display-name> <!-- 配置全局监听器 确保 容器 对象 只被实例化一次! --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 默认xml名称 必须是 applicationContext.xml 必须在 WEB-INF的根目录下 现在我们 设置applicationContext.xml文件的路径 我们也可以更改 xml文件的名称 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <servlet> <servlet-name>AddServlet</servlet-name> <servlet-class>cn.bdqn.servlet.AddServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AddServlet</servlet-name> <url-pattern>/AddServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
相应的底层代码
源代码
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) throws IllegalStateException, BeansException { if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException( "Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ContextLoader* definitions in your web.xml!"); } servletContext.log("Initializing Spring root WebApplicationContext"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { // Determine parent for root web application context, if any. ApplicationContext parent = loadParentContext(servletContext); // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. this.context = createWebApplicationContext(servletContext, parent); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context); if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } return this.context; } catch (RuntimeException ex) { logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; } catch (Error err) { logger.error("Context initialization failed", err); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); throw err; } }
开始正式的与struts2进行整合
struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="default" namespace="/" extends="struts-default"> <!-- 每次请求AddServlet 都会实例化一个 对象 需要让spring容器去管理 --> <action name="AddServlet" class="teacherAction" method="add"> <result>/success.jsp</result> </action> </package> </struts>
对应的action
public class AddAction extends ActionSupport { private String name; private Integer age; /* * 默认采用了 byName 方式 注入 但是前提 TeacherService的属性名称必须和容器中的service名称一致 * 可以查看default.properties文件 查看 * 我们现在写的方式不是byName */ private TeacherService service; public String add(){ System.out.println("进入add"); Teacher teacher=new Teacher(); teacher.settAge(age); teacher.settName(name); service.addTeacher(teacher); return SUCCESS; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public TeacherService getService() { return service; } public void setService(TeacherService service) { this.service = service; } }
在applicationContext.xml文件中新增
<!-- 配置action层 bean默认是单例! action是多例 scope配置成多例 --> <bean id="teacherAction" class="cn.bdqn.action.AddAction" scope="prototype"> <property name="service" ref="teacherService"></property> </bean>
OpenSessionInView模式
在 dao层以及service层创建对应的 根据ID获取Teacher的信息! 使用get方式 不会报错! 但是使用load方式获取数据的话,就会出现No Session! 因为在前台真正获取数据的时候,事务已经提交了,session也关闭了! 这时候 我们需要配置 OpenSessionInView模式!来保证用户获取数据的时候还有session! 只需要在web.xml文件中配置如下节点: <!-- 设置openSessionInView 必须在struts2的核心控制器 之前 不然会起作用 --> <filter> <filter-name>open</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>open</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置struts2的核心控制器 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>