现在的位置: 首页 > 综合 > 正文

Spring2.x+Struts2.x+Hibernate3.x

2014年05月08日 ⁄ 综合 ⁄ 共 11723字 ⁄ 字号 评论关闭

虽然现在Spring已经步入了3.x的时代,这里就简单介绍一下SSH集成快速快发,Spring的IOC和Hibernate使用了Annotation,Spring的AOP用了xml配置的方式,就是声明式事务的配置方式:

1.导入jar:

2.搭建框架:

a.准备资源文件jdbc.properties

jdbc.driverClass =  com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/hibernate?userUnicode=true&characterEncoding=UTF-8
jdbc.userName = root
jdbc.password =ysjian

b.配置applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
	<!-- 这里特别的注意,xsi:schemaLocation中要有上面的信息对应的地址 -->
<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:tx="http://www.springframework.org/schema/tx" 
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd


http://www.springframework.org/schema/tx


http://www.springframework.org/schema/tx/spring-tx-2.5.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-2.5.xsd


http://www.springframework.org/schema/aop

           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
           
	<!-- 使用注解的配置前提 -->
	<context:annotation-config />
	<!-- 指定在com.ssh下所有的包去匹配,需要在特定的bean中配置注解 -->
	<context:component-scan base-package="com.ssh"/>
	
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>classpath:jdbc.properties</value>
		</property>
	</bean>
	
	<!-- 配置数据源:dataSource -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="${jdbc.driverClass}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.userName}" />
		<property name="password" value="${jdbc.password}" />
	</bean>

	<!-- 配置SessionFactory,注入数据源dataSource -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<!-- 注入数据源dataSource -->
		<property name="dataSource" ref="dataSource" />
		<!-- 注入配置文件 -->
		<property name="packagesToScan">
			<list>
				<value>com.ssh.entity</value>
			</list>
		</property>
		<!-- 注入hibernate常用的属性 -->
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialet">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
				<!--<prop key="hibernate.format_sql">true</prop>
			-->
			</props>
		</property>
	</bean>
	
	<!-- 注入HibernateTemplate,建议使用组合的方式 -->
	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

	<!--配置声明式事务 ,将事务从DAO转移到BIZ-->
	<!-- 配置事务管理器 ,注入SessionFactory-->
	<bean id="hibernateTransactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!-- 定义事务通知 -->
	<tx:advice id="txAdvice" transaction-manager="hibernateTransactionManager">
		<tx:attributes>
			<tx:method name="add*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="*" propagation="SUPPORTS" />
		</tx:attributes>
	</tx:advice>
	
	<!-- 配置AOP -->
	<aop:config>
		<!-- 定义一个切入点(断言) -->
		<aop:pointcut id="bizMethods" expression="execution(* com.ssh.biz..*.*(..))" />
		<!-- 定义通知者 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="bizMethods" />
	</aop:config>
</beans>

c..配置struts.xml,这里只配了一个Action

<?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.i18n.encoding" value="GBK"></constant>
	<package name="struts2" extends="struts-default">
	<!-- 使用class="spring中Action的id" 用的是伪类 -->
		<action name="user_*" class="com.ssh.action.UserAction" method="{1}">
			<result name="success" type="redirectAction">user_doList</result>
			<result name="list">/list.jsp</result>
			<result name="detail">/update.jsp</result>
			<result name="login" type="redirect">/login.jsp</result>
		</action>
	</package>
</struts>

d.配置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">
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<!-- 监听器,初始化Spring容器,读取applicationContext.xml配置文件的信息 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<!--
			<param-value> /WEB-INF/applicationContext-*.xml,
			classpath*:applicationContext-*.xml </param-value>
		-->
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>


	<!--配置OSIV过滤器,解决在页面出现懒加载取不出数据的问题 -->
	<filter>
		<filter-name>OpenSessionInViewFilter</filter-name>
		<filter-class>
			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>OpenSessionInViewFilter</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>*.action</url-pattern>
		<url-pattern>*.jsp</url-pattern>
	</filter-mapping>
