struts2.2.1+spring 3.0.3+hibernate3.6+dwr3.0全註解整合詳解

今天搭建了一個ssh+dwr框架,其實ssh框架配置和以前差不多,主要是使用了註解實現C和M層,下面就是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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>nwr-web</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:applicationContext*.xml</param-value>
	</context-param>
	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>/WEB-INF/classes/log4j.properties</param-value>
	</context-param>
	<context-param>
		<param-name>log4jRefreshInterval</param-name>
		<param-value>60000</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>	
	<filter>
		<filter-name>struts-prepare</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>
		<init-param>
			<param-name>actionPackages</param-name>
			<param-value>com.essential.action</param-value>
		</init-param>
	</filter>
	<filter>
		<filter-name>struts-execute</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>
	</filter>	
	<servlet>
		<servlet-name>dwr</servlet-name>
		<servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>true</param-value>
		</init-param>
	</servlet>
	<filter-mapping>
		<filter-name>struts-prepare</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>struts-execute</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<servlet-mapping>
		<servlet-name>dwr</servlet-name>
		<url-pattern>/dwr/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>News.jsp</welcome-file>
	</welcome-file-list>
	<error-page>
		<error-code>500</error-code>
		<location>/error.jsp</location>
	</error-page>
	<error-page>
		<error-code>402</error-code>
		<location>/error.jsp</location>
	</error-page>
</web-app>

唯一需要說明一下的就是如果要使用struts2的註解就必須在配置filter的時候帶上actionPackages的參數,這個參數就是設置struts2容器搜索action的包路徑。

下面是struts.xml的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
    "http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>
	<package name="default" extends="struts-default">
		<global-results>
			<result name="error">error.jsp</result>
			<result name="input">error.jsp</result>
		</global-results>
	</package>
	<constant name="struts.convention.default.parent.package"
		value="default" />
</struts>

我是用的struts.convention插件把所有action的父包都定義爲我自定義的一個default包,大家也可以自定義其它父包,這樣定義的父包是所有action的默認父包,當然你也可以使用@package標籤爲action類定義不同的包。

下面介紹spring的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:dwr = "http://www.directwebremoting.org/schema/spring-dwr"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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-3.0.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
       http://www.directwebremoting.org/schema/spring-dwr 
       http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"
       >
    <dwr:annotation-scan scanRemoteProxy="true" base-package="com.essential.dwr"/>
    <dwr:annotation-scan scanDataTransferObject="true" base-package="com.essential.entity"/>
	<context:component-scan base-package="com.essential" />
	
    <bean id="configurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
           <value>classpath*:init.properties</value>
        </property>
    </bean>
	
	<bean id="mainDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
	   <property name="driverClass" value="${jdbc.driverClass}"></property>
       <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
       <property name="user" value="${jdbc.user}"></property>
       <property name="password" value="${jdbc.password}"></property>
  
       <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
       <property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
       <property name="initialPoolSize" value="${jdbc.initialPoolSize}"></property>
       <property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"></property>
       <property name="maxIdleTime" value="${jdbc.maxIdleTime}"></property>
       <property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>    
	</bean>

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
		<property name="targetDataSource">
			<ref local="mainDataSource" />
		</property>
	</bean>

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>

		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
				<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
				<prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
				<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
			</props>
		</property>

		<property name="packagesToScan" value="${hibernate.packagesToScan}" />
	</bean>

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>

	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="upd*" propagation="REQUIRED" read-only="false" />
			<tx:method name="del*" propagation="REQUIRED" read-only="false" />
			<tx:method name="add*" propagation="REQUIRED" read-only="false" />
			<tx:method name="insert*" propagation="REQUIRED" read-only="false" />
			<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
			<tx:method name="query*" propagation="SUPPORTS" read-only="true" />
			<tx:method name="*" propagation="SUPPORTS" read-only="true" />
		</tx:attributes>
	</tx:advice>

	<aop:config>
		<aop:pointcut id="productServiceMethods"
			expression="${spring.execution}" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods" />
	</aop:config>
	
</beans>

首先前兩行配置是dwr和spring整合的配置第一個是配置dwr的遠程代理對象的所在的包名,第二個則是dwr裏的傳輸對象所在的包名。

