- 先说点废话
s2sh,就是struts2,spring,hibernate;s2作为表现层和控制器,hibernate作为持久层,spring作为业务层(充分应用IOC和AOP)。其实业务还是业务,只是依赖类通过spring来注入和管理,使得代码非常简洁(前提你得非常熟悉,不然就像在下一样即将发疯);spring的应用主要是在管理对象的c创建(IOC)还有数据库事物的管理(AOP),今天熟悉了IOC的使用,写个demo记录一下。
- 准备事项
配置ssh的环境,主要是导包和创建配置文件。
struts的配置文件struts.xml,hibernate的配置文件hibernate.cfg.xml,spring的配置文件applicationContext.xml;
以及修改web.xml。
- 整合例子
目录如下,仍然是mvc,model存表对象,service存数据库事物,dao存单个表操作,action是控制器。
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>SpringPractice</display-name> <welcome-file-list> <welcome-file>hello</welcome-file> </welcome-file-list> <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> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation </param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> </web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /> <!-- submit不换行 --> <constant name="struts.ui.theme" value="simple" /> <constant name="struts.i18n.encoding" value="UTF-8"/> <!--整合spring--> <constant name="struts.objectFactory" value="spring" /> <!-- Add packages here --> <package name="default" namespace="/" extends="struts-default"> <!-- 测试action--> <!-- class对应applicationContext.xml的id,在applicationContext.xml上配置真是路径 --> <action name="add" class="add"> <result name="success"></result> </action> <action name="delete" class="delete"> <result name="success"></result> </action> <action name="testHello" class="Hello"> <result name="success"></result> </action> </package> </struts>
hibernate.xml 其实可以不要了,全部配在了applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.password">qwert1234</property> <property name="hibernate.connection.url">jdbc:mysql://3306:MyData?useSSL=true</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.characterEncoding">utf-8</property> <property name="show_sql">true</property> --> </session-factory> </hibernate-configuration>
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="root"></property> <property name="password" value="qwert1234"></property> <property name="url" value="jdbc:mysql://localhost:3306/MyData?useSSL=true"></property> <property name="driverClassName" value="com.mysql.jdbc.Driver" ></property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> --> <!-- 注入一个DataSource --> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.hbm2ddl.auto">false</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>model/user.hbm.xml</value> </list> </property> </bean> <bean id="userDaoImpl" class="dao.userDaoImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <bean id="userService" class="service.UserService" scope="prototype"> <property name="userDaoImpl" ref="userDaoImpl"></property> </bean> <!-- 配置action--> <bean id="add" class="action.addUserAction" scope="prototype"> <property name="userService" ref="userService"></property> </bean> <bean id="delete" class="action.deleteAction" scope="prototype"> <property name="userService" ref="userService"></property> </bean> <bean id="Hello" class="action.HelloAction" autowire="byName" scope="prototype"> </bean> </beans>
service对象里面有一个dao对象,是通过注入使用的;配置控制器的时候,把service注入进去,在此之前先实例化一个service对象;值得注意的是hibernate和spring的整合。
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="root"></property> <property name="password" value="qwert1234"></property> <property name="url" value="jdbc:mysql://localhost:3306/MyData?useSSL=true"></property> <property name="driverClassName" value="com.mysql.jdbc.Driver" ></property> </bean>
首先配置dataSource,class可以配jdbc或者是其他的连接池。配完了这几行,hibernate对应的配置可以去掉了。
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!-- <property name="configLocation" value="classpath:hibernate.cfg.xml"></property> --> <!-- 注入一个DataSource --> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.hbm2ddl.auto">false</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="mappingResources"> <list> <value>model/user.hbm.xml</value> </list> </property> </bean>
然后配置sessionFactory,注入dataSource,里面的key配置了数据库方言和hibernate的其他配置,配完之后可以去掉hibernate配置文件相应的地方了,list里配置了mapping,把映射表也配上了,所以hibernate的配置文件完全没用了。
<bean id="userDaoImpl" class="dao.userDaoImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean>
最后在dao中注入sessionFactory,这样就可以使用getHibernateTemplate这个方法了,少了很多代码。
userDao.java
package dao; import java.util.List; import model.user; public interface userDao { public void save(user user); public void delete(user user); public void update(user user); public List<user> select(); }
userDaoImpl.java
package dao; import java.util.List; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import model.user; public class userDaoImpl extends HibernateDaoSupport implements userDao{ @Override public void save(user user) { // TODO Auto-generated method stub this.getHibernateTemplate().save(user); } @Override public void delete(user user) { // TODO Auto-generated method stub String hql = "delete from user where username = "+user.getUsername(); this.getHibernateTemplate().bulkUpdate(hql); } @Override public void update(user user) { // TODO Auto-generated method stub this.getHibernateTemplate().update(user); } @Override public List<user> select() { // TODO Auto-generated method stub String hql = "from user"; List<user> list = (List<model.user>) this.getHibernateTemplate().find(hql); return list; } }
UserService.java
package service; import java.util.List; import dao.userDaoImpl; import model.user; public class UserService { private userDaoImpl userDaoImpl; public userDaoImpl getUserDaoImpl() { return userDaoImpl; } public void setUserDaoImpl(userDaoImpl userdao) { this.userDaoImpl = userdao; } //服务 public void addService(user u){ userDaoImpl.save(u); } public void updateService(user u){ userDaoImpl.update(u); } public void deleteService(user u){ userDaoImpl.delete(u); } public List<user> selectAllService(){ return userDaoImpl.select(); } }
控制器
package action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import model.user; import service.UserService; public class addUserAction extends ActionSupport implements ModelDriven<user>{ private user u; private UserService userService; public UserService getUserService() { return userService; } public void setUserService(UserService usService) { this.userService = usService; } public user getU() { return u; } public void setU(user u) { this.u = u; } @Override public user getModel() { if(u == null) // TODO Auto-generated method stub u = new user(); return u; } public String execute(){ this.userService.addService(u); return SUCCESS; } }
package action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import model.user; import service.UserService; public class deleteAction extends ActionSupport implements ModelDriven<user>{ private user u; private UserService userService; public UserService getUserService() { return userService; } public void setUserService(UserService usService) { this.userService = usService; } public user getU() { return u; } public void setU(user u) { this.u = u; } @Override public user getModel() { if(u == null) // TODO Auto-generated method stub u = new user(); return u; } public String execute(){ this.userService.deleteService(u); return SUCCESS; } }
页面代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>添加用户</title> </head> <body> <form action="add"> <table> <tr> <td>用户名:</td> <td><input type="text" size="18" name="username"></td> </tr> <tr> <td>密码:</td> <td><input type="password" size="18" name="password"></td> </tr> </table> <s:submit value="提交"></s:submit> <s:reset value="重置"></s:reset> </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@taglib prefix="s" uri="/struts-tags"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>删除用户</title> </head> <body> <form action="delete"> <table> <tr> <td>用户名:</td> <td><input type="text" size="18" name="username"></td> </tr> <tr> <td>密码:</td> <td><input type="password" size="18" name="password"></td> </tr> </table> <s:submit value="提交"></s:submit> <s:reset value="重置"></s:reset> </form> </body> </html>
- 错误
首先遇到的异常非常多,我甚至有些怀疑(厌烦)spring框架的加入。
1.命名注入对象的时候要按照驼峰命名法。
2.莫名其妙无法打开数据库的链接,重新写配置文件不适用properties之后正常了。
org.springframework.dao.DataAccessResourceFailureException: Cannot open connection; nested exception is org.hibernate.exception.JDBCConnectionException: Cannot open connection at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAcce
java.lang.NumberFormatException: For input string
3.struts配置action的时候不能不配置result,跳一堆红字...
4.在使用映射的时候,没有主键的时候会出错(或者我没找到合适的方式用)。如下错误:
ids for this class must be manually assigned before calling save(): model.user; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): model.user
5.仔细写配置文件,超坑。类似如下:
Invalid property 'userService' of bean class [action.addUserAction]: Bean property 'userService' is not writable or has an invalid setter method. Did you mean 'usService'?
6.tomcat经常添乱,因为启动记录里面的项目关闭了或者删除了。最后我把服务器删了重新添加,受够了启动无限报错。
java.lang.IllegalArgumentException: Document base
7.仔细写好路径,web.xml的,不然有如下错误。
parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]
- 最后
仍然很欣慰能运行正常,添加了spring之后设计变得简洁很多(非常仔细地写),如果使用了AOP则可以在不改写原有代码的情况下增加功能。