Spring Bootアプリケーショの組み込みTomcatとApacheとWebSocketの連携

# Spring Bootのアプリケーションについて

SpringBootでWebアプリを作成する際には、組み込みTomcatを利用したJarファイルの成果物を実行することで起動することが可能です。

```bash
java -jar xxx.jar
```


ただ、従来のWarファイルでのデプロイとは違うので組み込みTomcat+Apache+WebSocketとの連携設定で一癖ありハマりました。

## Ajpの設定
### 組み込みtomcat用のJavaConfigの追加

以下のJavaConfigが従来のserver.xmlの設定と同じものになります。

```java:TomcatConfiguration.java
@Configuration
public class TomcatConfiguration 
{

 
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
　　　　　　　　　　　　　　　　TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        tomcat.addAdditionalTomcatConnectors(ajpConnector());
        return tomcat;
    }

    private Connector ajpConnector() {
        Connector connector = new Connector("org.apache.coyote.ajp.AjpNioProtocol");
        connector.setAttribute("maxThreads", 100);
        connector.setProtocol("AJP/1.3");
        connector.setPort(8009);
        connector.setRedirectPort(8043);
        connector.setURIEncoding("UTF-8");
        return connector;
    }

}
```

```xml:server.xml
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
```

## WebSocketの有効化
### 1. 依存関係の追加
gradleの依存関係に追加

```groovy:build.gradle
dependencies {
...
    compile "org.springframework.boot:spring-boot-starter-websocket:1.3.3.RELEASE"
...
}
```

### 2. Websocketの有効化

`@EnableWebSocketMessageBroker`アノテーションを追加し、有効にする

```java:Application.java
@SpringBootApplication
@EnableWebSocketMessageBroker//追加
public class Application extends SpringBootServletInitializer
{
    public static void main( String... args )
    {
         SpringApplication.run( Application.class, args );
    }
}
```

### 3. WebSocket用のJavaConfigを追加

```java:WebSocketConfiguration.java
@Configuration
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer { // AbstractWebSocketMessageBrokerConfigurerを継承しWebSocket関連のBean定義をカスタマイズする

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat").setAllowedOrigins("*").withSockJS();//フロントが購読するエンドポイント
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/sock");
        registry.enableSimpleBroker("/topic", "/queue");
    }
}
```

### 4. コントローラーの設定


```java:ChatController.java
@RestController
@RequestMapping("/chat/")
public class ChatController
{    
    @MessageMapping( "/chat/{accountId}" )
    @SendTo( "/topic/chat/all" )
    public ChatList all( @DestinationVariable Integer accountId, ChatMessage message ) throws InterruptedException
    {
    ...
    }

}
```

### 5. フロントサイドのSockJSの設定
今回はAngularJs1系を利用

```js:ChatService.js
import SockJS from "sockjs-client";

export function ChatService($http, ChatStore) {
  let stompClient = {};
  var connect = ( $scope ) => {
    let socket = new SockJS( '/chat');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, (frame) => {//WebSocketのコネクション確立
      stompClient.subscribe('/topic/chat/all', ( chatList ) => {
      ...
      });
    });
  }
  var send = () => {
    stompClient.send(`/sock/chat/${ChatStore.accountId}`, {},JSON.stringify({
      'value': ChatStore.message
    }));
  }
  return {
    connect,
    send
 };
}
```

## Apacheの設定

```ini:httpd.conf
ProxyPass /chat/info ajp://localhost:8009/chat/info #SpringWebSocketが自動生成したSockJSとWebSocketを接続してくれるURL
ProxyPass /chat ws://localhost:8080/chat #wsのプロキシ設定
ProxyPass / ajp://localhost:8009/ #ajpのプロキシ設定
```

## 動作確認
上記の設定で組み込みTomcat+Apache+WebSocketの連携がうまくいく(はず)！！

# 終わりに

要点以外は端折りましたが、間違いがあったら都度記事を修正していきますので、お許しください。。。orz

じゃあの。