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中定義的類.這樣就可以調用里面的方法了。
轉自:http://blog.csdn.net/yaoyeyzq/article/details/6623571