</web-app>

3.模块设计,编写model

a.实体(Userinfo)

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="userinfo")
public class Userinfo implements Serializable {
	private static final long serialVersionUID = 3171941410139893214L;
	private int uid;
	private String uname;
	private String upass;
	@Id
	@GeneratedValue
	public int getUid() {
		return uid;
	}
	public void setUid(int uid) {
		this.uid = uid;
	}
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public String getUpass() {
		return upass;
	}
	public void setUpass(String upass) {
		this.upass = upass;
	}
	@Override
	public String toString() {
		return "Userinfo [uid=" + uid + ", uname=" + uname + ", upass=" + upass
				+ "]";
	}
	
}

b.DAO(UserinfoDao&UserinfoDaoImpl)

import java.util.List;

import javax.annotation.Resource;

import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Component;

import com.ssh.dao.UserinfoDao;
import com.ssh.entity.Userinfo;

@Component("userDao")
public class UserinfoDaoImpl implements UserinfoDao {

	private HibernateTemplate hibernateTemplate;

	@Resource
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}
	/**
	 * 新增方法
	 */
	public void addUser(Userinfo user) {
		try {
			hibernateTemplate.save(user);
		} catch (DataAccessException e) {
			throw e;
		}
	}

	/**
	 * 登录
	 */
	public Userinfo login(Userinfo user) {
		String hql = "from Userinfo u where u.uname=? and u.upass=?";
		List<Userinfo> list = hibernateTemplate.find(hql, new String[] {
				user.getUname(), user.getUpass() });
		Userinfo loginUser = null;
		if (list != null && list.size() != 0) {
			loginUser = list.get(0);
		}
		return loginUser;
	}

	/**
	 * 删除
	 */
	public void deleteUser(Userinfo user) {
		try {
			hibernateTemplate.delete(user);
		} catch (DataAccessException e) {
			throw e;
		}
	}

	/**
	 * 根据编号查询
	 */
	public Userinfo getUserById(int uid) {
		return (Userinfo) hibernateTemplate.get(Userinfo.class, uid);
	}

	/**
	 * 查询所有
	 */
	public List<Userinfo> getAllUsers() {
		String hql = "from Userinfo";
		// return hibernateTemplate.loadAll(Userinfo.class);
		return hibernateTemplate.find(hql);
	}

	/**
	 * 更新
	 */
	public void updateUser(Userinfo user) {
		try {
			hibernateTemplate.update(user);
		} catch (DataAccessException e) {
			throw e;
		}
	}
}

c.BIZ(UserinfoBzi&UserinfoBizImpl)

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.ssh.biz.UserinfoBiz;
import com.ssh.dao.UserinfoDao;
import com.ssh.entity.Userinfo;

@Component("userBiz")
public class UserinfoBizImpl implements UserinfoBiz {
	
	private UserinfoDao userinfoDao;
	
	@Resource(name="userDao")
	public void setUserinfoDao(UserinfoDao userinfoDao) {
		this.userinfoDao = userinfoDao;
	}
	
	public void addUser(Userinfo user) {
		userinfoDao.addUser(user);
	}
	public Userinfo login(Userinfo user) {
		return userinfoDao.login(user);
	}
	public void deleteUser(Userinfo user) {
		userinfoDao.deleteUser(user);
	}
	public Userinfo getUserById(int uid) {
		return userinfoDao.getUserById(uid);
	}
	public List<Userinfo> getAllUsers() {
		return userinfoDao.getAllUsers();
	}

	public void updateUser(Userinfo user) {
		userinfoDao.updateUser(user);
	}
}

d.Action(BasicAction&UserAction)

import java.util.Map;

import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

public class BasicAction extends ActionSupport implements RequestAware,SessionAware{

	private static final long serialVersionUID = -978999257562885869L;
	
	protected Map<String,Object> request;
	protected Map<String,Object> session;
	
