[SPRING] JSR-356 WebSocket @ServerEndpoint와 Spring 3 bean의 통합
SPRINGJSR-356 WebSocket @ServerEndpoint와 Spring 3 bean의 통합
완전히 새로운 JSR-356 WebSockets 지원없이 Spring 3.2.5를 사용하고 있습니다.
Spring 컨텍스트가 아닌 서블릿 컨테이너 자체에 의해 인스턴스화되는 @ServerEndpoint WebSocket 서버에서 싱글 톤 Bean 참조를 갖고 싶습니다.
그것을하는 깔끔한 방법은 무엇입니까?
내 현재 솔루션 : 정적 필드에 인스턴스가있는 @Service 싱글 톤 Bean을 만들었습니다.
@Service
public class WebSocketSupportBean {
private volatile static WebSocketSupportBean instance = null;
public static WebSocketSupportBean getInstance() {
return instance;
}
public WebSocketSupportBean() {
instance = this;
}
정적 메소드에 의해 @ServerEndpoint를 가져오고, null이 반환되면 사용자 연결을 끊습니다 (서버 시작 중에 Bean이 생성되지 않지만 사용자가 연결하는 경우).
해결법
-
==============================
1.스프링 프레임 워크 3.x로 웹 소켓을 설정할 수 있습니다.
스프링 프레임 워크 3.x로 웹 소켓을 설정할 수 있습니다.
스프링 코어 4.0으로 릴리스 된 Rossen Stoyanchev의 SpringConfiguration을 기반으로하는 방법을 보여주기위한 작은 개념 증명 (proof-of-concept) 애플리케이션을 개발했습니다.
응용 프로그램은 uri / wstest를 사용하여 @Autowired spring bean을 사용하여 인사말 단어를 선택하고 websocket 메시지에 회신하는 websocket 서버 끝점을 설정합니다.
websocket 연결이 시작되고 웹 소켓을 지원하는 브라우저에서 실행중인 html 페이지 (index.html)가 보내는 메시지입니다.
엔드 포인트 등록은 컨텍스트 초기화시 ServletContextListener에 의해 이루어지며 엔드 포인트가 인스턴스화되면 스프링으로 연결됩니다.
@WebListener public class MyApplication implements ServletContextListener { private final static String SERVER_CONTAINER_ATTRIBUTE = "javax.websocket.server.ServerContainer"; @Override public void contextInitialized(ServletContextEvent sce) { ServletContext container = sce.getServletContext(); final ServerContainer serverContainer = (ServerContainer) container.getAttribute(SERVER_CONTAINER_ATTRIBUTE); try { serverContainer.addEndpoint(new MyEndpointConfig(MyEndpoint.class, "/wstest")); } catch (DeploymentException e) { e.printStackTrace(); } } }
엔드 포인트는 다음과 같습니다.
@Component public class MyEndpoint extends Endpoint { @Autowired MyService myService; @Override public void onOpen(Session session, EndpointConfig config) { session.addMessageHandler(new MyMessageHandler(session)); } class MyMessageHandler implements MessageHandler.Whole<String> { final Session session; public MyMessageHandler(Session session) { this.session = session; } @Override public void onMessage(String message) { try { String greeting = myService.getGreeting(); session.getBasicRemote().sendText(greeting + ", got your message (" + message + "). Thanks ! (session: " + session.getId() + ")"); } catch (IOException e) { e.printStackTrace(); } } } }
Github 페이지에서 전체 소스를 확인하고 실행할 준비가되었습니다.
-
==============================
2.시험
시험
@ServerEndpoint(value = "/ws", configurator = SpringConfigurator.class)
그리고 Maven 종속성을 추가하십시오.
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> </dependency>
-
==============================
3.@ServerEndpoint 객체를 SpringBeanAutowiringSupport로 확장 할 수 있습니다. 그런 다음 Spring 기반의 웹 애플리케이션 내에서 이런 방식으로 생성 된 bean을 인식하게한다.
@ServerEndpoint 객체를 SpringBeanAutowiringSupport로 확장 할 수 있습니다. 그런 다음 Spring 기반의 웹 애플리케이션 내에서 이런 방식으로 생성 된 bean을 인식하게한다.
@PostConstruct public void init() { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); }
이렇게하면 @Autowired 주석이 올바르게 작동합니다.
@Autowired MyService myService;
-
==============================
4.이거 해봐, 나에게 효과적이야.
이거 해봐, 나에게 효과적이야.
@Component @ServerEndpoint(value = "/instantMessageServer",configurator = SpringConfigurator.class) public class InstantMessageServer{ private static IChatService chatService; @Autowired public InstantMessageServer(IChatService chatService){ this.chatService = chatService; } public InstantMessageServer(){} }
이 솔루션은 https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support에서 찾았습니다. @ServerEndpoint 주석으로 주석 처리 된 클래스는 SpringConfigurator로 httpsession을 얻습니다. 거기에는 메소드 수정 핸들러가 없습니다. SpringConfigurator를 확장하고이 메소드를 재정 의하여 별도의 구성자를 만들 수도 있습니다. Spring-websocket 및 메시징 API를 사용하여 실시간 웹 응용 프로그램을 만드는 것이 좋습니다.
public class ModifiedServerEndpointConfigurator extends SpringConfigurator{ @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { HttpSession httpSession = (HttpSession) request.getHttpSession(); sec.getUserProperties().put(HttpSession.class.getName(),httpSession); super.modifyHandshake(sec, request, response); } }
-
==============================
5.스프링 설정에 Bean 정의를 추가해야한다.
스프링 설정에 Bean 정의를 추가해야한다.
내가 JSR 356 websocket @ServerEndpoint를 통합하기 위해 찾은 해결책은 스프링 구성에 @Bean을 등록하여 수행 할 수있는 Spring에 의해 WebSocket 끝점에 대한 Servlet 컨테이너의 검색을 해제하는 것입니다. 이 봄까지 webSocket의 일부인 봄 STOMP websocket에 의해 일반 JSR 356 websocket을 대체하지 않습니다.
@ServerEndpoint(value="/chatMessage") public class ChatEndpoint{ // Normal websocket body goes here. }
구성에 Bean을 다음과 같이 추가 :
@Configuration public class WebsocketConfig{ @Bean public ChatEndpoint chatEndpoint(){ return new ChatEndpoint(); } // main one is ServerEndpointExporter which prevents Servlet container's scan for WebSocket @Bean public ServerEndpointExporter endpointExporter(){ return new ServerEndpointExporter(); } }
이 모든 것이 당신을 위해 완료되었습니다. 그러나 @ServerEndpoint에서 configurator = SpringConfigurator.class를 제거해야합니다. 나는 Spring Websocket 4.0.0을 사용하고 있으며 잘 동작한다. 이 링크를 볼 수도 있습니다.
괜찮 으면 컨셉으로이 링크를 따라 가세요.
일반적으로 스프링의 기본 구성과는 별도로 websocket 구성을 만들어야합니다.
from https://stackoverflow.com/questions/22435622/integrating-jsr-356-websocket-serverendpoint-with-spring-3-beans by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 autowired 빈이 널 포인터를 발생시킨다. (0) | 2019.02.18 |
---|---|
[SPRING] spring-boot webapp가 준비된 후 자동으로 브라우저를 시작합니다. (0) | 2019.02.18 |
[SPRING] Jersey ExceptionMapper는 예외를 매핑하지 않습니다. (0) | 2019.02.18 |
[SPRING] 포함 된 JAR에서 Spring의 @ComponentScan 검색 컴포넌트를 만드는 방법 (0) | 2019.02.18 |
[SPRING] Spring과 DBCP로 JDBC 커넥션을 처리하는 적절한 방법은 무엇입니까? (0) | 2019.02.18 |