WebSocket API

All lectures for UZ purposes
Daraja, Dars
Mavjud

Spring Framework WebSocket protokoli uchun API taqdim etadi, bu WebSocket xabarlarini boshqaruvchi mijoz va server dasturlarini yozish uchun foydalaniladi.

WebSocketHandler

WebSocket serverini yaratish juda ham oson, faqat WebSocketHandlerni amalga oshirish yoki ko'proq ehtimol bo'lgan TextWebSocketHandler yoki BinaryWebSocketHandlerni kengaytirish kerak. Quyidagi misol TextWebSocketHandlerdan foydalanadi:

import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
public class MyHandler extends TextWebSocketHandler {
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        // ...
    }
}

Oldingi WebSocket handlerini belgilangan URL manziliga yo'naltirish uchun maxsus Java-konfiguratsiyasi va XML namespace qo'llab-quvvatlovi mavjud, quyidagi misolda ko'rsatilganidek:

import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler");
    }
    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }
}

Quyidagi misol oldingi misoldagi konfiguratsiyaning XML ekvivalentini ko'rsatadi:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/websocket
        https://www.springframework.org/schema/websocket/spring-websocket.xsd">
    <websocket:handlers>
        <websocket:mapping path="/myHandler" handler="myHandler"/>
    </websocket:handlers>
    <bean id="myHandler" class="org.springframework.samples.MyHandler"/>
</beans>

Oldingi misol Spring MVC ilovalarida foydalanish uchun mo'ljallangan va DispatcherServlet konfiguratsiyasiga qo'shilishi kerak. Biroq, Spring'dagi WebSocket qo'llab-quvvatlovi Spring MVC'ga qaram emas. WebSocketHandlerni WebSocketHttpRequestHandler yordamida HTTP bilan ishlaydigan boshqa muhitlarga integratsiya qilish oson.

WebSocketHandler API'ni to'g'ridan-to'g'ri yoki bilvosita, masalan, STOMP orqali xabar almashinuvini qo'llashda, ilova xabarlarni yuborishni sinxronlashtirishi kerak, chunki asosiy standart WebSocket sessiyasi (JSR-356) bir vaqtning o'zida yuborishni qo'llamaydi. Bir variant WebSocketSession'ni ConcurrentWebSocketSessionDecorator yordamida qamrab olishdir.

WebSocket aloqasini o'rnatish tasdiqlari

WebSocket uchun aloqani o'rnatishni tasdiqlovchi dastlabki HTTP so'rovini sozlashning eng oddiy usuli HandshakeInterceptor hisoblanadi, bu aloqani o'rnatishni tasdiqlashdan "oldin" va "keyin" usullarni ochadi. WebSocketSession uchun atributlarga kirish yoki aloqani o'rnatishni tasdiqlashni cheklash uchun bunday interceptionni ishlatish mumkin. Quyidagi misolda HTTP sessiyasi atributlarini WebSocket sessiyasiga o'tkazish uchun ichki interception ishlatiladi:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new MyHandler(), "/myHandler")
            .addInterceptors(new HttpSessionHandshakeInterceptor());
    }
}

Quyidagi misol oldingi misoldagi konfiguratsiyaning XML ekvivalentini ko'rsatadi:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/websocket
        https://www.springframework.org/schema/websocket/spring-websocket.xsd">
    <websocket:handlers>
        <websocket:mapping path="/myHandler" handler="myHandler"/>
        <websocket:handshake-interceptors>
            <bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
        </websocket:handshake-interceptors>
    </websocket:handlers>
    <bean id="myHandler" class="org.springframework.samples.MyHandler"/>
</beans>

Ko'proq rivojlangan variant DefaultHandshakeHandler'ni kengaytirishdir, bu WebSocket uchun aloqani o'rnatish tasdiqlari, jumladan, mijoz manbasini tekshirish, subprotokol kelishuvi va boshqalarni amalga oshiradi. Ilova ham moslashtirilgan RequestUpgradeStrategyni moslashtirish uchun ushbu variantni ishlatishi mumkin bo'ladi, agar u hali qo'llab-quvvatlanmaydigan WebSocket server dvigateli va versiyasiga moslashtirilishi kerak bo'lsa. Java-konfiguratsiyalari va XML namespace moslashtirilgan HandshakeHandlerni sozlashga imkon beradi.

Spring WebSocketHandlerni qo'shimcha ish logikasi bilan bezash uchun foydalanilishi mumkin bo'lgan asosiy WebSocketHandlerDecorator sinfini taqdim etadi. Jurnalizatsiya va xatoliklarni qayta ishlash amalga oshirilgan va WebSocket'ni Java konfiguratsiyasi yoki XML namespace'dan foydalanganda avtomatik qo'shiladi. ExceptionWebSocketHandlerDecorator WebSocketHandler metodlaridan kelib chiqadigan barcha ushlanmagan xatolarni ushlaydi va WebSocket sessiyasini 1011 server xatosi statusi bilan yopadi.

