关键字 : struts2 spring2 hibernate3
Struts 2,Spring 2,Hibernate 整合
开发工具 Eclipse 6.5/6.6 GA
1. 首先创建一个 web 工程,我们暂且启明为 s2sh
这里我们选择的是 Java EE 5.0
finish
2. 向工程加入 hibernate 支持,这里我们使用的是 hibernate 3.2
默认就可以,不要忘记将 jar 包加入到 /WebRoot/WEB-INF/lib
实际上这里的 hibernate.cfg.xml 不起作用,因为该配置文件的内容由后面的 spring 配置文件进行管理,我们可以在创建之后将其删除
默认 next
我们根本不用 hibernate.cfg.xml, 所以这里根本不需要进行数据库配置,当然默认也无所谓。
继续 next
sessionFactory 我们在之后也会直接使用 spring 为我们提供的,所以这里不需要创建。
finish
3. 向工程加入 spring 支持,这里我们使用的是 spring2
这里我们选择的是 spring2 ,
不要忘记选中这 5 个库包:
Spring 2.0 AOP Libraries
Spring 2.0 Core Libraries
Spring 2.0 Persistence Core Libraries
Spring 2.0 Persistence JDBC Libraries
Spring 2.0 Web Libraries
也不要忘记将 jar 包加入到 /WebRoot/WEB-INF/lib 。
next
这里我们不需要 Enable AOP 所以不需要选中
不要忘记将配置文件 applicationContext.xml 指定在 /WEB-INF 目录下,不然服务器启动时无法加载
next
这里的 sessionFactory 我们也不需要,之后会手动配置。
finish
4. 加入 struts2 支持,由于 MyEclipse 并没有加入 Struts2 的支持,所以我们需要手动导入相关 jar 包。
这里我们使用的是 struts 2.0.11 版本
需要的相关 jar 包如下:
freemarker-2.3.8.jar
ognl-2.6.11.jar
struts2-core-2.0.11.jar
xwork-2.0.4.jar
struts2-spring-plugin-2.0.11.jar
4. 进行相关文件的配置
首先我们需要在 src 下加入 struts 的配置文件 struts.xml
- <?xml version ="1.0" encoding ="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
- "http://struts.apache.org/dtds/struts-2.0.dtd">
- <struts>
- <package name ="s2sh" extends ="struts-default" >
- </package>
- </struts>
接下来我们配置 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">
- <!-- 配置 struts2 的过滤器 -->
- <filter>
- <filter-name> struts2</filter-name>
- <filter-class>
- org.apache.struts2.dispatcher.FilterDispatcher
- </filter-class>
- </filter>
- <filter-mapping>
- <filter-name> struts2</filter-name>
- <url-pattern> /*</url-pattern>
- </filter-mapping>
- <!-- 配置 spring 的监听器 -->
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <welcome-file-list>
- <welcome-file> index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
到目前为止我们的整合工作已经完成。我们可以将该工程打包,以备下次直接使用。
这里由一个问题就是如果采用 myeclipse 加载 hibernate 和 spring 的 lib 包形式发布项目的时候会出现异常,我们可以手动去掉一个 asm-2.2.3jar 即可。
5. 下面我们做一个简单的应用来验证。
(1) 首先我们使用的是 mysql ,不要忘记将 mysql-jdbc 的 jar 包导入到我们的工程中
我们创建 s2sh 数据库,并创建表 person
- -- Table "person" DDL
- CREATE TABLE `person` (
- `id` int (11) NOT NULL ,
- `name ` varchar (20) NOT NULL ,
- `age` int (11) NOT NULL ,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
(2) 首先我们创建 test.s2sh.bean 包 , 在下面创建我们 person 表对应的 Entity Bean 及其映射文件
Person.java
- package test.s2sh.bean;
- public class Person {
- private Integer id;
- private String name;
- private int age;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this .id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this .name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this .age = age;
- }
- }
Person.hbm.xml
- <?xml version ="1.0" encoding ="utf-8" ?>
- <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name ="test.s2sh.bean.Person" table ="person" >
- <id name ="id" type ="java.lang.Integer" column ="id" >
- <generator class ="increment" ></generator>
- </id>
- <property name ="name" type ="string" column ="name"
- length ="20" ></property>
- <property name ="age" type ="java.lang.Integer" column ="age" ></property>
- </class>
- </hibernate-mapping>
(3) 在 spring 配置文件 applicationContext.xml 配置 hibernate 的连接数据库信息及 sessionFactory 创建方式
- <?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-2.0.xsd" >
- <!-- apache.dbcp 连接池的配置 -->
- <bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" destroy-method ="close" >
- <property name ="driverClassName" value ="com.mysql.jdbc.Driver" ></property>
- <property name ="url" value ="jdbc:mysql://localhost:3306/s2sh?useUnicode=true&characterEncoding=UTF-8" ></property>
- <property name ="username" value ="root" ></property>
- <property name ="password" value ="" ></property>
- <!-- 最大活动连接数 -->
- <property name ="maxActive" value ="100" ></property>
- <!-- 最大可空闲连接数 -->
- <property name ="maxIdle" value ="30" ></property>
- <!-- 最大可等待连接数 -->
- <property name ="maxWait" value ="500" ></property>
- <!-- 默认的提交方式(如果不需要事务可以设置成 true ,在实际应用中一般设置为 false, 默认为 false ) -->
- <property name ="defaultAutoCommit" value ="true" ></property>
- </bean>
- <!-- 这里直接使用 spring 对 hibernate3 支持的 sessionFactory -->
- <bean id ="sessionFactory" class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
- <property name ="dataSource" ref ="dataSource" ></property>
- <!-- hibernate 方言等相关配置 -->
- <property name ="hibernateProperties" >
- <props>
- <prop key ="connection.useUnicode" > true</prop>
- <prop key ="connection.characterEncoding" > utf-8</prop>
- <prop key ="hibernate.dialect" > org.hibernate.dialect.MySQLDialect</prop>
- <prop key ="hibernate.show_sql" > true</prop>
- </props>
- </property>
- <!-- hbm.xml 的映射文件 -->
- <property name ="mappingResources" >
- <list>
- <value> test/s2sh/bean/Person.hbm.xml</value>
- </list>
- </property>
- </bean>
- </beans>
如果出现乱码问题,可以考虑如下解决方案
- <property name ="hibernateProperties" >
- <props>
- <prop key ="connection.useUnicode" > true</prop>
- <prop key ="connection.characterEncoding" > utf-8</prop>
- <prop key ="hibernate.dialect" > org.hibernate.dialect.MySQLDialect</prop>
- <prop key ="hibernate.show_sql" > true</prop>
- </props>
- </property>
或者将 url 后面加入编码串 , 如下
- <property name ="url" value ="jdbc:mysql://localhost:3306/s2sh?useUnicode=true&characterEncoding=UTF-8" ></property>
注意 : 这里我的数据库编码是 utf-8
具体那种方案好用大家可以尝试一下,我基本上直接将两种方式都加上了。
(4) 下面我们开始写 DAO 层,首先创建 test.s2sh.dao 包放置 Dao 类的接口,创建 test.s2sh.dao.impl 包放置 Dao 类的实现。
PersonDAO.java
- package test.s2sh.dao;
- import java.util.List;
- import test.s2sh.bean.Person;
- public interface PersonDAO {
- void savePerson(Person p);
- void removePerson(Person p);
- Person findPersonById(Integer id);
- List<Person> findAllPersons();
- void updatePerson(Person p);
- }
由于使用了 spring ,所以 DAO 的实现类我们可以继承 HibernateDaoSupport 进行实现
PersonDAOImpl.java
- package test.s2sh.dao.impl;
- import java.util.List;
- import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
- import test.s2sh.bean.Person;
- import test.s2sh.dao.PersonDAO;
- public class PersonDAOImpl extends HibernateDaoSupport implements PersonDAO {
- public List<Person> findAllPersons() {
- String hql = "from Person p order by p.id desc" ;
- return (List<Person>)this .getHibernateTemplate().find(hql);
- }
- public Person findPersonById(Integer id) {
- Person p = (Person) this .getHibernateTemplate().get(Person.class , id);
- return p;
- }
- public void removePerson(Person p) {
- this .getHibernateTemplate().delete(p);
- }
- public void savePerson(Person p) {
- this .getHibernateTemplate().save(p);
- }
- public void updatePerson(Person p) {
- this .getHibernateTemplate().update(p);
- }
- }
(5) 下面我们开始进行 service 层的设计,这里的 service 层仅是简单调用 DAO 层的的方法。
同样是创建接口包 (test.s2sh.service) ,实现包和接口类 (test.s2sh.service.impl) ,实现类
PersonService.java
- package test.s2sh.service;
- import java.util.List;
- import test.s2sh.bean.Person;
- public interface PersonService {
- List<Person> findAll();
- void save(Person p);
- void delete(Person p);
- Person findById(Integer id);
- void update(Person p);
- }
这里我们需要使用 spring 的 ioc 将 DAO 诸如到 service 中,所以不要忘记在 service 实现类中加入 DAO 作为属性。
PersonServiceImpl.java
- package test.s2sh.service.impl;
- import java.util.List;
- import test.s2sh.bean.Person;
- import test.s2sh.dao.PersonDAO;
- import test.s2sh.service.PersonService;
- public class PersonServiceImpl implements PersonService {
- private PersonDAO personDAO;
- public void delete(Person p) {
- this .personDAO.removePerson(p);
- }
- public List<Person> findAll() {
- return this .personDAO.findAllPersons();
- }
- public Person findById(Integer id) {
- return this .personDAO.findPersonById(id);
- }
- public void save(Person p) {
- this .personDAO.savePerson(p);
- }
- public void update(Person p) {
- this .personDAO.updatePerson(p);
- }
- public PersonDAO getPersonDAO() {
- return personDAO;
- }
- public void setPersonDAO(PersonDAO personDAO) {
- this .personDAO = personDAO;
- }
- }
(6) 接下来我们开始对 action 层进行设置,实际项目中的 action 可能会有很多,所以我们这里需要对 action 进行分包,因为我们这里针对 Person 进行操作,所以我们创建 test.s2sh.action.person.
这里先做保存操作
SavePersonAction.java
- package test.s2sh.action.person;
- import test.s2sh.bean.Person;
- import test.s2sh.service.PersonService;
- import com.opensymphony.xwork2.ActionSupport;
- public class SavePersonAction extends ActionSupport {
- private Person p;
- private PersonService service;
- public Person getP() {
- return p;
- }
- public void setP(Person p) {
- this .p = p;
- }
- public PersonService getService() {
- return service;
- }
- public void setService(PersonService service) {
- this .service = service;
- }
- public String execute() throws Exception {
- this .service.save(p);
- return this .SUCCESS;
- }
- public void validate() {
- if (p.getName()==null ||"" .equals(p.getName())){
- this .addFieldError("p.name" , "name is not null" );
- }
- }
- }
下面创建一个保存人员的提交页面
save.jsp
- <%@ page language="java" import ="java.util.*" pageEncoding="utf-8" %>
- <%@ taglib prefix="s" uri="/struts-tags" %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
- <html>
- <head>
- <title>Save Person</title>
- </head>
- <body>
- <s:form action="savePerson" >
- <s:textfield name="p.name" label="name" ></s:textfield>
- <s:textfield name="p.age" label="age" ></s:textfield>
- <s:submit></s:submit>
- </s:form>
- </body>
- </html>
操作成功页面
save-success.jsp
- <%@ page language="java" import ="java.util.*" pageEncoding="utf-8" %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" >
- <html>
- <head>
- <title>Save OK</title>
- </head>
- <body>
- 保存成功 <br>
- </body>
- </html>
接下来我们需要配置 struts.xml, 创建 action
- <action name ="savePerson" class ="savePersonAction" >
- <result name ="success" type ="redirect" > /save-success.jsp</result>
- <result name ="input" > /save.jsp</result>
- </action>
由于现在的 action 的创建已经由 spring 所接管,所以这里 class 里面使用的是别名,该别名与 applicationContext.xml 中的 id 对应 .
接下来我们需要配置 applicationContext 的 ioc 。
- <bean id ="personDAO" class ="test.s2sh.dao.impl.PersonDAOImpl" scope ="singleton" >
- <!-- 由于该类是继承于 HibernateDaoSupport ,所以需要将 sessionFactory 注入 -->
- <property name ="sessionFactory" >
- <ref bean ="sessionFactory" />
- </property>
- </bean>
- <bean id ="personService" class ="test.s2sh.service.impl.PersonServiceImpl" >
- <property name ="personDAO" ref ="personDAO" ></property>
- </bean>
- <bean id ="savePersonAction" class ="test.s2sh.action.person.SavePersonAction" scope ="prototype" >
- <property name ="service" ref ="personService" ></property>
- </bean>
这里说明一下 spring 中的单例与设计模式中的单例不同,设计模式的单例是在 jvm 中只产生一个实例,而 spring 中的单例
是针对每个 ioc 容器来言,如果存在两个 ioc 容器,那么每个 ioc 容器都会生成唯一的类实例
将 sessionFactory 注入 Dao 中 , 这里的 Dao 来说是无状态的,可以设置为单例 singleton 。这里的 action 是使用 spring 创建的。
struts2 与 struts1 的 action 有所不同,因为 struts2 中的 action 中可能存在属性 , 这里是 Person ,所以 struts2 的 action 可能是有状态的。
如果是有状态的我们就需要将 scope 设置成原型模式,即每次请求都新建一个 action 。
不然可能会出现如果表单提交的第一次出错,之后就再也提交不过去了,值就是应为使用默认的 singleton ,
当第一次的时候就将 FieldError 中加入了错误,每次都是这个 action ,始终带着这个错误,所以就提交不过去了。
到目前为止这个整合已经完成了。
今天整合 s2sh 框架,碰到
ids for this class must be manually assigned before calling save(): test.s2sh.bean.Person
引起这个原因是:在整合过程中person
中的id
是自增的,而
表A
的id
字段不是自增字段,采用hibernate
的
< id name = "id" type = "java.lang.Integer" >
< column name = "id" />
< generator class = "increment" />
</ id >
本篇文章来自<A href='http://www.soidc.net'>IDC
专家网</a>
原文链接:http://www.soidc.net/discuss/1/060812/16/196029_1.html
遇到的问题:
第四步:调试
双击 Package Explorer 下 MySpringTest/src/TestAction.java 打开源代码 , 点击菜单 Run -> Run As -> 1. Java Application , 如果没有错误的话将会出现如下
1 log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
2 log4j:WARN Please initialize the log4j system properly.
3 HELLOROD JOHNSON
4 hellojeckj
解决方法:
在 WEB-INF/class 目录下建立一个 log4j.properties 文件 , 内容如下 :
log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n
刷新后就可以解决这个问题了!