当前位置: 代码迷 >> Web前端 >> 组合webservice实现dwr推送
  详细解决方案

组合webservice实现dwr推送

热度:141   发布时间:2012-11-23 00:03:43.0
结合webservice实现dwr推送
情景:
  客户端需要实时提醒服务,比如某个日程已过期的提醒,并且是刚刚过期的时间(所以是实时),
1.  日程对象放在数据库,由webservice调用得到
2.  webservice在拿到数据后必须主动把数据给我的主程序端
3.  主程序端在拿到数据后开始推送数据到客户端


代码:
public class CheckUnsignedBookingJob {
    private static final Logger log = LoggerFactory.getLogger(CheckUnsignedBookingJob.class);

    private VisitBookingService visitBookingService;

    private TourBookingService tourBookingService;

    private SignoutNoticeService signoutNoticeService;

    public void execute() {

        log.debug("CheckUnsignedBookingJob start");

        List<VisitBooking> visitBookings = visitBookingService.getUnsignoutedBookingInfo();

        log.debug("unsignouted visit booking size: {}", visitBookings.size());

        if (!visitBookings.isEmpty()) {
            for (VisitBooking visitBooking : visitBookings) {
                log.debug("visit booking number: {}", visitBooking.getBookingNumber());
                signoutNoticeService.visitBookingNotSignouted(visitBooking);
            }
        }

        List<TourBooking> tourBookings = tourBookingService.getUnsignoutedBookingInfo();

        log.debug("unsignouted tour booking size: {}", tourBookings.size());

        if (!tourBookings.isEmpty()) {
            for (TourBooking tourBooking : tourBookings) {
                log.debug("tour booking number: {}", tourBooking.getBookingNumber());
                signoutNoticeService.tourBookingNotSignouted(tourBooking);
            }
        }

        log.debug("CheckUnsignedBookingJob done");
    }

    public void setVisitBookingService(VisitBookingService visitBookingService) {
        this.visitBookingService = visitBookingService;
    }

    public void setTourBookingService(TourBookingService tourBookingService) {
        this.tourBookingService = tourBookingService;
    }

    public void setSignoutNoticeService(SignoutNoticeService signoutNoticeService) {
        this.signoutNoticeService = signoutNoticeService;
    }

}


这是webservice端的一个Job, 由spring定时触发,看配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	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" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
	default-lazy-init="true">

	<bean id="checkUnsignedBookingJobCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail">
			<bean
				class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
				<property name="targetObject">
					<bean class="com.XXX.tourbooking.job.CheckUnsignedBookingJob">
						<property name="visitBookingService" ref="visitBookingServiceImpl" />
						<property name="tourBookingService" ref="tourBookingServiceImpl" />
						<property name="signoutNoticeService" ref="signoutNoticeService" />
					</bean>
				</property>
				<property name="targetMethod">
					<value>execute</value>
				</property>
			</bean>
		</property>
		<property name="cronExpression">
			<value>0 0/30 * * * ?</value>
		</property>
	</bean>

	<!-- startQuertz -->

	<bean id="startQuertz" lazy-init="false" autowire="no"
		class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="triggers">
			<list>
				<ref bean="checkUnsignedBookingJobCronTrigger" />
			</list>
		</property>
	</bean>

</beans>



这个任务会定时触发刚那个Job的execute方法,在这个方法中,会调用webservice端的接口
SignoutNoticeService 中定义的方法,该接口的实现类在我们的主程序端,而不是webservice端。
@WebService
public interface SignoutNoticeService {

    void visitBookingNotSignouted(VisitBooking visitBooking);

    void tourBookingNotSignouted(TourBooking tourBooking);
}


看主程序端是如何实现webservice这个SignoutNoticeService 接口中的方法并实现推送的


@Service("signoutNoticeService")
@WebService(endpointInterface = "com.XXX.tourbooking.service.SignoutNoticeService")
public class SignoutNoticeServiceImpl implements SignoutNoticeService {
    private static final Logger log = LoggerFactory.getLogger(SignoutNoticeServiceImpl.class);

    public void visitBookingNotSignouted(final VisitBooking visitBooking) {
        log.info("signoutTimeoutVisitBookingPopup call..");
        log.info("SignoutNotice size: {}", SignoutNotice.signoutNoticeList.size());

        if (SignoutNotice.signoutNoticeList.size() > 0) {
            SignoutNotice notice = SignoutNotice.signoutNoticeList
                    .get(SignoutNotice.signoutNoticeList.size() - 1);
            log.info("SignoutNotice: {}", notice);
            if (notice != null) {
                notice.signoutTimeoutVisitBookingPopup(visitBooking.getId());
            }
        }
    }