下面一行是spring搜索bean的包名。下面其他的配置和以前沒什麼變化。

現在來講講struts2的action用註解怎麼實現:

1.其實註解和xml配置步驟差不多首先肯定是配置包,但是我們前面用struts.convention配置了默認包,所以也不用再配置,然後肯定是配置訪問的虛擬路勁咯,也就是配置namespace,使用@Namespace(value = "/mail")標籤配置,value屬性是配置namespace的路徑。

2.配置好了namespace然後就是action咯,配置這個是使用@Action(value = "sendMail", results = { @Result(name = SUCCESS, type = "redirect", location = "../News.jsp") })標籤,其中value是配置action的路徑,results是配置action的處理結果跳轉頁面,也可以配置多個頁面。

這樣就配置好了一個完整的action咯,我們現在要和spring整合就必須調用spring的bean,要調用bean很簡單定義一個私有變量,然後在變量上使用@resource標籤就行了,但是需要注意的是這裏的變量名必須和後面要講到的@service標籤中的名字要一致才行,不然注入不進來。

下面附上一個例子:

public class ActivityAction extends BaseAction {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5488332603981342055L;

	private long uid;

	private long eventId;

	private ActivityService activityService;

	/**
	 * 查詢活動列表
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "findActivityList")
	public String findActivityList() throws Exception {
		List<ActivityVo> activityVos = activityService.findActivityList();
		String result = ListToJsonString(activityVos);
		toWrite(result);
		return null;
	}

	/**
	 * 參加活動
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "joinActivity")
	public String joinActivity() throws Exception {
		boolean isSucc = activityService.insertActivityForUser(eventId, uid);
		toWrite(isSucc + "");
		return null;
	}

	/**
	 * 根據用戶標識查找活動列表
	 * 
	 * @return 我的活動列表
	 * @throws Exception
	 */
	@Action(value = "findMyActivityList")
	public String findMyActivityList() throws Exception {
		List<ActivityVo> activityVos = activityService.findMyActivityList(uid);
		String result = ListToJsonString(activityVos);
		toWrite(result);
		return null;
	}

	@Resource
	public void setActivityService(ActivityService activityService) {
		this.activityService = activityService;
	}

	public void setUid(long uid) {
		this.uid = uid;
	}

	public void setEventId(long eventId) {
		this.eventId = eventId;
	}

}

然後來講講service的配置,配置方法是使用@service(value="serviceName")標籤設置service,很簡單不用多講,而且調用dao的時候和action調用service一樣使用@resource標籤引入屬性就行了,下面是例子源碼:

@Service(value = "activityService")
public class ActivityServiceImpl implements ActivityService {

	@Resource
	ActivityDao activityDao;

	private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	@Override
	public boolean insertActivityForUser(long eventId, long uid) {
		return activityDao.insertActivityForUser(eventId, uid);
	}

	@Override
	public List<ActivityVo> findActivityList() {
		List<Activity> list = activityDao.findActivityList();
		List<ActivityVo> activityVos = new ArrayList<ActivityVo>();
		for (Activity activity : list) {
			ActivityVo activityVo = new ActivityVo();
			activityVo.setId(activity.getId());
			activityVo.setTitle(activity.getTitle());
			activityVo.setPublishTime(df.format(activity.getPublishTime()));
			activityVo.setImagurl(activity.getImagurl());
			activityVo.setContent(activity.getContent());
			activityVos.add(activityVo);
		}
		return activityVos;
	}

	@Override
	public List<ActivityVo> findMyActivityList(long uid) {
		List<Activity> list = activityDao.findMyActivityList(uid);
		List<ActivityVo> activityVos = new ArrayList<ActivityVo>();
		for (Activity activity : list) {
			ActivityVo activityVo = new ActivityVo();
			activityVo.setId(activity.getId());
			activityVo.setTitle(activity.getTitle());
			activityVo.setPublishTime(df.format(activity.getPublishTime()));
			activityVo.setImagurl(activity.getImagurl());
			activityVo.setDatetime(activity.getDatetime());
			activityVo.setDescription(activity.getDescription());
			activityVo.setContent(activity.getContent());
			activityVos.add(activityVo);
		}
		return activityVos;
	}
}


