Java WebSocket

Paylaş

Java programlama dilinde yer alan WebSocket nedir ile başlayarak WebSocket projesi oluşturma ve kullanımı ile ilgili bilgiler yer alıyor.

WebSocket nedir?

WebSocket hakkında detaylı bilgi almak için WebSocket yazıma bakmalısın.

Java WebSocket

Java ile WebSocket sunucusu ve Java tabanlı istemci oluşturmak için JCP tarafından belirlenen JSR 356 şartnamesi kullanılır.

WebSocket HTTP üzerine inşaa edildiğinden dolayı Servlet Container (Tomcat, Jetty vb.) ve Application Server (GlassFish, Payara vb.) tarafından desteklenmektedir.

WebSocket tanımları Java EE javax.websocket, Jakarta EE jakarta.websocket paketinde yer alır.

WebSocket projesi oluşturma

Maven projesi oluşturarak pom.xml dosyasına kullanılacak kütüphanenin eklenmesi yeterlidir.

Hızlıca maven projesi oluşturmak için archetype:generate kullanabiliriz.

mvn archetype:generate 
-DgroupId=com.yusufsezer 
-DartifactId=JavaWebSocket 
-DarchetypeArtifactId=maven-archetype-webapp 
-DinteractiveMode=false 

Projeyi oluşturduktan sonra pom.xml dosyasına aşağıdaki kütüphaneyi ekleyelim.

Java EE için;

<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>

Jakarta EE için;

<dependency>
    <groupId>jakarta.websocket</groupId>
    <artifactId>jakarta.websocket-api</artifactId>
    <version>2.1.1</version>
    <scope>provided</scope>
</dependency>

NOT: Güncel sürüm için maven depolarına bakmak faydalı olacaktır.

Java WebSocket sunucu veya istemci oluşturma işleminde programsal ve annotations kullanımını destekler.

Annotations hakkında detaylı bilgi almak için Java Annotations yazıma bakmalısın.

Programsal olarak WebSocket sunucusu oluşturma

Programsal olarak WebSocket sunucusu oluşturmak için Endpoint sınıfının kalıtım alınması ve onOpen metodunun override-ezilmesi edilmesi gerekir.

public class EchoEndpoint extends Endpoint {

    @Override
    public void onOpen(Session session, EndpointConfig config) {
        session.addMessageHandler(new MessageHandler.Whole<String>() {
            @Override
            public void onMessage(String message) {
                try {
                    session.getBasicRemote().sendText(message);
                } catch (IOException ex) {
                    System.err.println(ex);
                }
            }
        });
    }
}

Soyut onOpen metot imzasında yer alan Session sınıfı kullanarak herhangi bir mesaj geldiğinde yine session sınıfında yer alan getBasicRemote ile istemciye mesaj atılmıştır

WebSocket sınıfı hazırlandıktan sonra sınıfın WebSocket adresine bağlanması için ServerApplicationConfig arayüzünü uygulayan-implement eden sınıf oluşturulur.

public class EchoWebSocketConfig implements ServerApplicationConfig {

    @Override
    public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses) {

        Set<ServerEndpointConfig> configs = new HashSet<>();
        ServerEndpointConfig sec = ServerEndpointConfig.Builder
                .create(EchoEndpoint.class, "/echo")
                .build();
        configs.add(sec);

        return configs;
    }

    @Override
    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
        return scanned;
    }
}

Servlet Container veya Application Server getEndpointConfigs ve getAnnotatedEndpointClasses metotlarını çalıştırarak WebSocket ayarlarını yapar.

Arayüz uygulanarak-implement edilerek kullanılabileceği gibi arayüz içerisinde yer alan Builder sınıfı kullanılabilir.

NOT: Annotations kullanımı programsal kullanıma göre daha kolay olduğundan annotations kullanımı tercih edilmektedir.

NOT2: Hem annotations kullanımı hem de programsal kullanım istendiğinde annotations kullanımını da programsal olarak yönetmek gerekebilir.

Annotations kullanarak WebSocket sunucusu oluşturma

Annotations kullanımı sınıf başına @ServerEndpoint ve gelen mesajların yönetileceği metot başına @OnMessage ifadesini eklemek yeterli olacaktır.

@ServerEndpoint(value = "/echo")
public class EchoEndpoint {

    @OnMessage
    public String onMessage(Session session, String message) {
        return message;
    }

}

WebSocket adresi ve diğer ayarlar @ServerEndpoint içerisine yazılır ve arka planda yapılır.

Annotations kullanımda WebSocket durumlarını yönetmek için @OnOpen, @OnMessage, @OnError ve @OnClose annotationları yer alır.

@ServerEndpoint(value = "/echo")
public class EchoEndpoint {

    @OnOpen
    public void open(Session session, EndpointConfig config) {
        System.out.println("Yeni giriş: " + session.getId());
    }

    @OnMessage
    public void message(Session session, String message) {
        System.out.println("Yeni mesaj: " + message);
    }

    @OnError
    public void error(Session session, Throwable error) {
        System.err.println(session.getId());
        System.err.println(error);
    }

    @OnClose
    public void close(Session session, CloseReason closeReason) {
        System.out.println(session.getId());
        System.out.println(closeReason.getCloseCode().getCode());
        System.out.println(closeReason.getReasonPhrase());
    }

}

İstemcilere düz metin (String) yerine byte veya özel veri gönderebilir.

Diğer veri türlerini almak ve yönetmek için farklı metot imzaları ile @OnMessage ifadesi tekrar kullanılabilir.

