Java EWS Java API 的基本使用

alston · 2020-04-22 10:24:29 · 热度: 750

需求功能

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

  • 从 MMS 预定会议时,需要将会议信息推送到Exchange服务器中。
  • 从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() {
        @Override
        public 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 绑定,即无法获取改动的会议信息。

猜你喜欢:
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册