Deploy qilish

Agar DispatcherServlet HTTP orqali WebSocket aloqasini o'rnatishni tasdiqlashni va boshqa HTTP so'rovlarini boshqaradigan bo'lsa, Spring WebSocket API'ni Spring MVC ilovasiga osonlik bilan integratsiya qilish mumkin. HTTP so'rovlarini WebSocketHttpRequestHandler bilan qo'ng'iroq qilish orqali boshqa HTTP ishlov berish ssenariylariga integratsiya qilish ham oson. Bu qulay va tushunarli.

JSR-356'dagi WebSocket API Java'da ikki xil deploy qilish mexanizmlarini taqdim etadi. Birinchisi servlet konteynerining classpathini ishga tushirishda skanerlashni o'z ichiga oladi (Servlet 3 xususiyati). Boshqa biri servlet konteynerini ishga tushirishda foydalanish uchun ro'yxatga olish API'dan iborat. Bu mexanizmlardan hech biri barcha HTTP ishlov berish protseduralari uchun yagona "frontend controller" ishlatishga imkon bermaydi - masalan, Spring MVC'dagi DispatcherServlet.

Bu JSR-356'ning ahamiyatli cheklovidir, bu muammolarni Spring'dagi WebSocket'ning qo'llab-quvvatlovchi vositalari JSR-356 ish muhitida ishlashda ham serverga xos RequestUpgradeStrategy realizatsiyalari bilan hal qiladi. Hozirgi vaqtda bunday strategiyalar Tomcat, Jetty, GlassFish, WebLogic, WebSphere va Undertow (va WildFly) uchun mavjud.

Java'dagi oldingi WebSocket API cheklovini bartaraf etish uchun so'rov yaratilgan, uni eclipse-ee4j/websocket-api#211 manzilida topishingiz mumkin. Tomcat, Undertow va WebSphere o'z alternativ API'larini taqdim etadi, bu orqali Jetty bilan amalga oshirish mumkin. Umid qilamizki, boshqa serverlar uchun ham xuddi shunday amalga oshiriladi.

Ikkinchi darajali masala shundaki, JSR-356'ni qo'llab-quvvatlaydigan servlet konteynerlari ServletContainerInitializer (SCI) skanerlashni bajarishi kerak, bu ilova ishga tushirishni sekinlashtirishi mumkin - ba'zi hollarda sezilarli darajada. Agar JSR-356'ni qo'llab-quvvatlaydigan servlet konteyner versiyasiga yangilanishdan so'ng sezilarli sekinlashishni kuzatsangiz, <absolute-ordering /> elementini web.xmlda yozish orqali veb-fragmentlarni (va SCI skanerlashni) tanlab faollashtirish yoki deaktivlashtirish mumkin bo'lishi kerak, quyidagi misolda ko'rsatilganidek:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/javaee
        https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <absolute-ordering/>
</web-app>

Keyin, Spring'dan o'z SpringServletContainerInitializerni, bu Servlet 3'da Java'dagi API'ning boshlanishi qo'llab-quvvatlaydigan veb-fragmentlarni tanlab faollashtirish mumkin. Quyidagi misol buni qanday amalga oshirishni ko'rsatadi:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://java.sun.com/xml/ns/javaee
        https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <absolute-ordering>
        <name>spring_web</name>
    </absolute-ordering>
</web-app>

Server konfiguratsiyasi

Har bir asosiy WebSocket protokoli mexanizmi ishlash vaqtining xususiyatlarini nazorat qiluvchi konfiguratsiya xususiyatlarini ochib beradi, masalan, xabar buferi hajmi, befarq vaqt kutilishi va boshqalar.

Tomcat, WildFly va GlassFish uchun, quyidagi misolda ko'rsatilganidek, Java-konfiguratsiyalarida ServletServerContainerFactoryBeanni qo'shishingiz mumkin:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        container.setMaxTextMessageBufferSize(8192);
        container.setMaxBinaryMessageBufferSize(8192);
        return container;
    }
}

Quyidagi misol oldingi misoldagi konfiguratsiyaning XML ekvivalentini ko'rsatadi:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/websocket
        https://www.springframework.org/schema/websocket/spring-websocket.xsd">
    <bean class="org.springframework...ServletServerContainerFactoryBean">
        <property name="maxTextMessageBufferSize" value="8192"/>
        <property name="maxBinaryMessageBufferSize" value="8192"/>
    </bean>