@ServerEndpoint(value = "/echo")
public class EchoEndpoint {

    @OnMessage
    public void textMessage(Session session, String message) {
        System.out.println("Text message: " + message);
    }

    @OnMessage
    public void binaryMessage(Session session, ByteBuffer message) {
        System.out.println("Binary message: " + message.toString());
    }

    @OnMessage
    public void pongMessage(Session session, PongMessage message) {
        System.out.println("Pong message: " + message.getApplicationData().toString());
    }

}

Session

Java WebSocket istemcileri Session arüyüzü ile ifade eder.

Arayüzün bir örneği metotlara parametre olarak geçirilir.

Arayüz içerisindeki bazı metotlar ve açıklamaları aşağıdadır.

close – İstemci WebSocket bağlantısını kapatmak için kullanılır.

addMessageHandler – Programsal kullanımda mesajları yönetmek için kullanılır.

isOpen – İstemci bağlantı durumunu almak için kullanılır.

getId – İstemciye ait benzersiz numarayı almak için kullanılır.

getOpenSessions – Tüm istemcileri almak için kullanılır.

getBasicRemote – getAsyncRemote – RemoteEndpoint arayüzünü uygulayan sınıf döndürerek istemciye veri gönderimi için kullanılır.

getUserProperties – İstemciye ait veri saklamak için kullanılır.

Aşağıdaki örnek kullanımda bir istemciden gelen veri tüm istemcilere gönderilmiştir.

@ServerEndpoint(value = "/echo")
public class EchoEndpoint {

    @OnMessage
    public void message(Session session, String message) {
        session
                .getOpenSessions()
                .stream()
                .filter(p -> p.isOpen() == true)
                .forEachOrdered((s) -> {
                    try {
                        s.getBasicRemote().sendText(message);
                    } catch (IOException ex) {
                        System.err.println(ex);
                    }
                });
    }

}

ServerEndpoint

WebSocket ayarları için kullanılır.

value – WebSocket adresini alır.

URI template ile @ServerEndpoint(“/room/{roomName}”) gibi kullanıma sahiptir.

URI template ile kullanımda adresi elde etmek için @PathParam kullanılır.

@OnMessage
public void onMessage(Session session, 
        String message, 
        @PathParam("roomName") String roomName) {
    // ...
}

subprotocols – Desteklenen alt protokollerin listesini belirlemek için kullanılır.

decoders – Gelen mesajı işleyecek sınıfları belirlemek için kullanılır.

encoders – Giden mesajı işleyecek sınıfları belirlemek için kullanılır.

configurator – WebSocket ayarlarının yapıldığı sınıfı belirlemek için kullanılır.

Decoders – Encoders

WebSocket String veri türü yanında byte ve özel veri türü iletişimini destekler.

Sunucudan veya istemciden gelen-giden farklı veri türlerinin işlenebilmesi için Java programlama diline çevrilmesi gerekebilir.

Bu durum için Decoders-Encoders yapısı kullanılır.

Örneğin; Aşağıdaki Java sınıfı istemciye gönderelim.

public class Person {

    long id;
    String firstName;
    String lastName;

    // constructor-get-set

}

Java nesnelerini istemciye göndermek için RemoteEndpoint arayüzüne ait sendObject metodu kullanılır.

@ServerEndpoint(
        value = "/echo",
        encoders = PersonEncoder.class
)
public class EchoEndpoint {

    @OnMessage
    public void message(Session session, String message) {
        session
                .getOpenSessions()
                .stream()
                .filter(p -> p.isOpen() == true)
                .forEachOrdered((s) -> {
                    try {
                        Person yusuf = new Person(1, "Yusuf", "SEZER");
                        s.getBasicRemote().sendObject(yusuf);
                    } catch (IOException | EncodeException ex) {
                        System.err.println(ex);
                    }
                });
    }
}

Sınıf istemciye gönderildiğinde @ServerEndpoint ifadesindeki encoders ile belirtilen sınıf kullanılarak istemciye gönderilecektir.

Encoder tanımlamak için Encoder.Binary, Encoder.BinaryStream, Encoder.Text ve Encoder.TextStream arayüzleri kullanılır.

İstemciye gönderilecek veri türüne göre arayüz implement edilir.

public class PersonEncoder implements Encoder.Text<Person> {

    @Override
    public void init(EndpointConfig config) {}

    @Override
    public void destroy() {}

    @Override
    public String encode(Person person) throws EncodeException {
        return person.getId()
                + " - "
                + person.getFirstName()
                + " - "
                + person.getLastName();
    }

}

WebSocket sunucusundan istemciye Person sınıfından bir nesne gönderildiğinde PersonEncoder sınıfı içerisinde yer alan encode metodunun sonucu istemciye gönderilir.

WebSocket istemcisi oluşturma

Java ile oluşturulan WebSocket sunucusunu tarayıcı üzerinden kullanmak için ayrıca kütüphanenin kullanımına ihtiyaç yoktur.

HTML5 WebSocket yazımda yer alan kodlar kullanılabilir.

WebSocket sunucusu için Java tabanlı istemci oluşturmak için WebSocket implementasyonu olan Tyrus kullanılabilir.

Java WebSocket geliştirmek için oldukça sade bir yapı sunar.

Böylece isteğe özel WebSocket sunucusu ve istemcisi mimarisi oluşturmaya imkan verir.

Java WebSocket örneğine buradan ulaşabilirsiniz.

Java Derslerine buradan ulaşabilirsiniz.

Hayırlı günler dilerim.


Bunlarda ilgini çekebilir


LinkedIn grubuna buradan katılın.