    public void tourBookingNotSignouted(final TourBooking tourBooking) {
        log.info("signoutTimeoutTourBookingPopup call..");
        log.info("signoutNoticeList size: {}", SignoutNotice.signoutNoticeList.size());

        if (SignoutNotice.signoutNoticeList.size() > 0) {
            SignoutNotice notice = SignoutNotice.signoutNoticeList
                    .get(SignoutNotice.signoutNoticeList.size() - 1);
            log.info("SignoutNotice: {}", notice);
            if (notice != null) {
                notice.signoutTimeoutTourBookingPopup(tourBooking.getId());
            }
        }
    }

}

可以看到这个实现类的头部注解,这个地方是关键,webservice端的数据给到了主程序端,虽然我还不明白,哈哈(可能是个长连接)。。。

实现类的方法中,调用了主程序端定义的服务器推送类SignoutNotice,这个类实现了dwr的服务器推送所需要的操作。
public class SignoutNotice {
    private static final Logger log = Logger.getLogger(SignoutNotice.class);

    public static List<SignoutNotice> signoutNoticeList = new ArrayList<SignoutNotice>();

    private String[] pushRoleId = new String[] { "1", "2" };
    private Collection<ScriptSession> sessions = new ArrayList<ScriptSession>();

    public SignoutNotice() {
        log.info("new SignoutNotice...");
        signoutNoticeList.add(this);
    }

    public void signoutTimeoutVisitBookingPopup(String bookId) {
        log.info("signoutTimeoutVisitBookingPopup ajax call.....");
        Collection filterSessions = filterScriptSessionByRoleId(sessions);
        log.info("signoutTimeoutVisitBookingPopup sessions.size(): " + sessions.size()+" filterSessions.size():"+filterSessions.size());
        Util util = new Util(filterSessions);
        util.addFunctionCall("AlertSignoutNoticeVisitBooking", bookId);
    }

    public void signoutTimeoutTourBookingPopup(String bookId) {
        log.info("signoutTimeoutTourBookingPopup ajax call.....");
        Collection filterSessions = filterScriptSessionByRoleId(sessions);
        log.info("signoutTimeoutTourBookingPopup sessions.size(): " + sessions.size()+" filterSessions.size():"+filterSessions.size());
        Util util = new Util(filterSessions);
        util.addFunctionCall("AlertSignoutNoticeTourBooking", bookId);
    }

    public void init(String roleId) {
        log.info("init .....");
        WebContext wctx = WebContextFactory.get();
        ScriptSession scriptSession = wctx.getScriptSession();
        log.info("roleId: " + roleId);
        scriptSession.setAttribute("roleId", roleId);
        sessions.add(scriptSession);
    }

    public Collection filterScriptSessionByRoleId(Collection<ScriptSession> sessions) {
        Collection filterSessions = new ArrayList();
        for (ScriptSession scriptSession : sessions) {
            String roleId = (String) scriptSession.getAttribute("roleId");
            log.info("roleId:" + roleId);
            for (String id : pushRoleId) {
                if (id.equals(roleId)) {
                    filterSessions.add(scriptSession);
                    break;
                }
            }
        }
        return filterSessions;
    }
}


这个类需要在dwr.xml配置文件中进行配置,作为一个ajax类,dwr的ajax就不讲解了。
要实现dwr的reverseAjax,在上面这个类中已经用到了方法util.addFunctionCall("AlertSignoutNoticeTourBooking", bookId);其中AlertSignoutNoticeTourBooking就是在页面上定义的一个js方法,这个方法实现提醒服务,它是由服务器端调用的,就是说,服务器端调用客户端的方法。
在客户端,我们需要进行如下的初始化才能实现dwr的服务器推送功能:

 dwr.engine.setActiveReverseAjax(true);
  SignoutNotice.init(roleId); 


dwr.engine.setActiveReverseAjax(true); 这句是dwr实现服务器推送必不可少的设置。
以前我有写过一个简单的dwr推送demo,可以去参考。

至此,webservice结合dwr实现服务器推送已经完成的差不多了,在客户端只要有过期的日程,就会被提醒。
  相关解决方案