46 changed files with 46 additions and 3083 deletions
@ -1,64 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<parent> |
|
||||||
<!-- Your own application should inherit from spring-boot-starter-parent --> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-samples</artifactId> |
|
||||||
<version>2.0.0.BUILD-SNAPSHOT</version> |
|
||||||
</parent> |
|
||||||
<artifactId>spring-boot-sample-jetty8-ssl</artifactId> |
|
||||||
<name>Spring Boot Jetty 8 SSL Sample</name> |
|
||||||
<description>Spring Boot Jetty 8 SSL Sample</description> |
|
||||||
<url>http://projects.spring.io/spring-boot/</url> |
|
||||||
<organization> |
|
||||||
<name>Pivotal Software, Inc.</name> |
|
||||||
<url>http://www.spring.io</url> |
|
||||||
</organization> |
|
||||||
<properties> |
|
||||||
<main.basedir>${basedir}/../..</main.basedir> |
|
||||||
<jetty.version>8.1.15.v20140411</jetty.version> |
|
||||||
<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version> |
|
||||||
<servlet-api.version>3.0.1</servlet-api.version> |
|
||||||
</properties> |
|
||||||
<dependencies> |
|
||||||
<!-- Compile --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter</artifactId> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-jetty</artifactId> |
|
||||||
<exclusions> |
|
||||||
<exclusion> |
|
||||||
<groupId>org.eclipse.jetty.websocket</groupId> |
|
||||||
<artifactId>*</artifactId> |
|
||||||
</exclusion> |
|
||||||
</exclusions> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework</groupId> |
|
||||||
<artifactId>spring-webmvc</artifactId> |
|
||||||
</dependency> |
|
||||||
<!-- Test --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-test</artifactId> |
|
||||||
<scope>test</scope> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.apache.httpcomponents</groupId> |
|
||||||
<artifactId>httpclient</artifactId> |
|
||||||
<scope>test</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<build> |
|
||||||
<plugins> |
|
||||||
<plugin> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId> |
|
||||||
</plugin> |
|
||||||
</plugins> |
|
||||||
</build> |
|
||||||
</project> |
|
||||||
@ -1,29 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2015 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8.ssl; |
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication; |
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|
||||||
|
|
||||||
@SpringBootApplication |
|
||||||
public class SampleJetty8SslApplication { |
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception { |
|
||||||
SpringApplication.run(SampleJetty8SslApplication.class, args); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2015 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8.ssl.service; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value; |
|
||||||
import org.springframework.stereotype.Component; |
|
||||||
|
|
||||||
@Component |
|
||||||
public class HelloWorldService { |
|
||||||
|
|
||||||
@Value("${name:World}") |
|
||||||
private String name; |
|
||||||
|
|
||||||
public String getHelloMessage() { |
|
||||||
return "Hello " + this.name; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,38 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8.ssl.web; |
|
||||||
|
|
||||||
import sample.jetty8.ssl.service.HelloWorldService; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.stereotype.Controller; |
|
||||||
import org.springframework.web.bind.annotation.GetMapping; |
|
||||||
import org.springframework.web.bind.annotation.ResponseBody; |
|
||||||
|
|
||||||
@Controller |
|
||||||
public class SampleController { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private HelloWorldService helloWorldService; |
|
||||||
|
|
||||||
@GetMapping("/") |
|
||||||
@ResponseBody |
|
||||||
public String helloWorld() { |
|
||||||
return this.helloWorldService.getHelloMessage(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,4 +0,0 @@ |
|||||||
server.port = 8443 |
|
||||||
server.ssl.key-store = classpath:sample.jks |
|
||||||
server.ssl.key-store-password = secret |
|
||||||
server.ssl.key-password = password |
|
||||||
Binary file not shown.
@ -1,57 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8.ssl; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
import org.junit.runner.RunWith; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.boot.context.embedded.LocalServerPort; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate; |
|
||||||
import org.springframework.http.HttpStatus; |
|
||||||
import org.springframework.http.ResponseEntity; |
|
||||||
import org.springframework.test.annotation.DirtiesContext; |
|
||||||
import org.springframework.test.context.junit4.SpringRunner; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
|
|
||||||
/** |
|
||||||
* Basic integration tests for demo application. |
|
||||||
* |
|
||||||
* @author Dave Syer |
|
||||||
*/ |
|
||||||
@RunWith(SpringRunner.class) |
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) |
|
||||||
@DirtiesContext |
|
||||||
public class SampleJetty8SslApplicationTests { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private TestRestTemplate restTemplate; |
|
||||||
|
|
||||||
@LocalServerPort |
|
||||||
private int port; |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testHome() throws Exception { |
|
||||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/", String.class); |
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); |
|
||||||
assertThat(entity.getBody()).isEqualTo("Hello World"); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<parent> |
|
||||||
<!-- Your own application should inherit from spring-boot-starter-parent --> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-samples</artifactId> |
|
||||||
<version>2.0.0.BUILD-SNAPSHOT</version> |
|
||||||
</parent> |
|
||||||
<artifactId>spring-boot-sample-jetty8</artifactId> |
|
||||||
<name>Spring Boot Jetty 8 Sample</name> |
|
||||||
<description>Spring Boot Jetty 8 Sample</description> |
|
||||||
<url>http://projects.spring.io/spring-boot/</url> |
|
||||||
<organization> |
|
||||||
<name>Pivotal Software, Inc.</name> |
|
||||||
<url>http://www.spring.io</url> |
|
||||||
</organization> |
|
||||||
<properties> |
|
||||||
<main.basedir>${basedir}/../..</main.basedir> |
|
||||||
<jetty.version>8.1.15.v20140411</jetty.version> |
|
||||||
<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version> |
|
||||||
</properties> |
|
||||||
<dependencies> |
|
||||||
<!-- Compile --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter</artifactId> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-jetty</artifactId> |
|
||||||
<exclusions> |
|
||||||
<exclusion> |
|
||||||
<groupId>org.eclipse.jetty.websocket</groupId> |
|
||||||
<artifactId>*</artifactId> |
|
||||||
</exclusion> |
|
||||||
</exclusions> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework</groupId> |
|
||||||
<artifactId>spring-webmvc</artifactId> |
|
||||||
</dependency> |
|
||||||
<!-- Test --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-test</artifactId> |
|
||||||
<scope>test</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<build> |
|
||||||
<plugins> |
|
||||||
<plugin> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId> |
|
||||||
</plugin> |
|
||||||
</plugins> |
|
||||||
</build> |
|
||||||
</project> |
|
||||||
@ -1,29 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2015 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8; |
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication; |
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|
||||||
|
|
||||||
@SpringBootApplication |
|
||||||
public class SampleJetty8Application { |
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception { |
|
||||||
SpringApplication.run(SampleJetty8Application.class, args); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2015 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8.service; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value; |
|
||||||
import org.springframework.stereotype.Component; |
|
||||||
|
|
||||||
@Component |
|
||||||
public class HelloWorldService { |
|
||||||
|
|
||||||
@Value("${name:World}") |
|
||||||
private String name; |
|
||||||
|
|
||||||
public String getHelloMessage() { |
|
||||||
return "Hello " + this.name; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,38 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8.web; |
|
||||||
|
|
||||||
import sample.jetty8.service.HelloWorldService; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.stereotype.Controller; |
|
||||||
import org.springframework.web.bind.annotation.GetMapping; |
|
||||||
import org.springframework.web.bind.annotation.ResponseBody; |
|
||||||
|
|
||||||
@Controller |
|
||||||
public class SampleController { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private HelloWorldService helloWorldService; |
|
||||||
|
|
||||||
@GetMapping("/") |
|
||||||
@ResponseBody |
|
||||||
public String helloWorld() { |
|
||||||
return this.helloWorldService.getHelloMessage(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
server.compression.enabled: true |
|
||||||
server.compression.min-response-size: 1 |
|
||||||
server.max-http-header-size: 4096 |
|
||||||
@ -1,81 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty8; |
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream; |
|
||||||
import java.nio.charset.Charset; |
|
||||||
import java.util.zip.GZIPInputStream; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
import org.junit.runner.RunWith; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate; |
|
||||||
import org.springframework.http.HttpEntity; |
|
||||||
import org.springframework.http.HttpHeaders; |
|
||||||
import org.springframework.http.HttpMethod; |
|
||||||
import org.springframework.http.HttpStatus; |
|
||||||
import org.springframework.http.ResponseEntity; |
|
||||||
import org.springframework.test.annotation.DirtiesContext; |
|
||||||
import org.springframework.test.context.junit4.SpringRunner; |
|
||||||
import org.springframework.util.StreamUtils; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
|
|
||||||
/** |
|
||||||
* Basic integration tests for demo application. |
|
||||||
* |
|
||||||
* @author Dave Syer |
|
||||||
* @author Andy Wilkinson |
|
||||||
*/ |
|
||||||
@RunWith(SpringRunner.class) |
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) |
|
||||||
@DirtiesContext |
|
||||||
public class SampleJetty8ApplicationTests { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private TestRestTemplate restTemplate; |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testHome() throws Exception { |
|
||||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/", String.class); |
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); |
|
||||||
assertThat(entity.getBody()).isEqualTo("Hello World"); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testCompression() throws Exception { |
|
||||||
HttpHeaders requestHeaders = new HttpHeaders(); |
|
||||||
requestHeaders.set("Accept-Encoding", "gzip"); |
|
||||||
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders); |
|
||||||
ResponseEntity<byte[]> entity = this.restTemplate.exchange("/", HttpMethod.GET, |
|
||||||
requestEntity, byte[].class); |
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); |
|
||||||
GZIPInputStream inflater = new GZIPInputStream( |
|
||||||
new ByteArrayInputStream(entity.getBody())); |
|
||||||
try { |
|
||||||
assertThat(StreamUtils.copyToString(inflater, Charset.forName("UTF-8"))) |
|
||||||
.isEqualTo("Hello World"); |
|
||||||
} |
|
||||||
finally { |
|
||||||
inflater.close(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<parent> |
|
||||||
<!-- Your own application should inherit from spring-boot-starter-parent --> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-samples</artifactId> |
|
||||||
<version>2.0.0.BUILD-SNAPSHOT</version> |
|
||||||
</parent> |
|
||||||
<artifactId>spring-boot-sample-jetty92</artifactId> |
|
||||||
<name>Spring Boot Jetty 9.2 Sample</name> |
|
||||||
<description>Spring Boot Jetty 9.2 Sample</description> |
|
||||||
<url>http://projects.spring.io/spring-boot/</url> |
|
||||||
<organization> |
|
||||||
<name>Pivotal Software, Inc.</name> |
|
||||||
<url>http://www.spring.io</url> |
|
||||||
</organization> |
|
||||||
<properties> |
|
||||||
<main.basedir>${basedir}/../..</main.basedir> |
|
||||||
<jetty.version>9.2.17.v20160517</jetty.version> |
|
||||||
</properties> |
|
||||||
<dependencies> |
|
||||||
<!-- Compile --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter</artifactId> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-jetty</artifactId> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework</groupId> |
|
||||||
<artifactId>spring-webmvc</artifactId> |
|
||||||
</dependency> |
|
||||||
<!-- Test --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-test</artifactId> |
|
||||||
<scope>test</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<build> |
|
||||||
<plugins> |
|
||||||
<plugin> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId> |
|
||||||
</plugin> |
|
||||||
</plugins> |
|
||||||
</build> |
|
||||||
</project> |
|
||||||
@ -1,29 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty92; |
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication; |
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|
||||||
|
|
||||||
@SpringBootApplication |
|
||||||
public class SampleJetty92Application { |
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception { |
|
||||||
SpringApplication.run(SampleJetty92Application.class, args); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty92.service; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value; |
|
||||||
import org.springframework.stereotype.Component; |
|
||||||
|
|
||||||
@Component |
|
||||||
public class HelloWorldService { |
|
||||||
|
|
||||||
@Value("${name:World}") |
|
||||||
private String name; |
|
||||||
|
|
||||||
public String getHelloMessage() { |
|
||||||
return "Hello " + this.name; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,38 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty92.web; |
|
||||||
|
|
||||||
import sample.jetty92.service.HelloWorldService; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.stereotype.Controller; |
|
||||||
import org.springframework.web.bind.annotation.GetMapping; |
|
||||||
import org.springframework.web.bind.annotation.ResponseBody; |
|
||||||
|
|
||||||
@Controller |
|
||||||
public class SampleController { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private HelloWorldService helloWorldService; |
|
||||||
|
|
||||||
@GetMapping("/") |
|
||||||
@ResponseBody |
|
||||||
public String helloWorld() { |
|
||||||
return this.helloWorldService.getHelloMessage(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,2 +0,0 @@ |
|||||||
server.compression.enabled: true |
|
||||||
server.compression.min-response-size: 1 |
|
||||||
@ -1,81 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package sample.jetty92; |
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream; |
|
||||||
import java.nio.charset.Charset; |
|
||||||
import java.util.zip.GZIPInputStream; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
import org.junit.runner.RunWith; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate; |
|
||||||
import org.springframework.http.HttpEntity; |
|
||||||
import org.springframework.http.HttpHeaders; |
|
||||||
import org.springframework.http.HttpMethod; |
|
||||||
import org.springframework.http.HttpStatus; |
|
||||||
import org.springframework.http.ResponseEntity; |
|
||||||
import org.springframework.test.annotation.DirtiesContext; |
|
||||||
import org.springframework.test.context.junit4.SpringRunner; |
|
||||||
import org.springframework.util.StreamUtils; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
|
|
||||||
/** |
|
||||||
* Basic integration tests for demo application. |
|
||||||
* |
|
||||||
* @author Dave Syer |
|
||||||
* @author Andy Wilkinson |
|
||||||
*/ |
|
||||||
@RunWith(SpringRunner.class) |
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) |
|
||||||
@DirtiesContext |
|
||||||
public class SampleJetty92ApplicationTests { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private TestRestTemplate restTemplate; |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testHome() throws Exception { |
|
||||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/", String.class); |
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); |
|
||||||
assertThat(entity.getBody()).isEqualTo("Hello World"); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testCompression() throws Exception { |
|
||||||
HttpHeaders requestHeaders = new HttpHeaders(); |
|
||||||
requestHeaders.set("Accept-Encoding", "gzip"); |
|
||||||
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders); |
|
||||||
ResponseEntity<byte[]> entity = this.restTemplate.exchange("/", HttpMethod.GET, |
|
||||||
requestEntity, byte[].class); |
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); |
|
||||||
GZIPInputStream inflater = new GZIPInputStream( |
|
||||||
new ByteArrayInputStream(entity.getBody())); |
|
||||||
try { |
|
||||||
assertThat(StreamUtils.copyToString(inflater, Charset.forName("UTF-8"))) |
|
||||||
.isEqualTo("Hello World"); |
|
||||||
} |
|
||||||
finally { |
|
||||||
inflater.close(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,54 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<parent> |
|
||||||
<!-- Your own application should inherit from spring-boot-starter-parent --> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-samples</artifactId> |
|
||||||
<version>2.0.0.BUILD-SNAPSHOT</version> |
|
||||||
</parent> |
|
||||||
<artifactId>spring-boot-sample-websocket-jetty93</artifactId> |
|
||||||
<name>Spring Boot WebSocket Jetty 9.3 Sample</name> |
|
||||||
<description>Spring Boot WebSocket Jetty 9.3 Sample</description> |
|
||||||
<url>http://projects.spring.io/spring-boot/</url> |
|
||||||
<organization> |
|
||||||
<name>Pivotal Software, Inc.</name> |
|
||||||
<url>http://www.spring.io</url> |
|
||||||
</organization> |
|
||||||
<properties> |
|
||||||
<main.basedir>${basedir}/../..</main.basedir> |
|
||||||
<jetty.version>9.3.14.v20161028</jetty.version> |
|
||||||
</properties> |
|
||||||
<dependencies> |
|
||||||
<!-- Compile --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-websocket</artifactId> |
|
||||||
<exclusions> |
|
||||||
<exclusion> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-tomcat</artifactId> |
|
||||||
</exclusion> |
|
||||||
</exclusions> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-jetty</artifactId> |
|
||||||
</dependency> |
|
||||||
<!-- Test --> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-starter-test</artifactId> |
|
||||||
<scope>test</scope> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<build> |
|
||||||
<plugins> |
|
||||||
<plugin> |
|
||||||
<groupId>org.springframework.boot</groupId> |
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId> |
|
||||||
</plugin> |
|
||||||
</plugins> |
|
||||||
</build> |
|
||||||
</project> |
|
||||||
@ -1,91 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93; |
|
||||||
|
|
||||||
import samples.websocket.jetty93.client.GreetingService; |
|
||||||
import samples.websocket.jetty93.client.SimpleGreetingService; |
|
||||||
import samples.websocket.jetty93.echo.DefaultEchoService; |
|
||||||
import samples.websocket.jetty93.echo.EchoService; |
|
||||||
import samples.websocket.jetty93.echo.EchoWebSocketHandler; |
|
||||||
import samples.websocket.jetty93.reverse.ReverseWebSocketEndpoint; |
|
||||||
import samples.websocket.jetty93.snake.SnakeWebSocketHandler; |
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication; |
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; |
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder; |
|
||||||
import org.springframework.boot.web.support.SpringBootServletInitializer; |
|
||||||
import org.springframework.context.annotation.Bean; |
|
||||||
import org.springframework.context.annotation.Configuration; |
|
||||||
import org.springframework.web.socket.WebSocketHandler; |
|
||||||
import org.springframework.web.socket.config.annotation.EnableWebSocket; |
|
||||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; |
|
||||||
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; |
|
||||||
import org.springframework.web.socket.handler.PerConnectionWebSocketHandler; |
|
||||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter; |
|
||||||
|
|
||||||
@Configuration |
|
||||||
@EnableAutoConfiguration |
|
||||||
@EnableWebSocket |
|
||||||
public class SampleJetty93WebSocketsApplication extends SpringBootServletInitializer |
|
||||||
implements WebSocketConfigurer { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { |
|
||||||
registry.addHandler(echoWebSocketHandler(), "/echo").withSockJS(); |
|
||||||
registry.addHandler(snakeWebSocketHandler(), "/snake").withSockJS(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { |
|
||||||
return application.sources(SampleJetty93WebSocketsApplication.class); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public EchoService echoService() { |
|
||||||
return new DefaultEchoService("Did you say \"%s\"?"); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public GreetingService greetingService() { |
|
||||||
return new SimpleGreetingService(); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public WebSocketHandler echoWebSocketHandler() { |
|
||||||
return new EchoWebSocketHandler(echoService()); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public WebSocketHandler snakeWebSocketHandler() { |
|
||||||
return new PerConnectionWebSocketHandler(SnakeWebSocketHandler.class); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public ReverseWebSocketEndpoint reverseWebSocketEndpoint() { |
|
||||||
return new ReverseWebSocketEndpoint(); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public ServerEndpointExporter serverEndpointExporter() { |
|
||||||
return new ServerEndpointExporter(); |
|
||||||
} |
|
||||||
|
|
||||||
public static void main(String[] args) { |
|
||||||
SpringApplication.run(SampleJetty93WebSocketsApplication.class, args); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,23 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.client; |
|
||||||
|
|
||||||
public interface GreetingService { |
|
||||||
|
|
||||||
String getGreeting(); |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,61 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.client; |
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch; |
|
||||||
import java.util.concurrent.atomic.AtomicReference; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import org.springframework.web.socket.TextMessage; |
|
||||||
import org.springframework.web.socket.WebSocketSession; |
|
||||||
import org.springframework.web.socket.handler.TextWebSocketHandler; |
|
||||||
|
|
||||||
public class SimpleClientWebSocketHandler extends TextWebSocketHandler { |
|
||||||
|
|
||||||
protected Log logger = LogFactory.getLog(SimpleClientWebSocketHandler.class); |
|
||||||
|
|
||||||
private final GreetingService greetingService; |
|
||||||
|
|
||||||
private final CountDownLatch latch; |
|
||||||
|
|
||||||
private final AtomicReference<String> messagePayload; |
|
||||||
|
|
||||||
public SimpleClientWebSocketHandler(GreetingService greetingService, |
|
||||||
CountDownLatch latch, AtomicReference<String> message) { |
|
||||||
this.greetingService = greetingService; |
|
||||||
this.latch = latch; |
|
||||||
this.messagePayload = message; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterConnectionEstablished(WebSocketSession session) throws Exception { |
|
||||||
TextMessage message = new TextMessage(this.greetingService.getGreeting()); |
|
||||||
session.sendMessage(message); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleTextMessage(WebSocketSession session, TextMessage message) |
|
||||||
throws Exception { |
|
||||||
this.logger.info("Received: " + message + " (" + this.latch.getCount() + ")"); |
|
||||||
session.close(); |
|
||||||
this.messagePayload.set(message.getPayload()); |
|
||||||
this.latch.countDown(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,26 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.client; |
|
||||||
|
|
||||||
public class SimpleGreetingService implements GreetingService { |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getGreeting() { |
|
||||||
return "Hello world!"; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,32 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.echo; |
|
||||||
|
|
||||||
public class DefaultEchoService implements EchoService { |
|
||||||
|
|
||||||
private final String echoFormat; |
|
||||||
|
|
||||||
public DefaultEchoService(String echoFormat) { |
|
||||||
this.echoFormat = (echoFormat != null) ? echoFormat : "%s"; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getMessage(String message) { |
|
||||||
return String.format(this.echoFormat, message); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,23 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.echo; |
|
||||||
|
|
||||||
public interface EchoService { |
|
||||||
|
|
||||||
String getMessage(String message); |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,60 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.echo; |
|
||||||
|
|
||||||
import org.slf4j.Logger; |
|
||||||
import org.slf4j.LoggerFactory; |
|
||||||
|
|
||||||
import org.springframework.web.socket.CloseStatus; |
|
||||||
import org.springframework.web.socket.TextMessage; |
|
||||||
import org.springframework.web.socket.WebSocketHandler; |
|
||||||
import org.springframework.web.socket.WebSocketSession; |
|
||||||
import org.springframework.web.socket.handler.TextWebSocketHandler; |
|
||||||
|
|
||||||
/** |
|
||||||
* Echo messages by implementing a Spring {@link WebSocketHandler} abstraction. |
|
||||||
*/ |
|
||||||
public class EchoWebSocketHandler extends TextWebSocketHandler { |
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(EchoWebSocketHandler.class); |
|
||||||
|
|
||||||
private final EchoService echoService; |
|
||||||
|
|
||||||
public EchoWebSocketHandler(EchoService echoService) { |
|
||||||
this.echoService = echoService; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterConnectionEstablished(WebSocketSession session) { |
|
||||||
logger.debug("Opened new session in instance " + this); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleTextMessage(WebSocketSession session, TextMessage message) |
|
||||||
throws Exception { |
|
||||||
String echoMessage = this.echoService.getMessage(message.getPayload()); |
|
||||||
logger.debug(echoMessage); |
|
||||||
session.sendMessage(new TextMessage(echoMessage)); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void handleTransportError(WebSocketSession session, Throwable exception) |
|
||||||
throws Exception { |
|
||||||
session.close(CloseStatus.SERVER_ERROR); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,33 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.reverse; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import javax.websocket.OnMessage; |
|
||||||
import javax.websocket.Session; |
|
||||||
import javax.websocket.server.ServerEndpoint; |
|
||||||
|
|
||||||
@ServerEndpoint("/reverse") |
|
||||||
public class ReverseWebSocketEndpoint { |
|
||||||
|
|
||||||
@OnMessage |
|
||||||
public void handleMessage(Session session, String message) throws IOException { |
|
||||||
session.getBasicRemote() |
|
||||||
.sendText("Reversed: " + new StringBuilder(message).reverse()); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,22 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.snake; |
|
||||||
|
|
||||||
public enum Direction { |
|
||||||
NONE, NORTH, SOUTH, EAST, WEST |
|
||||||
} |
|
||||||
@ -1,77 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.snake; |
|
||||||
|
|
||||||
public class Location { |
|
||||||
|
|
||||||
public int x; |
|
||||||
public int y; |
|
||||||
public static final int GRID_SIZE = 10; |
|
||||||
public static final int PLAYFIELD_HEIGHT = 480; |
|
||||||
public static final int PLAYFIELD_WIDTH = 640; |
|
||||||
|
|
||||||
public Location(int x, int y) { |
|
||||||
this.x = x; |
|
||||||
this.y = y; |
|
||||||
} |
|
||||||
|
|
||||||
public Location getAdjacentLocation(Direction direction) { |
|
||||||
switch (direction) { |
|
||||||
case NORTH: |
|
||||||
return new Location(this.x, this.y - Location.GRID_SIZE); |
|
||||||
case SOUTH: |
|
||||||
return new Location(this.x, this.y + Location.GRID_SIZE); |
|
||||||
case EAST: |
|
||||||
return new Location(this.x + Location.GRID_SIZE, this.y); |
|
||||||
case WEST: |
|
||||||
return new Location(this.x - Location.GRID_SIZE, this.y); |
|
||||||
case NONE: |
|
||||||
// fall through
|
|
||||||
default: |
|
||||||
return this; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean equals(Object o) { |
|
||||||
if (this == o) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
if (o == null || getClass() != o.getClass()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
Location location = (Location) o; |
|
||||||
|
|
||||||
if (this.x != location.x) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
if (this.y != location.y) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int hashCode() { |
|
||||||
int result = this.x; |
|
||||||
result = 31 * result + this.y; |
|
||||||
return result; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,160 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.snake; |
|
||||||
|
|
||||||
import java.util.ArrayDeque; |
|
||||||
import java.util.Collection; |
|
||||||
import java.util.Deque; |
|
||||||
|
|
||||||
import org.springframework.web.socket.TextMessage; |
|
||||||
import org.springframework.web.socket.WebSocketSession; |
|
||||||
|
|
||||||
public class Snake { |
|
||||||
|
|
||||||
private static final int DEFAULT_LENGTH = 5; |
|
||||||
|
|
||||||
private final Deque<Location> tail = new ArrayDeque<Location>(); |
|
||||||
|
|
||||||
private final Object monitor = new Object(); |
|
||||||
|
|
||||||
private final int id; |
|
||||||
|
|
||||||
private final WebSocketSession session; |
|
||||||
|
|
||||||
private final String hexColor; |
|
||||||
|
|
||||||
private Direction direction; |
|
||||||
|
|
||||||
private int length = DEFAULT_LENGTH; |
|
||||||
|
|
||||||
private Location head; |
|
||||||
|
|
||||||
public Snake(int id, WebSocketSession session) { |
|
||||||
this.id = id; |
|
||||||
this.session = session; |
|
||||||
this.hexColor = SnakeUtils.getRandomHexColor(); |
|
||||||
resetState(); |
|
||||||
} |
|
||||||
|
|
||||||
private void resetState() { |
|
||||||
this.direction = Direction.NONE; |
|
||||||
this.head = SnakeUtils.getRandomLocation(); |
|
||||||
this.tail.clear(); |
|
||||||
this.length = DEFAULT_LENGTH; |
|
||||||
} |
|
||||||
|
|
||||||
private void kill() throws Exception { |
|
||||||
synchronized (this.monitor) { |
|
||||||
resetState(); |
|
||||||
sendMessage("{'type': 'dead'}"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void reward() throws Exception { |
|
||||||
synchronized (this.monitor) { |
|
||||||
this.length++; |
|
||||||
sendMessage("{'type': 'kill'}"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected void sendMessage(String msg) throws Exception { |
|
||||||
this.session.sendMessage(new TextMessage(msg)); |
|
||||||
} |
|
||||||
|
|
||||||
public void update(Collection<Snake> snakes) throws Exception { |
|
||||||
synchronized (this.monitor) { |
|
||||||
Location nextLocation = this.head.getAdjacentLocation(this.direction); |
|
||||||
if (nextLocation.x >= SnakeUtils.PLAYFIELD_WIDTH) { |
|
||||||
nextLocation.x = 0; |
|
||||||
} |
|
||||||
if (nextLocation.y >= SnakeUtils.PLAYFIELD_HEIGHT) { |
|
||||||
nextLocation.y = 0; |
|
||||||
} |
|
||||||
if (nextLocation.x < 0) { |
|
||||||
nextLocation.x = SnakeUtils.PLAYFIELD_WIDTH; |
|
||||||
} |
|
||||||
if (nextLocation.y < 0) { |
|
||||||
nextLocation.y = SnakeUtils.PLAYFIELD_HEIGHT; |
|
||||||
} |
|
||||||
if (this.direction != Direction.NONE) { |
|
||||||
this.tail.addFirst(this.head); |
|
||||||
if (this.tail.size() > this.length) { |
|
||||||
this.tail.removeLast(); |
|
||||||
} |
|
||||||
this.head = nextLocation; |
|
||||||
} |
|
||||||
|
|
||||||
handleCollisions(snakes); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void handleCollisions(Collection<Snake> snakes) throws Exception { |
|
||||||
for (Snake snake : snakes) { |
|
||||||
boolean headCollision = this.id != snake.id |
|
||||||
&& snake.getHead().equals(this.head); |
|
||||||
boolean tailCollision = snake.getTail().contains(this.head); |
|
||||||
if (headCollision || tailCollision) { |
|
||||||
kill(); |
|
||||||
if (this.id != snake.id) { |
|
||||||
snake.reward(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Location getHead() { |
|
||||||
synchronized (this.monitor) { |
|
||||||
return this.head; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Collection<Location> getTail() { |
|
||||||
synchronized (this.monitor) { |
|
||||||
return this.tail; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void setDirection(Direction direction) { |
|
||||||
synchronized (this.monitor) { |
|
||||||
this.direction = direction; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public String getLocationsJson() { |
|
||||||
synchronized (this.monitor) { |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(this.head.x), |
|
||||||
Integer.valueOf(this.head.y))); |
|
||||||
for (Location location : this.tail) { |
|
||||||
sb.append(','); |
|
||||||
sb.append(String.format("{x: %d, y: %d}", Integer.valueOf(location.x), |
|
||||||
Integer.valueOf(location.y))); |
|
||||||
} |
|
||||||
return String.format("{'id':%d,'body':[%s]}", Integer.valueOf(this.id), |
|
||||||
sb.toString()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public int getId() { |
|
||||||
return this.id; |
|
||||||
} |
|
||||||
|
|
||||||
public String getHexColor() { |
|
||||||
return this.hexColor; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,115 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.snake; |
|
||||||
|
|
||||||
import java.util.Collection; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.Timer; |
|
||||||
import java.util.TimerTask; |
|
||||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||||
import java.util.concurrent.CopyOnWriteArrayList; |
|
||||||
|
|
||||||
import org.slf4j.Logger; |
|
||||||
import org.slf4j.LoggerFactory; |
|
||||||
|
|
||||||
/** |
|
||||||
* Sets up the timer for the multi-player snake game WebSocket example. |
|
||||||
*/ |
|
||||||
public class SnakeTimer { |
|
||||||
|
|
||||||
private static final long TICK_DELAY = 100; |
|
||||||
|
|
||||||
private static final Object MONITOR = new Object(); |
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SnakeTimer.class); |
|
||||||
|
|
||||||
private static final ConcurrentHashMap<Integer, Snake> snakes = new ConcurrentHashMap<Integer, Snake>(); |
|
||||||
|
|
||||||
private static Timer gameTimer = null; |
|
||||||
|
|
||||||
public static void addSnake(Snake snake) { |
|
||||||
synchronized (MONITOR) { |
|
||||||
if (snakes.isEmpty()) { |
|
||||||
startTimer(); |
|
||||||
} |
|
||||||
snakes.put(Integer.valueOf(snake.getId()), snake); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static Collection<Snake> getSnakes() { |
|
||||||
return Collections.unmodifiableCollection(snakes.values()); |
|
||||||
} |
|
||||||
|
|
||||||
public static void removeSnake(Snake snake) { |
|
||||||
synchronized (MONITOR) { |
|
||||||
snakes.remove(Integer.valueOf(snake.getId())); |
|
||||||
if (snakes.isEmpty()) { |
|
||||||
stopTimer(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void tick() throws Exception { |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
for (Iterator<Snake> iterator = SnakeTimer.getSnakes().iterator(); iterator |
|
||||||
.hasNext();) { |
|
||||||
Snake snake = iterator.next(); |
|
||||||
snake.update(SnakeTimer.getSnakes()); |
|
||||||
sb.append(snake.getLocationsJson()); |
|
||||||
if (iterator.hasNext()) { |
|
||||||
sb.append(','); |
|
||||||
} |
|
||||||
} |
|
||||||
broadcast(String.format("{'type': 'update', 'data' : [%s]}", sb.toString())); |
|
||||||
} |
|
||||||
|
|
||||||
public static void broadcast(String message) throws Exception { |
|
||||||
Collection<Snake> snakes = new CopyOnWriteArrayList<>(SnakeTimer.getSnakes()); |
|
||||||
for (Snake snake : snakes) { |
|
||||||
try { |
|
||||||
snake.sendMessage(message); |
|
||||||
} |
|
||||||
catch (Throwable ex) { |
|
||||||
// if Snake#sendMessage fails the client is removed
|
|
||||||
removeSnake(snake); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public static void startTimer() { |
|
||||||
gameTimer = new Timer(SnakeTimer.class.getSimpleName() + " Timer"); |
|
||||||
gameTimer.scheduleAtFixedRate(new TimerTask() { |
|
||||||
@Override |
|
||||||
public void run() { |
|
||||||
try { |
|
||||||
tick(); |
|
||||||
} |
|
||||||
catch (Throwable ex) { |
|
||||||
log.error("Caught to prevent timer from shutting down", ex); |
|
||||||
} |
|
||||||
} |
|
||||||
}, TICK_DELAY, TICK_DELAY); |
|
||||||
} |
|
||||||
|
|
||||||
public static void stopTimer() { |
|
||||||
if (gameTimer != null) { |
|
||||||
gameTimer.cancel(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,54 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.snake; |
|
||||||
|
|
||||||
import java.awt.Color; |
|
||||||
import java.util.Random; |
|
||||||
|
|
||||||
public class SnakeUtils { |
|
||||||
|
|
||||||
public static final int PLAYFIELD_WIDTH = 640; |
|
||||||
public static final int PLAYFIELD_HEIGHT = 480; |
|
||||||
public static final int GRID_SIZE = 10; |
|
||||||
|
|
||||||
private static final Random random = new Random(); |
|
||||||
|
|
||||||
public static String getRandomHexColor() { |
|
||||||
float hue = random.nextFloat(); |
|
||||||
// sat between 0.1 and 0.3
|
|
||||||
float saturation = (random.nextInt(2000) + 1000) / 10000f; |
|
||||||
float luminance = 0.9f; |
|
||||||
Color color = Color.getHSBColor(hue, saturation, luminance); |
|
||||||
return '#' + Integer.toHexString((color.getRGB() & 0xffffff) | 0x1000000) |
|
||||||
.substring(1); |
|
||||||
} |
|
||||||
|
|
||||||
public static Location getRandomLocation() { |
|
||||||
int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH)); |
|
||||||
int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT)); |
|
||||||
return new Location(x, y); |
|
||||||
} |
|
||||||
|
|
||||||
private static int roundByGridSize(int value) { |
|
||||||
value = value + (GRID_SIZE / 2); |
|
||||||
value = value / GRID_SIZE; |
|
||||||
value = value * GRID_SIZE; |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,112 +0,0 @@ |
|||||||
/* |
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
* contributor license agreements. See the NOTICE file distributed with |
|
||||||
* this work for additional information regarding copyright ownership. |
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
* (the "License"); you may not use this file except in compliance with |
|
||||||
* the License. You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.snake; |
|
||||||
|
|
||||||
import java.awt.Color; |
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.Random; |
|
||||||
import java.util.concurrent.atomic.AtomicInteger; |
|
||||||
|
|
||||||
import org.springframework.web.socket.CloseStatus; |
|
||||||
import org.springframework.web.socket.TextMessage; |
|
||||||
import org.springframework.web.socket.WebSocketSession; |
|
||||||
import org.springframework.web.socket.handler.TextWebSocketHandler; |
|
||||||
|
|
||||||
public class SnakeWebSocketHandler extends TextWebSocketHandler { |
|
||||||
|
|
||||||
public static final int PLAYFIELD_WIDTH = 640; |
|
||||||
public static final int PLAYFIELD_HEIGHT = 480; |
|
||||||
public static final int GRID_SIZE = 10; |
|
||||||
|
|
||||||
private static final AtomicInteger snakeIds = new AtomicInteger(0); |
|
||||||
private static final Random random = new Random(); |
|
||||||
|
|
||||||
private final int id; |
|
||||||
private Snake snake; |
|
||||||
|
|
||||||
public static String getRandomHexColor() { |
|
||||||
float hue = random.nextFloat(); |
|
||||||
// sat between 0.1 and 0.3
|
|
||||||
float saturation = (random.nextInt(2000) + 1000) / 10000f; |
|
||||||
float luminance = 0.9f; |
|
||||||
Color color = Color.getHSBColor(hue, saturation, luminance); |
|
||||||
return '#' + Integer.toHexString((color.getRGB() & 0xffffff) | 0x1000000) |
|
||||||
.substring(1); |
|
||||||
} |
|
||||||
|
|
||||||
public static Location getRandomLocation() { |
|
||||||
int x = roundByGridSize(random.nextInt(PLAYFIELD_WIDTH)); |
|
||||||
int y = roundByGridSize(random.nextInt(PLAYFIELD_HEIGHT)); |
|
||||||
return new Location(x, y); |
|
||||||
} |
|
||||||
|
|
||||||
private static int roundByGridSize(int value) { |
|
||||||
value = value + (GRID_SIZE / 2); |
|
||||||
value = value / GRID_SIZE; |
|
||||||
value = value * GRID_SIZE; |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
public SnakeWebSocketHandler() { |
|
||||||
this.id = snakeIds.getAndIncrement(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterConnectionEstablished(WebSocketSession session) throws Exception { |
|
||||||
this.snake = new Snake(this.id, session); |
|
||||||
SnakeTimer.addSnake(this.snake); |
|
||||||
StringBuilder sb = new StringBuilder(); |
|
||||||
for (Iterator<Snake> iterator = SnakeTimer.getSnakes().iterator(); iterator |
|
||||||
.hasNext();) { |
|
||||||
Snake snake = iterator.next(); |
|
||||||
sb.append(String.format("{id: %d, color: '%s'}", |
|
||||||
Integer.valueOf(snake.getId()), snake.getHexColor())); |
|
||||||
if (iterator.hasNext()) { |
|
||||||
sb.append(','); |
|
||||||
} |
|
||||||
} |
|
||||||
SnakeTimer |
|
||||||
.broadcast(String.format("{'type': 'join','data':[%s]}", sb.toString())); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void handleTextMessage(WebSocketSession session, TextMessage message) |
|
||||||
throws Exception { |
|
||||||
String payload = message.getPayload(); |
|
||||||
if ("west".equals(payload)) { |
|
||||||
this.snake.setDirection(Direction.WEST); |
|
||||||
} |
|
||||||
else if ("north".equals(payload)) { |
|
||||||
this.snake.setDirection(Direction.NORTH); |
|
||||||
} |
|
||||||
else if ("east".equals(payload)) { |
|
||||||
this.snake.setDirection(Direction.EAST); |
|
||||||
} |
|
||||||
else if ("south".equals(payload)) { |
|
||||||
this.snake.setDirection(Direction.SOUTH); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) |
|
||||||
throws Exception { |
|
||||||
SnakeTimer.removeSnake(this.snake); |
|
||||||
SnakeTimer.broadcast( |
|
||||||
String.format("{'type': 'leave', 'id': %d}", Integer.valueOf(this.id))); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,134 +0,0 @@ |
|||||||
<!-- |
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
contributor license agreements. See the NOTICE file distributed with |
|
||||||
this work for additional information regarding copyright ownership. |
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
(the "License"); you may not use this file except in compliance with |
|
||||||
the License. You may obtain a copy of the License at |
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software |
|
||||||
distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
See the License for the specific language governing permissions and |
|
||||||
limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<!DOCTYPE html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<title>Apache Tomcat WebSocket Examples: Echo</title> |
|
||||||
<style type="text/css"> |
|
||||||
#connect-container { |
|
||||||
float: left; |
|
||||||
width: 400px |
|
||||||
} |
|
||||||
|
|
||||||
#connect-container div { |
|
||||||
padding: 5px; |
|
||||||
} |
|
||||||
|
|
||||||
#console-container { |
|
||||||
float: left; |
|
||||||
margin-left: 15px; |
|
||||||
width: 400px; |
|
||||||
} |
|
||||||
|
|
||||||
#console { |
|
||||||
border: 1px solid #CCCCCC; |
|
||||||
border-right-color: #999999; |
|
||||||
border-bottom-color: #999999; |
|
||||||
height: 170px; |
|
||||||
overflow-y: scroll; |
|
||||||
padding: 5px; |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
|
|
||||||
#console p { |
|
||||||
padding: 0; |
|
||||||
margin: 0; |
|
||||||
} |
|
||||||
</style> |
|
||||||
<script src="https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script> |
|
||||||
<script type="text/javascript"> |
|
||||||
var ws = null; |
|
||||||
|
|
||||||
function setConnected(connected) { |
|
||||||
document.getElementById('connect').disabled = connected; |
|
||||||
document.getElementById('disconnect').disabled = !connected; |
|
||||||
document.getElementById('echo').disabled = !connected; |
|
||||||
} |
|
||||||
|
|
||||||
function connect() { |
|
||||||
var target = document.getElementById('target').value; |
|
||||||
ws = new SockJS(target); |
|
||||||
ws.onopen = function () { |
|
||||||
setConnected(true); |
|
||||||
log('Info: WebSocket connection opened.'); |
|
||||||
}; |
|
||||||
ws.onmessage = function (event) { |
|
||||||
log('Received: ' + event.data); |
|
||||||
}; |
|
||||||
ws.onclose = function () { |
|
||||||
setConnected(false); |
|
||||||
log('Info: WebSocket connection closed.'); |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
function disconnect() { |
|
||||||
if (ws != null) { |
|
||||||
ws.close(); |
|
||||||
ws = null; |
|
||||||
} |
|
||||||
setConnected(false); |
|
||||||
} |
|
||||||
|
|
||||||
function echo() { |
|
||||||
if (ws != null) { |
|
||||||
var message = document.getElementById('message').value; |
|
||||||
log('Sent: ' + message); |
|
||||||
ws.send(message); |
|
||||||
} else { |
|
||||||
alert('WebSocket connection not established, please connect.'); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function log(message) { |
|
||||||
var console = document.getElementById('console'); |
|
||||||
var p = document.createElement('p'); |
|
||||||
p.style.wordWrap = 'break-word'; |
|
||||||
p.appendChild(document.createTextNode(message)); |
|
||||||
console.appendChild(p); |
|
||||||
while (console.childNodes.length > 25) { |
|
||||||
console.removeChild(console.firstChild); |
|
||||||
} |
|
||||||
console.scrollTop = console.scrollHeight; |
|
||||||
} |
|
||||||
</script> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable |
|
||||||
Javascript and reload this page!</h2></noscript> |
|
||||||
<div> |
|
||||||
<div id="connect-container"> |
|
||||||
<div> |
|
||||||
<input id="target" type="text" size="40" style="width: 350px" value="/echo"/> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<button id="connect" onclick="connect();">Connect</button> |
|
||||||
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<textarea id="message" style="width: 350px">Here is a message!</textarea> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<button id="echo" onclick="echo();" disabled="disabled">Echo message</button> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div id="console-container"> |
|
||||||
<div id="console"></div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</body> |
|
||||||
</html> |
|
||||||
@ -1,33 +0,0 @@ |
|||||||
<!-- |
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
contributor license agreements. See the NOTICE file distributed with |
|
||||||
this work for additional information regarding copyright ownership. |
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
(the "License"); you may not use this file except in compliance with |
|
||||||
the License. You may obtain a copy of the License at |
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software |
|
||||||
distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
See the License for the specific language governing permissions and |
|
||||||
limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<!DOCTYPE html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<title>Apache Tomcat WebSocket Examples: Index</title> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable |
|
||||||
Javascript and reload this page!</h2></noscript> |
|
||||||
<p>Please select the sample you would like to try.</p> |
|
||||||
<ul> |
|
||||||
<li><a href="./echo.html">Echo</a></li> |
|
||||||
<li><a href="./reverse.html">Reverse</a></li> |
|
||||||
<li><a href="./snake.html">Snake</a></li> |
|
||||||
</ul> |
|
||||||
</body> |
|
||||||
</html> |
|
||||||
@ -1,141 +0,0 @@ |
|||||||
<!-- |
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
contributor license agreements. See the NOTICE file distributed with |
|
||||||
this work for additional information regarding copyright ownership. |
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
(the "License"); you may not use this file except in compliance with |
|
||||||
the License. You may obtain a copy of the License at |
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software |
|
||||||
distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
See the License for the specific language governing permissions and |
|
||||||
limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<!DOCTYPE html> |
|
||||||
<html> |
|
||||||
<head> |
|
||||||
<title>WebSocket Examples: Reverse</title> |
|
||||||
<style type="text/css"> |
|
||||||
#connect-container { |
|
||||||
float: left; |
|
||||||
width: 400px |
|
||||||
} |
|
||||||
|
|
||||||
#connect-container div { |
|
||||||
padding: 5px; |
|
||||||
} |
|
||||||
|
|
||||||
#console-container { |
|
||||||
float: left; |
|
||||||
margin-left: 15px; |
|
||||||
width: 400px; |
|
||||||
} |
|
||||||
|
|
||||||
#console { |
|
||||||
border: 1px solid #CCCCCC; |
|
||||||
border-right-color: #999999; |
|
||||||
border-bottom-color: #999999; |
|
||||||
height: 170px; |
|
||||||
overflow-y: scroll; |
|
||||||
padding: 5px; |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
|
|
||||||
#console p { |
|
||||||
padding: 0; |
|
||||||
margin: 0; |
|
||||||
} |
|
||||||
</style> |
|
||||||
<script type="text/javascript"> |
|
||||||
var ws = null; |
|
||||||
|
|
||||||
function setConnected(connected) { |
|
||||||
document.getElementById('connect').disabled = connected; |
|
||||||
document.getElementById('disconnect').disabled = !connected; |
|
||||||
document.getElementById('reverse').disabled = !connected; |
|
||||||
} |
|
||||||
|
|
||||||
function connect() { |
|
||||||
var target = document.getElementById('target').value; |
|
||||||
ws = new WebSocket(target); |
|
||||||
ws.onopen = function () { |
|
||||||
setConnected(true); |
|
||||||
log('Info: WebSocket connection opened.'); |
|
||||||
}; |
|
||||||
ws.onmessage = function (event) { |
|
||||||
log('Received: ' + event.data); |
|
||||||
}; |
|
||||||
ws.onclose = function () { |
|
||||||
setConnected(false); |
|
||||||
log('Info: WebSocket connection closed.'); |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
function updateTarget() { |
|
||||||
if (window.location.protocol == 'http:') { |
|
||||||
document.getElementById('target').value = 'ws://' + window.location.host + document.getElementById('target').value; |
|
||||||
} else { |
|
||||||
document.getElementById('target').value = 'wss://' + window.location.host + document.getElementById('target').value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function disconnect() { |
|
||||||
if (ws != null) { |
|
||||||
ws.close(); |
|
||||||
ws = null; |
|
||||||
} |
|
||||||
setConnected(false); |
|
||||||
} |
|
||||||
|
|
||||||
function reverse() { |
|
||||||
if (ws != null) { |
|
||||||
var message = document.getElementById('message').value; |
|
||||||
log('Sent: ' + message); |
|
||||||
ws.send(message); |
|
||||||
} else { |
|
||||||
alert('WebSocket connection not established, please connect.'); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function log(message) { |
|
||||||
var console = document.getElementById('console'); |
|
||||||
var p = document.createElement('p'); |
|
||||||
p.style.wordWrap = 'break-word'; |
|
||||||
p.appendChild(document.createTextNode(message)); |
|
||||||
console.appendChild(p); |
|
||||||
while (console.childNodes.length > 25) { |
|
||||||
console.removeChild(console.firstChild); |
|
||||||
} |
|
||||||
console.scrollTop = console.scrollHeight; |
|
||||||
} |
|
||||||
</script> |
|
||||||
</head> |
|
||||||
<body onload="updateTarget()"> |
|
||||||
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable |
|
||||||
Javascript and reload this page!</h2></noscript> |
|
||||||
<div> |
|
||||||
<div id="connect-container"> |
|
||||||
<div> |
|
||||||
<input id="target" type="text" size="40" style="width: 350px" value="/reverse"/> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<button id="connect" onclick="connect();">Connect</button> |
|
||||||
<button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<textarea id="message" style="width: 350px">Here is a message!</textarea> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<button id="reverse" onclick="reverse();" disabled="disabled">Reverse message</button> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div id="console-container"> |
|
||||||
<div id="console"></div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</body> |
|
||||||
</html> |
|
||||||
@ -1,250 +0,0 @@ |
|||||||
<!-- |
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more |
|
||||||
contributor license agreements. See the NOTICE file distributed with |
|
||||||
this work for additional information regarding copyright ownership. |
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0 |
|
||||||
(the "License"); you may not use this file except in compliance with |
|
||||||
the License. You may obtain a copy of the License at |
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0 |
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software |
|
||||||
distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
See the License for the specific language governing permissions and |
|
||||||
limitations under the License. |
|
||||||
--> |
|
||||||
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> |
|
||||||
<head> |
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> |
|
||||||
<title>Apache Tomcat WebSocket Examples: Multiplayer Snake</title> |
|
||||||
<style type="text/css"> |
|
||||||
#playground { |
|
||||||
width: 640px; |
|
||||||
height: 480px; |
|
||||||
background-color: #000; |
|
||||||
} |
|
||||||
|
|
||||||
#console-container { |
|
||||||
float: left; |
|
||||||
margin-left: 15px; |
|
||||||
width: 300px; |
|
||||||
} |
|
||||||
|
|
||||||
#console { |
|
||||||
border: 1px solid #CCCCCC; |
|
||||||
border-right-color: #999999; |
|
||||||
border-bottom-color: #999999; |
|
||||||
height: 480px; |
|
||||||
overflow-y: scroll; |
|
||||||
padding-left: 5px; |
|
||||||
padding-right: 5px; |
|
||||||
width: 100%; |
|
||||||
} |
|
||||||
|
|
||||||
#console p { |
|
||||||
padding: 0; |
|
||||||
margin: 0; |
|
||||||
} |
|
||||||
</style> |
|
||||||
<script src="https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable |
|
||||||
Javascript and reload this page!</h2></noscript> |
|
||||||
|
|
||||||
<div style="float: left"> |
|
||||||
<canvas id="playground" width="640" height="480"></canvas> |
|
||||||
</div> |
|
||||||
<div id="console-container"> |
|
||||||
<div id="console"></div> |
|
||||||
</div> |
|
||||||
<script type="text/javascript"> |
|
||||||
|
|
||||||
var Game = {}; |
|
||||||
|
|
||||||
Game.fps = 30; |
|
||||||
Game.socket = null; |
|
||||||
Game.nextFrame = null; |
|
||||||
Game.interval = null; |
|
||||||
Game.direction = 'none'; |
|
||||||
Game.gridSize = 10; |
|
||||||
|
|
||||||
function Snake() { |
|
||||||
this.snakeBody = []; |
|
||||||
this.color = null; |
|
||||||
} |
|
||||||
|
|
||||||
Snake.prototype.draw = function(context) { |
|
||||||
for (var id in this.snakeBody) { |
|
||||||
context.fillStyle = this.color; |
|
||||||
context.fillRect(this.snakeBody[id].x, this.snakeBody[id].y, Game.gridSize, Game.gridSize); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
Game.initialize = function() { |
|
||||||
this.entities = []; |
|
||||||
canvas = document.getElementById('playground'); |
|
||||||
if (!canvas.getContext) { |
|
||||||
Console.log('Error: 2d canvas not supported by this browser.'); |
|
||||||
return; |
|
||||||
} |
|
||||||
this.context = canvas.getContext('2d'); |
|
||||||
window.addEventListener('keydown', function (e) { |
|
||||||
var code = e.keyCode; |
|
||||||
if (code > 36 && code < 41) { |
|
||||||
switch (code) { |
|
||||||
case 37: |
|
||||||
if (Game.direction != 'east') Game.setDirection('west'); |
|
||||||
break; |
|
||||||
case 38: |
|
||||||
if (Game.direction != 'south') Game.setDirection('north'); |
|
||||||
break; |
|
||||||
case 39: |
|
||||||
if (Game.direction != 'west') Game.setDirection('east'); |
|
||||||
break; |
|
||||||
case 40: |
|
||||||
if (Game.direction != 'north') Game.setDirection('south'); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}, false); |
|
||||||
Game.connect(); |
|
||||||
}; |
|
||||||
|
|
||||||
Game.setDirection = function(direction) { |
|
||||||
Game.direction = direction; |
|
||||||
Game.socket.send(direction); |
|
||||||
Console.log('Sent: Direction ' + direction); |
|
||||||
}; |
|
||||||
|
|
||||||
Game.startGameLoop = function() { |
|
||||||
if (window.webkitRequestAnimationFrame) { |
|
||||||
Game.nextFrame = function () { |
|
||||||
webkitRequestAnimationFrame(Game.run); |
|
||||||
}; |
|
||||||
} else if (window.mozRequestAnimationFrame) { |
|
||||||
Game.nextFrame = function () { |
|
||||||
mozRequestAnimationFrame(Game.run); |
|
||||||
}; |
|
||||||
} else { |
|
||||||
Game.interval = setInterval(Game.run, 1000 / Game.fps); |
|
||||||
} |
|
||||||
if (Game.nextFrame != null) { |
|
||||||
Game.nextFrame(); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
Game.stopGameLoop = function () { |
|
||||||
Game.nextFrame = null; |
|
||||||
if (Game.interval != null) { |
|
||||||
clearInterval(Game.interval); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
Game.draw = function() { |
|
||||||
this.context.clearRect(0, 0, 640, 480); |
|
||||||
for (var id in this.entities) { |
|
||||||
this.entities[id].draw(this.context); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
Game.addSnake = function(id, color) { |
|
||||||
Game.entities[id] = new Snake(); |
|
||||||
Game.entities[id].color = color; |
|
||||||
}; |
|
||||||
|
|
||||||
Game.updateSnake = function(id, snakeBody) { |
|
||||||
if (typeof Game.entities[id] != "undefined") { |
|
||||||
Game.entities[id].snakeBody = snakeBody; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
Game.removeSnake = function(id) { |
|
||||||
Game.entities[id] = null; |
|
||||||
// Force GC. |
|
||||||
delete Game.entities[id]; |
|
||||||
}; |
|
||||||
|
|
||||||
Game.run = (function() { |
|
||||||
var skipTicks = 1000 / Game.fps, nextGameTick = (new Date).getTime(); |
|
||||||
|
|
||||||
return function() { |
|
||||||
while ((new Date).getTime() > nextGameTick) { |
|
||||||
nextGameTick += skipTicks; |
|
||||||
} |
|
||||||
Game.draw(); |
|
||||||
if (Game.nextFrame != null) { |
|
||||||
Game.nextFrame(); |
|
||||||
} |
|
||||||
}; |
|
||||||
})(); |
|
||||||
|
|
||||||
Game.connect = (function() { |
|
||||||
Game.socket = new SockJS("/snake"); |
|
||||||
|
|
||||||
Game.socket.onopen = function () { |
|
||||||
// Socket open.. start the game loop. |
|
||||||
Console.log('Info: WebSocket connection opened.'); |
|
||||||
Console.log('Info: Press an arrow key to begin.'); |
|
||||||
Game.startGameLoop(); |
|
||||||
setInterval(function() { |
|
||||||
// Prevent server read timeout. |
|
||||||
Game.socket.send('ping'); |
|
||||||
}, 5000); |
|
||||||
}; |
|
||||||
|
|
||||||
Game.socket.onclose = function () { |
|
||||||
Console.log('Info: WebSocket closed.'); |
|
||||||
Game.stopGameLoop(); |
|
||||||
}; |
|
||||||
|
|
||||||
Game.socket.onmessage = function (message) { |
|
||||||
// _Potential_ security hole, consider using json lib to parse data in production. |
|
||||||
var packet = eval('(' + message.data + ')'); |
|
||||||
switch (packet.type) { |
|
||||||
case 'update': |
|
||||||
for (var i = 0; i < packet.data.length; i++) { |
|
||||||
Game.updateSnake(packet.data[i].id, packet.data[i].body); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 'join': |
|
||||||
for (var j = 0; j < packet.data.length; j++) { |
|
||||||
Game.addSnake(packet.data[j].id, packet.data[j].color); |
|
||||||
} |
|
||||||
break; |
|
||||||
case 'leave': |
|
||||||
Game.removeSnake(packet.id); |
|
||||||
break; |
|
||||||
case 'dead': |
|
||||||
Console.log('Info: Your snake is dead, bad luck!'); |
|
||||||
Game.direction = 'none'; |
|
||||||
break; |
|
||||||
case 'kill': |
|
||||||
Console.log('Info: Head shot!'); |
|
||||||
break; |
|
||||||
} |
|
||||||
}; |
|
||||||
}); |
|
||||||
|
|
||||||
var Console = {}; |
|
||||||
|
|
||||||
Console.log = (function(message) { |
|
||||||
var console = document.getElementById('console'); |
|
||||||
var p = document.createElement('p'); |
|
||||||
p.style.wordWrap = 'break-word'; |
|
||||||
p.innerHTML = message; |
|
||||||
console.appendChild(p); |
|
||||||
while (console.childNodes.length > 25) { |
|
||||||
console.removeChild(console.firstChild); |
|
||||||
} |
|
||||||
console.scrollTop = console.scrollHeight; |
|
||||||
}); |
|
||||||
|
|
||||||
Game.initialize(); |
|
||||||
</script> |
|
||||||
</body> |
|
||||||
</html> |
|
||||||
@ -1,138 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2017 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93; |
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch; |
|
||||||
import java.util.concurrent.TimeUnit; |
|
||||||
import java.util.concurrent.atomic.AtomicReference; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
import org.junit.Test; |
|
||||||
import org.junit.runner.RunWith; |
|
||||||
import samples.websocket.jetty93.SampleJetty93WebSocketsApplication; |
|
||||||
import samples.websocket.jetty93.client.GreetingService; |
|
||||||
import samples.websocket.jetty93.client.SimpleClientWebSocketHandler; |
|
||||||
import samples.websocket.jetty93.client.SimpleGreetingService; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value; |
|
||||||
import org.springframework.boot.CommandLineRunner; |
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; |
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder; |
|
||||||
import org.springframework.boot.context.embedded.LocalServerPort; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
|
||||||
import org.springframework.context.ConfigurableApplicationContext; |
|
||||||
import org.springframework.context.annotation.Bean; |
|
||||||
import org.springframework.context.annotation.Configuration; |
|
||||||
import org.springframework.test.annotation.DirtiesContext; |
|
||||||
import org.springframework.test.context.junit4.SpringRunner; |
|
||||||
import org.springframework.web.socket.client.WebSocketConnectionManager; |
|
||||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
|
|
||||||
@RunWith(SpringRunner.class) |
|
||||||
@SpringBootTest(classes = SampleJetty93WebSocketsApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) |
|
||||||
@DirtiesContext |
|
||||||
public class SampleWebSocketsApplicationTests { |
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(SampleWebSocketsApplicationTests.class); |
|
||||||
|
|
||||||
@LocalServerPort |
|
||||||
private int port = 1234; |
|
||||||
|
|
||||||
@Test |
|
||||||
public void echoEndpoint() throws Exception { |
|
||||||
ConfigurableApplicationContext context = new SpringApplicationBuilder( |
|
||||||
ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class) |
|
||||||
.properties("websocket.uri:ws://localhost:" + this.port |
|
||||||
+ "/echo/websocket") |
|
||||||
.run("--spring.main.web_environment=false"); |
|
||||||
long count = context.getBean(ClientConfiguration.class).latch.getCount(); |
|
||||||
AtomicReference<String> messagePayloadReference = context |
|
||||||
.getBean(ClientConfiguration.class).messagePayload; |
|
||||||
context.close(); |
|
||||||
assertThat(count).isEqualTo(0); |
|
||||||
assertThat(messagePayloadReference.get()) |
|
||||||
.isEqualTo("Did you say \"Hello world!\"?"); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void reverseEndpoint() throws Exception { |
|
||||||
ConfigurableApplicationContext context = new SpringApplicationBuilder( |
|
||||||
ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class) |
|
||||||
.properties( |
|
||||||
"websocket.uri:ws://localhost:" + this.port + "/reverse") |
|
||||||
.run("--spring.main.web_environment=false"); |
|
||||||
long count = context.getBean(ClientConfiguration.class).latch.getCount(); |
|
||||||
AtomicReference<String> messagePayloadReference = context |
|
||||||
.getBean(ClientConfiguration.class).messagePayload; |
|
||||||
context.close(); |
|
||||||
assertThat(count).isEqualTo(0); |
|
||||||
assertThat(messagePayloadReference.get()).isEqualTo("Reversed: !dlrow olleH"); |
|
||||||
} |
|
||||||
|
|
||||||
@Configuration |
|
||||||
static class ClientConfiguration implements CommandLineRunner { |
|
||||||
|
|
||||||
@Value("${websocket.uri}") |
|
||||||
private String webSocketUri; |
|
||||||
|
|
||||||
private final CountDownLatch latch = new CountDownLatch(1); |
|
||||||
|
|
||||||
private final AtomicReference<String> messagePayload = new AtomicReference<String>(); |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run(String... args) throws Exception { |
|
||||||
logger.info("Waiting for response: latch=" + this.latch.getCount()); |
|
||||||
if (this.latch.await(10, TimeUnit.SECONDS)) { |
|
||||||
logger.info("Got response: " + this.messagePayload.get()); |
|
||||||
} |
|
||||||
else { |
|
||||||
logger.info("Response not received: latch=" + this.latch.getCount()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public WebSocketConnectionManager wsConnectionManager() { |
|
||||||
|
|
||||||
WebSocketConnectionManager manager = new WebSocketConnectionManager(client(), |
|
||||||
handler(), this.webSocketUri); |
|
||||||
manager.setAutoStartup(true); |
|
||||||
|
|
||||||
return manager; |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public StandardWebSocketClient client() { |
|
||||||
return new StandardWebSocketClient(); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public SimpleClientWebSocketHandler handler() { |
|
||||||
return new SimpleClientWebSocketHandler(greetingService(), this.latch, |
|
||||||
this.messagePayload); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public GreetingService greetingService() { |
|
||||||
return new SimpleGreetingService(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,153 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2017 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.echo; |
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch; |
|
||||||
import java.util.concurrent.TimeUnit; |
|
||||||
import java.util.concurrent.atomic.AtomicReference; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
import org.junit.Test; |
|
||||||
import org.junit.runner.RunWith; |
|
||||||
import samples.websocket.jetty93.SampleJetty93WebSocketsApplication; |
|
||||||
import samples.websocket.jetty93.client.GreetingService; |
|
||||||
import samples.websocket.jetty93.client.SimpleClientWebSocketHandler; |
|
||||||
import samples.websocket.jetty93.client.SimpleGreetingService; |
|
||||||
import samples.websocket.jetty93.echo.CustomContainerWebSocketsApplicationTests.CustomContainerConfiguration; |
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value; |
|
||||||
import org.springframework.boot.CommandLineRunner; |
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; |
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder; |
|
||||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; |
|
||||||
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; |
|
||||||
import org.springframework.context.ConfigurableApplicationContext; |
|
||||||
import org.springframework.context.annotation.Bean; |
|
||||||
import org.springframework.context.annotation.Configuration; |
|
||||||
import org.springframework.test.annotation.DirtiesContext; |
|
||||||
import org.springframework.test.context.junit4.SpringRunner; |
|
||||||
import org.springframework.util.SocketUtils; |
|
||||||
import org.springframework.web.socket.client.WebSocketConnectionManager; |
|
||||||
import org.springframework.web.socket.client.standard.StandardWebSocketClient; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
|
|
||||||
@RunWith(SpringRunner.class) |
|
||||||
@SpringBootTest(classes = { SampleJetty93WebSocketsApplication.class, |
|
||||||
CustomContainerConfiguration.class }, webEnvironment = WebEnvironment.DEFINED_PORT) |
|
||||||
@DirtiesContext |
|
||||||
public class CustomContainerWebSocketsApplicationTests { |
|
||||||
|
|
||||||
private static Log logger = LogFactory |
|
||||||
.getLog(CustomContainerWebSocketsApplicationTests.class); |
|
||||||
|
|
||||||
private static int PORT = SocketUtils.findAvailableTcpPort(); |
|
||||||
|
|
||||||
@Test |
|
||||||
public void echoEndpoint() throws Exception { |
|
||||||
ConfigurableApplicationContext context = new SpringApplicationBuilder( |
|
||||||
ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class) |
|
||||||
.properties("websocket.uri:ws://localhost:" + PORT |
|
||||||
+ "/ws/echo/websocket") |
|
||||||
.run("--spring.main.web_environment=false"); |
|
||||||
long count = context.getBean(ClientConfiguration.class).latch.getCount(); |
|
||||||
AtomicReference<String> messagePayloadReference = context |
|
||||||
.getBean(ClientConfiguration.class).messagePayload; |
|
||||||
context.close(); |
|
||||||
assertThat(count).isEqualTo(0); |
|
||||||
assertThat(messagePayloadReference.get()) |
|
||||||
.isEqualTo("Did you say \"Hello world!\"?"); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void reverseEndpoint() throws Exception { |
|
||||||
ConfigurableApplicationContext context = new SpringApplicationBuilder( |
|
||||||
ClientConfiguration.class, PropertyPlaceholderAutoConfiguration.class) |
|
||||||
.properties( |
|
||||||
"websocket.uri:ws://localhost:" + PORT + "/ws/reverse") |
|
||||||
.run("--spring.main.web_environment=false"); |
|
||||||
long count = context.getBean(ClientConfiguration.class).latch.getCount(); |
|
||||||
AtomicReference<String> messagePayloadReference = context |
|
||||||
.getBean(ClientConfiguration.class).messagePayload; |
|
||||||
context.close(); |
|
||||||
assertThat(count).isEqualTo(0); |
|
||||||
assertThat(messagePayloadReference.get()).isEqualTo("Reversed: !dlrow olleH"); |
|
||||||
} |
|
||||||
|
|
||||||
@Configuration |
|
||||||
protected static class CustomContainerConfiguration { |
|
||||||
|
|
||||||
@Bean |
|
||||||
public EmbeddedServletContainerFactory embeddedServletContainerFactory() { |
|
||||||
return new JettyEmbeddedServletContainerFactory("/ws", PORT); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Configuration |
|
||||||
static class ClientConfiguration implements CommandLineRunner { |
|
||||||
|
|
||||||
@Value("${websocket.uri}") |
|
||||||
private String webSocketUri; |
|
||||||
|
|
||||||
private final CountDownLatch latch = new CountDownLatch(1); |
|
||||||
|
|
||||||
private final AtomicReference<String> messagePayload = new AtomicReference<String>(); |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run(String... args) throws Exception { |
|
||||||
logger.info("Waiting for response: latch=" + this.latch.getCount()); |
|
||||||
if (this.latch.await(10, TimeUnit.SECONDS)) { |
|
||||||
logger.info("Got response: " + this.messagePayload.get()); |
|
||||||
} |
|
||||||
else { |
|
||||||
logger.info("Response not received: latch=" + this.latch.getCount()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public WebSocketConnectionManager wsConnectionManager() { |
|
||||||
|
|
||||||
WebSocketConnectionManager manager = new WebSocketConnectionManager(client(), |
|
||||||
handler(), this.webSocketUri); |
|
||||||
manager.setAutoStartup(true); |
|
||||||
|
|
||||||
return manager; |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public StandardWebSocketClient client() { |
|
||||||
return new StandardWebSocketClient(); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public SimpleClientWebSocketHandler handler() { |
|
||||||
return new SimpleClientWebSocketHandler(greetingService(), this.latch, |
|
||||||
this.messagePayload); |
|
||||||
} |
|
||||||
|
|
||||||
@Bean |
|
||||||
public GreetingService greetingService() { |
|
||||||
return new SimpleGreetingService(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,40 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2012-2016 the original author or authors. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package samples.websocket.jetty93.snake; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat; |
|
||||||
import static org.mockito.ArgumentMatchers.anyString; |
|
||||||
import static org.mockito.BDDMockito.willThrow; |
|
||||||
import static org.mockito.Mockito.mock; |
|
||||||
|
|
||||||
public class SnakeTimerTests { |
|
||||||
|
|
||||||
@Test |
|
||||||
public void removeDysfunctionalSnakes() throws Exception { |
|
||||||
Snake snake = mock(Snake.class); |
|
||||||
willThrow(new IOException()).given(snake).sendMessage(anyString()); |
|
||||||
SnakeTimer.addSnake(snake); |
|
||||||
|
|
||||||
SnakeTimer.broadcast(""); |
|
||||||
assertThat(SnakeTimer.getSnakes()).hasSize(0); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue