2018/12/20 更新:

这篇文章的同步方式存在缺陷,在仔细研究Exchange后有不少新的收获,找到了更好的解决方案,请移步这里观看~

Exchange 会议同步入门指南


需求功能

最近公司接到一个需求,将客户的 Exchange 服务器中的会议信息,同步到公司现有的会议管理系统中(MMS),为了实现这个需求,需要做以下几件事:

  1. 从 MMS 预定会议时,需要将会议信息推送到Exchange服务器中。
  2. 从Exchange预定会议时,在MMS系统中需要有一个监听机制(EWS 中称“通知”/Notifications),实时监测会议信息的变化,并将变化后的数据同步到MMS系统。

准备工作

获取 EWS Java API ,请移步:https://github.com/OfficeDev/ews-java-api

简单实现

1.获得 EWS 服务

传入参数为 Exchange 服务器的版本号,根据实际情况选择。

//在 Notifications 中,ExchangeVersion.Exchange2010 版本不支持流式通知,需要不断的执行 GetEvents 方法达到实时监听。
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
//Exchange服务器的域名,使用ip可能会连接失败,如服务器在本地,没有域名可以在host文件中添加一条域名解析规则
String serverHost = "exchange.server.host"
//登录的账号和密码,账号一定是可以登录进去的账号,不一定是邮箱地址
ExchangeCredentials credentials = new WebCredentials("emailAddress", "password");
service.setCredentials(credentials);
//固定写法
service.setUrl(new URI("https://" + serverHost + "/ews/exchange.asmx"));
service.setCredentials(credentials);
service.setTraceEnabled(true);

2. 查询 Exchange 的会议信息

查找距现在24小时以内开始的所有会议邮件(Appoinement)

Date start = new Date();
Date end = new Date(start.getTime() + 1000*3600*24);CalendarView cView = new CalendarView(start, end);
//指定要查看的邮箱
FolderId folderId = new FolderId(WellKnownFolderName.Calendar, new Mailbox(emailAddress));
FindItemsResults<Appointment> findResults = null;
try {findResults = service.findAppointments(folderId, cView);
} catch (Exception e) {e.printStackTrace();
}
ArrayList<Appointment> appointmentItems = findResults==null?null:findResults.getItems();

遍历结果,获取会议信息