</beans>
Mijoz tomoni uchun WebSocket konfiguratsiyasi WebSocketContainerFactoryBean (XML) yoki ContainerProvider.getWebSocketContainer() (Java-konfiguratsiya) yordamida amalga oshirilishi kerak.

Jetty holatida Jetty uchun oldindan sozlangan WebSocketServerFactoryni taqdim etishingiz va uni Spring'dagi DefaultHandshakeHandler'ga Java-konfiguratsiyasi orqali ulashingiz kerak. Quyidagi misol buni qanday amalga oshirishni ko'rsatadi:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(echoWebSocketHandler(),
            "/echo").setHandshakeHandler(handshakeHandler());
    }
    @Bean
    public DefaultHandshakeHandler handshakeHandler() {
        WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
        policy.setInputBufferSize(8192);
        policy.setIdleTimeout(600000);
        return new DefaultHandshakeHandler(
                new JettyRequestUpgradeStrategy(new WebSocketServerFactory(policy)));
    }
}

Quyidagi misol oldingi misoldagi konfiguratsiyaning XML ekvivalentini ko'rsatadi:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/websocket
        https://www.springframework.org/schema/websocket/spring-websocket.xsd">
    <websocket:handlers>
        <websocket:mapping path="/echo" handler="echoHandler"/>
        <websocket:handshake-handler ref="handshakeHandler"/>
    </websocket:handlers>
    <bean id="handshakeHandler" class="org.springframework...DefaultHandshakeHandler">
        <constructor-arg ref="upgradeStrategy"/>
    </bean>
    <bean id="upgradeStrategy" class="org.springframework...JettyRequestUpgradeStrategy">
        <constructor-arg ref="serverFactory"/>
    </bean>
    <bean id="serverFactory" class="org.eclipse.jetty...WebSocketServerFactory">
        <constructor-arg>
            <bean class="org.eclipse.jetty...WebSocketPolicy">
                <constructor-arg value="SERVER"/>
                <property name="inputBufferSize" value="8092"/>
                <property name="idleTimeout" value="600000"/>
            </bean>
        </constructor-arg>
    </bean>
</beans>

Yaroqli manbalar

Spring Framework 4.1.5 versiyasidan boshlab, WebSocket va SockJS uchun default ish logikasi faqat bir xil manbadan kelgan so'rovlarni qabul qilishdan iborat. Shuningdek, barcha yoki ma'lum manbalar ro'yxatini ruxsat berish mumkin. Ushbu tekshiruv asosan brauzer mijozlari uchun mo'ljallangan. Boshqa turdagi mijozlarga Origin sarlavhasining qiymatini o'zgartirish hech qanday to'siq bermaydi (batafsil ma'lumot uchun "RFC 6454: Web Origin kontseptsiyasi" bo'limiga qarang).

Uchta ish logikasi variantlari quyidagicha:

  • Faqat bitta manbadan kelgan so'rovlarni qabul qilish (standart): Bu rejimda, agar SockJS yoqilgan bo'lsa, ichki ramka (Iframe) HTTP javobining X-Frame-Options sarlavhasi SAMEORIGINga o'rnatiladi va JSONP uzatish mexanizmi o'chiriladi, chunki u manba tekshiruvini imkoniyat bermaydi. Natijada, IE6 va IE7 qo'llab-quvvatlanmaydi, agar bu rejim yoqilgan bo'lsa.

  • Berilgan manbalar ro'yxatini qabul qilish: Har bir yaroqli manba http:// yoki https:// bilan boshlanishi kerak. Bu rejimda, agar SockJS yoqilgan bo'lsa, iframe uzatish o'chiriladi. Natijada, IE6 dan IE9 gacha qo'llab-quvvatlanmaydi, agar bu rejim yoqilgan bo'lsa.

  • Har qanday manbalarni qabul qilish: Ushbu rejimni yoqish uchun * yaroqli manba qiymati sifatida ko'rsatilishi kerak. Bu rejimda barcha uzatish mexanizmlari mavjud.

WebSocket va SockJS uchun yaroqli manbalarni quyidagi misolda ko'rsatilganidek sozlashingiz mumkin:

import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("https://mydomain.com");
    }
    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }
}

Quyidagi misol oldingi misoldagi konfiguratsiyaning XML ekvivalentini ko'rsatadi:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/websocket
        https://www.springframework.org/schema/websocket/spring-websocket.xsd">
    <websocket:handlers allowed-origins="https://mydomain.com">
        <websocket:mapping path="/myHandler" handler="myHandler" />
    </websocket:handlers>
    <bean id="myHandler" class="org.springframework.samples.MyHandler"/>
</beans>
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION