Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 달팽이
- 스프링 시큐리티
- spring boot
- BFS
- 유레카
- 다익스트라
- 주울
- 메모이제이션
- 플로이드 와샬
- 완전 탐색
- Spring Cloud Config
- Gradle
- 비트마스킹
- Logback
- 스택
- 서비스 디스커버리
- spring cloud
- 백트래킹
- Java
- dp
- 이분 매칭
- 트리
- 게이트웨이
- 도커
- docker-compose
- Zuul
- 구현
- ZuulFilter
- 구간 트리
- 이분 탐색
Archives
- Today
- Total
Hello, Freakin world!
[채팅앱][클라이언트] EventHandler 코드 작성하기 본문
메서드 설명
- getHandlerMap()
이 메서드는 클래스 내에 존재하는 @Event 애너테이션이 달린 메서드들을 자신의 메서드명(event명)으로 매핑한 맵을 반환한다. (내가 임의로 메서드명과 이벤트명이 같아지도록 구현함)
그 과정에서 Stream api와 Reflection api를 사용했다.
- delegate()
handler 맵을 순회하면서 전달받은 key에 포함된 eventName 값을 이용해 이와 일치하는 Method를 찾는다.
그리고 찾은 method를 호출한다.
또 다른 중요 키포인트
이 클래스는 외부에 delegate() 만을 노출한다.
직접적으로 핸들러가 호출되는 일은 없다.
이는 클래스 사용자가 어떤 api를 쓸지 고민할 필요가 없게 만든다.
후~ 뼈대 작업이 끝났다. 이제 테스트를 추가하면서 필요한 핸들러들을 추가하면 된다!!!
public class EventHandler {
private Map<String, Method> handlerMap;
private Selector selector;
public void setSelector(Selector selector) {
this.selector = selector;
}
public EventHandler() {
handlerMap = getHandlerMap();
}
private Map<String, Method> getHandlerMap() {
Method[] methods = this.getClass().getDeclaredMethods();
for (Method m : methods) { m.setAccessible(true); }
return Arrays.stream(methods)
.filter(method -> method.isAnnotationPresent(Event.class))
.collect(Collectors.toMap(
method -> method.getName().toLowerCase(),
method -> method));
}
/*
map 을 이용해서 key 에 맞는 핸들러 매핑. key 에는 eventName:String 값이 등록되어있다.
*/
public void delegate(SelectionKey key) {
// 이 부분은 JSON 으로 바꿔야한다. write 의 경우 eventName 이외에 message 도 보내야한다.
String attachedEventName = (String) key.attachment();
String lowerCaseEventName = attachedEventName.toLowerCase();
Method method = handlerMap.keySet().stream()
.filter(eventNameKey -> eventNameKey.equals(lowerCaseEventName))
.map(eventNameKey -> handlerMap.get(eventNameKey))
.findFirst().orElseThrow(() -> new RuntimeException("조건에 맞는 핸들러를 찾을 수 없습니다."));
invoke(method, key);
}
private void invoke(Method method, SelectionKey key){
try {
method.invoke(this, key);
} catch (Exception e) { // <- 수정 필요함. 편의를 위해 최상위 예외로 캐치
e.printStackTrace();
throw new RuntimeException("핸들러 invoke 오류");
}
}
@Event(eventName = "connect")
private void connect(SelectionKey key) {
SocketAddress serverAddress = new InetSocketAddress("localhost", 9000);
boolean isConnected = NioOperations.connect(key,serverAddress); //채널 간의 연결 구현
// 부수 작업들
}
}
'Toy Project > 채팅 앱 만들기' 카테고리의 다른 글
[채팅앱][클라이언트] 논블락킹 ConnectionLoop 기능 구현 및 고찰 (0) | 2020.03.11 |
---|---|
[채팅앱] 클라이언트 서버 통신 - 첫번째 목표 설정 (0) | 2020.03.02 |
[채팅앱][클라이언트] EventHandler 클래스 및 아키텍처 수정 (0) | 2020.02.28 |
[채팅앱][클라이언트] EventHandler 클래스 설계 (0) | 2020.02.27 |
[채팅앱][클라이언트] EventLoop 클래스 작성하기 - 반드시 단위 테스트 작성해야만 하는가에 대해서 (0) | 2020.02.27 |
Comments