情景:
客户端需要实时提醒服务,比如某个日程已过期的提醒,并且是刚刚过期的时间(所以是实时),
1. 日程对象放在数据库,由webservice调用得到
2. webservice在拿到数据后必须主动把数据给我的主程序端
3. 主程序端在拿到数据后开始推送数据到客户端
代码:
这是webservice端的一个Job, 由spring定时触发,看配置:
这个任务会定时触发刚那个Job的execute方法,在这个方法中,会调用webservice端的接口
SignoutNoticeService 中定义的方法,该接口的实现类在我们的主程序端,而不是webservice端。
看主程序端是如何实现webservice这个SignoutNoticeService 接口中的方法并实现推送的
可以看到这个实现类的头部注解,这个地方是关键,webservice端的数据给到了主程序端,虽然我还不明白,哈哈(可能是个长连接)。。。
实现类的方法中,调用了主程序端定义的服务器推送类SignoutNotice,这个类实现了dwr的服务器推送所需要的操作。
这个类需要在dwr.xml配置文件中进行配置,作为一个ajax类,dwr的ajax就不讲解了。
要实现dwr的reverseAjax,在上面这个类中已经用到了方法util.addFunctionCall("AlertSignoutNoticeTourBooking", bookId);其中AlertSignoutNoticeTourBooking就是在页面上定义的一个js方法,这个方法实现提醒服务,它是由服务器端调用的,就是说,服务器端调用客户端的方法。
在客户端,我们需要进行如下的初始化才能实现dwr的服务器推送功能:
dwr.engine.setActiveReverseAjax(true); 这句是dwr实现服务器推送必不可少的设置。
以前我有写过一个简单的dwr推送demo,可以去参考。
至此,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实现服务器推送已经完成的差不多了,在客户端只要有过期的日程,就会被提醒。