for(Appointment ap:allAppointment){ap.load();String subject = ap.getSubject();//如邮箱主题以“已取消”开头,说明该会议已经被取消if(subject.startsWith("已取消")){continue;}//得到HTML格式的内容,通过工具类提取body标签的内容String html_body = ap.getBody().toString();String body = DataUtils.getContentFromHtml(huml_body);//会议的开始和结束时间Date start = ap.getStart();Date end = ap.getEnd();//会议使用的资源List<Attendee> resources = ap.getResources().getItems();//参加会议的员工List<Attendee> RequiredAttendees = ap.getRequiredAttendees().getItems();List<Attendee> OptionalAttendees = ap.getOptionalAttendees().getItems();}

从HTML提取body信息的工具类

public class DataUtils {public static String getContentFromHtml(String content){content = content.replaceAll("</?[^>]+>", ""); //剔出<html>的标签content = content.replaceAll("<a>\\s*|\t|\r|\n</a>", "");content = content.replaceAll("&nbsp;", "");content = content.replaceAll("\n", "");return content;}
}

3. 向 Exchange 发送一条会议邮件

Appointment appointment = null;
try {appointment = new Appointment(service);appointment.setSubject("会议主题");appointment.setBody(MessageBody.getMessageBodyFromText("会议消息体"));appointment.setStart(new Date());appointment.setEnd(new Date().getTime()+1000*3600*24);appointment.setLocation("会议位置");appointment.getResources().add("会议资源账号,如:meetingroom@company.com");appointment.getRequiredAttendees().add("必须参加的员工的账号");appointment.getOptionalAttendees().add("可选参加的员工的账号");appointment.save();appointment.update(ConflictResolutionMode.AutoResolve);
} catch (Exception e) {e.printStackTrace();
}

4. 建立监听,接收会议变化事件的通知

try {//将需要监听的事件作为参数传入构造方法IAsyncResult asyncresult = service.beginSubscribeToPullNotificationsOnAllFolders(null, null, 5, null, EventType.NewMail, EventType.Created, EventType.Deleted);PullSubscription subscription = service.endSubscribeToPullNotifications(asyncresult);//由于博主Exchange服务器版本限制,只能通过定时调用GetEvent方法达到实时监听TimerTask task = new TimerTask() {@Overridepublic void run() {try {GetEventsResults events = subscription.getEvents();Iterable<ItemEvent> itemEvents = events.getItemEvents();for(ItemEvent itemEvent:itemEvents){if(itemEvent.getEventType() == EventType.Created){Item item = null;try{item = Item.bind(service,itemEvent.getItemId());}catch (ServiceResponseException e){//找不到该邮件continue;}if(item instanceof Appointment){Appointment appointment = Appointment.bind(service, item.getId());//得到发生变化的会议,执行业务逻辑}}}} catch (Exception e) {e.printStackTrace();}}};new Timer().scheduleAtFixedRate(task, delay, 1 * 10 * 1000);} catch (URISyntaxException e) {e.printStackTrace();
} catch (Exception e) {e.printStackTrace();
}

遗留问题

  • 监听效果不够优雅,使用这种异步订阅方式,在Exchange服务器中创建一个会议,会被触发两次。并且,修改会议或者取消会议,都会被 EventType.Created 响应一次
  • 如果使用同步订阅方式,得到的 itemID 不能和 Appoinement 绑定,即无法获取改动的会议信息

参考资料:

https://github.com/OfficeDev/ews-java-api/wiki/Getting-Started-Guide#using-pull-notifications-with-the-ews-java-api

https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/notification-subscriptions-mailbox-events-and-ews-in-exchange

EWS Java API 的基本使用相关推荐

  1. java ews_如何验证EWS Java API

    我们使用EWS Java API在 Java应用程序上使用outlook日历.我在EWS上遇到了身份验证问题. 我尝试使用由rackspace提供的云Outlook帐户上的应用程序,一切正常,所以我知 ...

  2. ews java api maven_通过 EWS JAVA API读取exchange邮件

    为什么80%的码农都做不了架构师?>>> 第一步,下载EWS JAVA API包 从如下路径下载EWS API包:http://code.msdn.microsoft.com/Exc ...

  3. ews java 新建邮箱_通过EWS JAVA API订阅邮箱更新

    0. EWS JAVA API是什么? 用来访问 Exchange Web 服务的 Java 客户端,说白了就是一套访问Exchange邮件服务的Java API库,利用它我们可以编写Java代码来动 ...

  4. Java 通过EWS JAVA API发送exchange邮件

    一.依赖的包 commons-codec-1.11.jar commons-lang3-3.9.jar commons-logging-1.2.jar ews-java-api-2.0.jar htt ...

  5. 2021年大数据Kafka(五):❤️Kafka的java API编写❤️

    全网最详细的大数据Kafka文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 Kafka的java API编写 一.生产者代码 第一步: ...

  6. 2021年大数据ZooKeeper(五):ZooKeeper Java API操作

    目录 ZooKeeper Java API操作 引入maven坐标 节点的操作 ZooKeeper Java API操作 这里操作Zookeeper的JavaAPI使用的是一套zookeeper客户端 ...

  7. 随机森林 java_机器学习weka,java api调用随机森林及保存模型

    工作需要,了解了一下weka的java api,主要是随机森林这一块,刚开始学习,记录下. 了解不多,直接上demo,里面有一些注释说明: package weka; import java.io.F ...

  8. 【ZooKeeper Notes 3】ZooKeeper Java API 使用样例

    查看PDF版本 转载请注明:@ni掌柜 nileader@gmail.com ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务框架,包含一组简单的原语集合.通过这些原语言的组合使用, ...

  9. Kafka系列三 java API操作

    使用java API操作kafka 1.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xs ...

最新文章

  1. 说说进程与线程的区别与联系
  2. netty3超长字符串
  3. css元素居中方法归纳
  4. C语言九十七之实现有 1、2、3、4 个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?并且输出多少个
  5. Oracle 时区(TimeZone )-- DST
  6. Linux系统日志及日志分析
  7. Javascript实现重力弹跳拖拽运动效果
  8. C#类型的强制转换及隐式转换
  9. cad怎么快速算面积_微信收到CAD图纸打不开怎么办?2种方法教你手机CAD快速看图...
  10. 【语义分割】数据增强方法(原图与标签同时扩增)
  11. java spliterator_java 8 stream中的Spliterator简介
  12. mysql新手常见问题_MySQL数据库入门-新手常见问题答疑
  13. 最全面的PS快捷键使用指南
  14. 一起话单业务量下降问题的排查过程
  15. Error-Input tensor has type kTfLiteFloat32: it requires specifying NormalizationOptions metadata to
  16. keil4软件的下载与安装
  17. 亦是美网络,致力于操作系统应用与计算机网络技术的IT网站。
  18. 今日头条技术架构分析
  19. 虚拟交换系统 (VSS)
  20. 日语学习网站分类汇总

热门文章

  1. 【问链-区块链基础知识系列】 第十课 首席架构师谈区块链技术演进
  2. Linux ARM平台开发系列讲解(摄像头V4L2子系统) 2.12.5 V4L2 control的原理和实现
  3. JupyterLab教程:程序员的笔记本神器v2.0
  4. WSA系列API函数
  5. SAP WRITE设置列表颜色 页眉页尾输出控制
  6. 你居然不会狄杰斯特算法?惊了!
  7. Client MFC application解决办法
  8. 基于SSM生产计划排程管理系统
  9. 《千与千寻》与《天空之城》配色分享
  10. win7系统如何映射服务器,win7系统映射网络驱动器怎么访问