然後就是dao的配置和前面的差不多就是定義dao的時候是用@repository標籤,直接貼代碼就行了:

@Repository(value = "activityDao")
public class ActivityDao extends BaseDao<Activity> {

	/**
	 * 參加活動
	 * 
	 * @param eventId
	 *            活動ID
	 * @param uid
	 *            用戶ID
	 * @return 成功返回true,失敗返回false
	 */
	@SuppressWarnings("unchecked")
	public boolean insertActivityForUser(long eventId, long uid) {
		Session session = getSession();
		Query query = session
				.createSQLQuery("select au.aid from activity_users au where au.aid=:aid and au.uid=:uid");
		List list = query.setParameter("uid", uid).setParameter("aid", eventId)
				.list();
		if (list.size() > 0) {
			return false;
		} else {
			session.createSQLQuery(
					"insert into activity_users(aid,uid) values(:aid,:uid)")
					.setParameter("uid", uid).setParameter("aid", eventId)
					.executeUpdate();
			return true;
		}
	}

	/**
	 * 查詢活動列表
	 * 
	 * @return 活動列表
	 */
	@SuppressWarnings("unchecked")
	public List<Activity> findActivityList() {
		Session session = getSession();
		List<Activity> list = session.createQuery(
				"from Activity where status = 2 order by publishTime desc")
				.setMaxResults(10).list();
		return list;
	}

	/**
	 * 根據用戶標識查詢用戶參加的所有活動
	 * 
	 * @param uid
	 *            用戶標識
	 * @return 活動列表
	 */
	@SuppressWarnings("unchecked")
	public List<Activity> findMyActivityList(final long uid) {
		return getHibernateTemplate().execute(new HibernateCallback() {

			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				List<Activity> list = session
						.createQuery(
								"select a from Activity a left join a.users u where u.id=:uid order by a.publishTime desc")
						.setParameter("uid", uid).list();
				return list;
			}
		});
	}

}

下面是BaseDao的代碼:

public class BaseDao<E> extends HibernateDaoSupport {

	@Resource(name = "sessionFactory")
	public void setInjectionSessionFacotry(SessionFactory sessionFacotry) {
		super.setSessionFactory(sessionFacotry);
	}

	@PostConstruct
	public void injectSessionFactory() {
		logger.info(super.getSessionFactory());
	}

	public Serializable save(E entity) {
		return getHibernateTemplate().save(entity);
	}

	public void update(E entity) {
		getHibernateTemplate().update(entity);
	}

	public void delete(E entity) {
		getHibernateTemplate().delete(entity);
	}

	public User query(long id) {
		return getHibernateTemplate().get(User.class, id);
	}

}

在這個類裏面注入sessionFactory對象。

下面來講講dwr的配置,要配置dwr的遠程代理對象在類上使用@RemoteProxy類中的方法@RemoteMethod這樣在javascript中直接用類名+方法名直接調用就行了。如果要調用spring的bean和上面一樣,就不不多說。如果dwr和jsp頁面傳輸的時候需要用到java實體那麼就在需要傳輸的實體類上用@DataTransferObject標籤,才能正確轉換類型,不然會報異常。下面是例子:

@RemoteProxy
public class TestDwr implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2060851629180328131L;

	@RemoteMethod
	public String testDwr() {
		return "測試.";
	}
}

實體的例子大家可以隨便定義一個類就行了加上標籤就OK,這裏就不列出來了。

下面是jsp使用dwr必須引入3個jsp:

<script type="text/javascript" src="<%=path %>/dwr/engine.js"></script>
<script type="text/javascript" src="<%=path %>/dwr/util.js"></script>
<script type="text/javascript" src="<%=path %>/dwr/interface/TestDwr .js"></script>

前面2個是dwr必須要使用的2個js包,後面一個就是你在java中定義的類.這樣就可以調用裏面的方法了。

 

到這裏全部講完了,有什麼不足的地方還請各位多補充。

所有jar包已經上傳,需要的可以去下載http://download.csdn.net/detail/yaoyeyzq/4516689

發佈了34 篇原創文章 · 獲贊 47 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章