	public void setRequest(Map<String, Object> request) {
		this.request = request;
	}

	public void setSession(Map<String, Object> session) {
		this.session = session;
	}
}

mport java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.ssh.biz.UserinfoBiz;
import com.ssh.entity.Userinfo;

@Component("userAction")
public class UserAction extends BasicAction {

	private static final long serialVersionUID = -7076569534584788161L;
	
	private UserinfoBiz userBiz;

	private Userinfo user;

	@Resource(name="userBiz")
	public void setUserBiz(UserinfoBiz userBiz) {
		this.userBiz = userBiz;
	}

	public Userinfo getUser() {
		return user;
	}

	public void setUser(Userinfo user) {
		this.user = user;
	}

	/**
	 * 登录
	 * @return
	 * @throws Exception
	 */
	public String doLogin() throws Exception {
		
		Userinfo loginUser = userBiz.login(user);
		if (loginUser != null) {
			session.put("loginUser", loginUser);
			return this.SUCCESS;
		}
		return this.LOGIN;
	}

	public String doList() throws Exception {
		List<Userinfo> list = userBiz.getAllUsers();
		request.put("list", list);
		return "list";
	}

	/**
	 * 登录
	 * 
	 * @return
	 * @throws Exception
	 */
	public String doAdd() throws Exception {

		userBiz.addUser(user);
		return this.SUCCESS;
	}

	/**
	 * 查找个人详细信息系
	 * @return
	 * @throws Exception
	 */
	public String doDetail() throws Exception {

		user = userBiz.getUserById(user.getUid());
		request.put("user", user);
		
		return "detail";
	}

	/**
	 * 更新个人详细信息系
	 * @return
	 * @throws Exception
	 */
	public String doUpdate() throws Exception {
		userBiz.updateUser(user);
		
		return this.SUCCESS;
	}	
	/**
	 * 登录
	 * 
	 * @return
	 * @throws Exception
	 */
	public String doDelete() throws Exception {
		user = userBiz.getUserById(user.getUid());
		userBiz.deleteUser(user);

		return this.SUCCESS;
	}
}

大体的写好了,可以进行测试了,这里就不写了,SSH继承,简单的模式,在项目中可以再此基础上扩展。

说说几个问题:

1.那个OpenSessionInViewFilter过滤器是用来解决在jsp页面取数据是Session关闭后无法取出懒加载关联的对象,建议配上。

<!--配置OSIV过滤器,解决在页面出现懒加载取不出数据的问题 -->
	<filter>
		<filter-name>OpenSessionInViewFilter</filter-name>
		<filter-class>
			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>OpenSessionInViewFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

2.中文乱码问题,可以再Struts2中的struts.xml配置文件中配置一个常量,Spring提供了一个过滤器,但建议使用struts2中的常量。

<constant name="struts.i18n.encoding" value="GBK" />

Spring的Filter:

<!-- struts1中的乱码解决问题,在struts2中只需要设置一个常量 -->
<filter>
	<filter-name>encoding</filter-name>
		<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>GBK</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>encoding</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

3.如果在applicationContext.xml中没有配置声明式事务,那么在页面中比如注册和删除修改等操作会出现错误:

错误如下:

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

简单说一下这个原因:因为如果没有在applicationContext.xml中配置声明式事务的话,而OpenSessionInViewFilter在web.xml中有配置,OpenSessionInViewFilte此时默认对事物的管理是read-only的,所以修改操作会出现问题,而读取没有问题

a.可以去掉OpenSessionInViewFilter,但不建议这么做.

b.将声明式事务配上,不搞特殊化,呵呵。

另外我还发现,如果不配置声明式事务,在测试时,同样能给数据库保存数据,这个和之前Spring与Hibernate的集成有点区别,HibernateTemplate带来的好处,但还是不建议不配置声明式事务,如果不配置,又回到那个转账的问题了。

【上篇】
【下篇】

抱歉!评论已关闭.