2017-01-21 2 views
2

Теперь я немного изучаю Akka, но я не могу понять точного значения getSender(). В this official document, метод getSender() используется и объяснение, какЧто означает «getSender()» в Акке?

// Reply to original sender of message getSender().tell(msg + ":" + getSelf());

Это, как представляется, способ ответа, поэтому этот актер должен реагировать на актера, который отправил сообщение и этот метод является то, что делает его на самом деле. И я смущен, потому что не понимаю, дает ли getSender() актер приемника или актер отправителя. Итак, не могли бы вы рассказать мне об этом?

Спасибо.

public class WebSocketActor extends UntypedActor { 

/** 
* Actor's reference 
*/ 
private final static ActorRef ref = Akka.system().actorOf(new Props(WebSocketActor.class)); 

/** 
* the list of those who should get messages 
*/ 
Map<String, WebSocket.Out<JsonNode>> members = new HashMap<String, WebSocket.Out<JsonNode>>(); 

/** 
* a method adding a certain user 
* @param username a user name 
* @param in receive of WebSokcet 
* @param out sending of WebSocket 
* @throws Exception 
*/ 
public static void join(final String username, WebSocket.In<JsonNode> in, WebSocket.Out<JsonNode> out) throws Exception { 

    // causing JOIN event 
    Boolean result = (Boolean) Await.result(ask(ref, new Message(username, "", "", WebSocketEvent.JOIN, out), 1000), Duration.create(1, SECONDS)); 

    if(result) { 
     // if a message is sent,MESSAGE event will occur. 
     in.onMessage(new Callback<JsonNode>() { 
      public void invoke(JsonNode event) { 
       ref.tell(new Message(username, event.get("x").asText(), event.get("y").asText(), WebSocketEvent.MESSAGE, null), ref); 
      } 
     }); 
     // a close method when WebSocket is closed 
     in.onClose(new Callback0() { 
      public void invoke() { 
       ref.tell(new Message(username, "", "", WebSocketEvent.QUIT, null), ref); 
      } 
     }); 
    } else { 
     // sending an error 
     ObjectNode error = Json.newObject(); 
     error.put("error", result); 
     out.write(error); 
    } 
} 

/** 
* the executable method when an event happens 
* @param message an event object 
* @throws Exception 
*/ 
@Override 
public void onReceive(Object message) throws Exception { 

    // diciding whether the object is an event or not 
    Option<Message> event = EventUtil.getEvent(message); 
    if(event.isDefined()){ 
     Message m = event.get(); 
     switch (m.getEventType()) { 
      // adding to members 
      case JOIN: 
       members.put(m.getUsername(), m.getChannel()); 
       getSender().tell(true, ref); 
       break; 
      // sending all 
      case MESSAGE: 
       WebSocketMessenger.notifyAll(m.getUsername(), m.getX(), m.getY(), members); 
       break; 
      // excluding someone from members 
      case QUIT: 
       members.remove(m.getUsername()); 
       break; 
      default: 
       unhandled(message); 
       break; 
     } 
    } 

} 

}

В коде выше, в onReceive(Object message) методе вы можете увидеть метод getSender(). Однако, когда вызывается метод join(final String username, WebSocket.In<JsonNode> in, WebSocket.Out out), сначала актер запрашивает новое сообщение другого актера, а затем в методе onReceive(Object message), другой участник отвечает true, выполняя как getSender().tell(true, ref);. В этом обстоятельстве getSender() дает первый актер, который спросил. Разве это не странно, потому что первый актер, который попросил, дал true другому актеру, который должен дать true первому актеру? Ваш ответ был бы очень полезен, но я до сих пор не ясно, извините.

EDIT: Вы сказали, что это не работает, но оно работает. Вы знакомы с PlayFramework? Если это так, совершенно просто понять целое изображение. Этот код является кодом контроллера, который вызывает метод join().

public static WebSocket<JsonNode> ws() { 
    final String username = session("username"); 
    return new WebSocket<JsonNode>() { 
     @Override 
     public void onReady(final WebSocket.In<JsonNode> in, final WebSocket.Out<JsonNode> out) { 
      try { 
       WebSocketActor.join(username, in, out); 
      } catch (Exception e) { 
       Logger.error("Can't connect WebSocket"); 
       e.printStackTrace(); 
      } 
     } 
    }; 
} 

ответ

2

Он просто возвращает ссылку на актера (ActorRef) , что только что отправил сообщение, которое вы в настоящее время обработки.

Таким образом, это способ для актера: ответить сообщение ... в коде его обработки.

Другими словами, если актеру отправить сообщение M1 к актеру B, когда B вызывает getSender, он возвращает ссылку на актера А.

редактировать после кода при условии:

Ниже не будет работать должным образом:

Boolean result = (Boolean) Await.result(ask(ref, new Message(username, "", "", WebSocketEvent.JOIN, out), 1000), Duration.create(1, SECONDS)); 

вы не можете спросить() и ожидать ответа от актера, если вы не себя актером. Метод join() является статическим и полностью выполняется вне актерской системы! он мог (и должен) находиться в другом классе.

Вот почему getSender() здесь не имеет смысла: нет отправителя «akka».

+0

Я понимаю возвращаемое значение метода 'getSender()'. Тем не менее, я до сих пор не путаюсь с некоторыми пунктами, пожалуйста, см. Мой дополнительный вопрос, если это возможно. –

+0

Хорошо, вы сбиты с толку, потому что ваш класс смешивает две проблемы: * обработка событий в websocket * с * обработкой сообщений актера *. Кроме того, метод ask() в методе соединения не будет работать, потому что ask() не вызывается аккой akka, а статическим методом! поэтому getSender() не возвращает ссылку на актер, поскольку источник сообщения не является актером. Вы видите, что я имею в виду? –

+0

Существует огромное количество информации, позвольте мне видеть ... Во-первых, что вы подразумеваете под обработкой событий _websocket с обработкой сообщений actor? Можете быть более конкретными? Во-вторых, я могу понять, что вы скажете, может быть, это нехорошо, не следуя теории Акки. И на самом деле, что я должен интерпретировать этот код? Есть ли у вас какие-либо идеи? –

Смежные вопросы