Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
6c9c4e0a
Commit
6c9c4e0a
authored
Aug 22, 2013
by
Dave Syer
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/websocket'
parents
b141d12a
4be79561
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
357 additions
and
156 deletions
+357
-156
pom.xml
spring-boot-autoconfigure/pom.xml
+5
-0
WebSocketAutoConfiguration.java
...t/autoconfigure/websocket/WebSocketAutoConfiguration.java
+151
-0
spring.factories
...utoconfigure/src/main/resources/META-INF/spring.factories
+2
-1
SampleIntegrationTests.java
.../org/springframework/boot/cli/SampleIntegrationTests.java
+3
-1
pom.xml
spring-boot-dependencies/pom.xml
+6
-1
pom.xml
spring-boot-integration-tests/pom.xml
+4
-0
pom.xml
spring-boot-samples/pom.xml
+1
-0
pom.xml
spring-boot-samples/spring-boot-sample-websocket/pom.xml
+4
-21
SampleWebSocketsApplication.java
...samples/websocket/config/SampleWebSocketsApplication.java
+6
-69
echo.html
...boot-sample-websocket/src/main/resources/static/echo.html
+2
-9
snake.html
...oot-sample-websocket/src/main/resources/static/snake.html
+4
-14
SampleWebSocketsApplicationTests.java
...ples/websocket/echo/SampleWebSocketsApplicationTests.java
+39
-7
pom.xml
spring-boot-starters/spring-boot-starter-parent/pom.xml
+6
-1
pom.xml
...tarters/spring-boot-starter-parent/src/main/maven/pom.xml
+6
-1
pom.xml
spring-boot-starters/spring-boot-starter-websocket/pom.xml
+2
-15
BeanDefinitionLoader.java
...n/java/org/springframework/boot/BeanDefinitionLoader.java
+39
-10
TomcatEmbeddedServletContainerFactory.java
...mbedded/tomcat/TomcatEmbeddedServletContainerFactory.java
+67
-5
SpringApplicationTests.java
...java/org/springframework/boot/SpringApplicationTests.java
+8
-0
application.properties
spring-boot/src/test/resources/application.properties
+2
-1
No files found.
spring-boot-autoconfigure/pom.xml
View file @
6c9c4e0a
...
...
@@ -71,6 +71,11 @@
<artifactId>
spring-web
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-websocket
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-webmvc
</artifactId>
...
...
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java
0 → 100644
View file @
6c9c4e0a
/*
* Copyright 2012-2013 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
org
.
springframework
.
boot
.
autoconfigure
.
websocket
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.servlet.ServletContainerInitializer
;
import
org.apache.catalina.Context
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.factory.config.BeanPostProcessor
;
import
org.springframework.boot.autoconfigure.AutoConfigureBefore
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration
;
import
org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
;
import
org.springframework.web.socket.WebSocketHandler
;
import
org.springframework.web.socket.sockjs.SockJsHttpRequestHandler
;
import
org.springframework.web.socket.sockjs.SockJsService
;
import
org.springframework.web.socket.sockjs.support.AbstractSockJsService
;
import
org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService
;
/**
* Auto configuration for websockets (and sockjs in particular). Users should be able to
* just define beans of type {@link WebSocketHandler}. If <code>spring-websocket</code> is
* detected on the classpath then we add a {@link DefaultSockJsService} and an MVC handler
* mapping to <code>/<beanName>/**</code> for all of the
* <code>WebSocketHandler</code> beans that have a bean name beginning with "/".
*
* @author Dave Syer
*/
@Configuration
@ConditionalOnClass
({
WebSocketHandler
.
class
})
@AutoConfigureBefore
(
EmbeddedServletContainerAutoConfiguration
.
class
)
public
class
WebSocketAutoConfiguration
{
private
static
class
WebSocketEndpointPostProcessor
implements
BeanPostProcessor
{
private
Map
<
String
,
WebSocketHandler
>
prefixes
=
new
HashMap
<
String
,
WebSocketHandler
>();
@Override
public
Object
postProcessBeforeInitialization
(
Object
bean
,
String
beanName
)
throws
BeansException
{
return
bean
;
}
@Override
public
Object
postProcessAfterInitialization
(
Object
bean
,
String
beanName
)
throws
BeansException
{
if
(
bean
instanceof
WebSocketHandler
&&
beanName
.
startsWith
(
"/"
))
{
this
.
prefixes
.
put
(
beanName
,
(
WebSocketHandler
)
bean
);
}
return
bean
;
}
public
WebSocketHandler
getHandler
(
String
prefix
)
{
return
this
.
prefixes
.
get
(
prefix
);
}
public
String
[]
getPrefixes
()
{
return
this
.
prefixes
.
keySet
().
toArray
(
new
String
[
this
.
prefixes
.
size
()]);
}
}
@Bean
public
WebSocketEndpointPostProcessor
webSocketEndpointPostProcessor
()
{
return
new
WebSocketEndpointPostProcessor
();
}
@Bean
@ConditionalOnMissingBean
(
SockJsService
.
class
)
public
DefaultSockJsService
sockJsService
()
{
DefaultSockJsService
service
=
new
DefaultSockJsService
(
sockJsTaskScheduler
());
service
.
setSockJsClientLibraryUrl
(
"https://cdn.sockjs.org/sockjs-0.3.4.min.js"
);
service
.
setWebSocketsEnabled
(
true
);
return
service
;
}
@Bean
public
SimpleUrlHandlerMapping
handlerMapping
(
SockJsService
sockJsService
,
Collection
<
WebSocketHandler
>
handlers
)
{
WebSocketEndpointPostProcessor
processor
=
webSocketEndpointPostProcessor
();
Map
<
String
,
Object
>
urlMap
=
new
HashMap
<
String
,
Object
>();
for
(
String
prefix
:
webSocketEndpointPostProcessor
().
getPrefixes
())
{
urlMap
.
put
(
prefix
+
"/**"
,
new
SockJsHttpRequestHandler
(
sockJsService
,
processor
.
getHandler
(
prefix
)));
}
if
(
sockJsService
instanceof
AbstractSockJsService
)
{
((
AbstractSockJsService
)
sockJsService
).
setValidSockJsPrefixes
(
processor
.
getPrefixes
());
}
SimpleUrlHandlerMapping
handlerMapping
=
new
SimpleUrlHandlerMapping
();
handlerMapping
.
setOrder
(-
1
);
handlerMapping
.
setUrlMap
(
urlMap
);
return
handlerMapping
;
}
@Bean
@ConditionalOnMissingBean
(
name
=
"sockJsTaskScheduler"
)
public
ThreadPoolTaskScheduler
sockJsTaskScheduler
()
{
ThreadPoolTaskScheduler
taskScheduler
=
new
ThreadPoolTaskScheduler
();
taskScheduler
.
setThreadNamePrefix
(
"SockJS-"
);
return
taskScheduler
;
}
@Configuration
@ConditionalOnClass
(
name
=
"org.apache.tomcat.websocket.server.WsSci"
)
protected
static
class
TomcatWebSocketConfiguration
{
@Bean
public
TomcatEmbeddedServletContainerFactory
tomcatEmbeddedServletContainerFactory
()
{
TomcatEmbeddedServletContainerFactory
factory
=
new
TomcatEmbeddedServletContainerFactory
()
{
@Override
protected
void
postProcessContext
(
Context
context
)
{
context
.
addServletContainerInitializer
(
(
ServletContainerInitializer
)
BeanUtils
.
instantiate
(
ClassUtils
.
resolveClassName
(
"org.apache.tomcat.websocket.server.WsSci"
,
null
)),
null
);
}
};
return
factory
;
}
}
}
spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
View file @
6c9c4e0a
...
...
@@ -12,4 +12,5 @@ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration
spring-boot-cli/src/test/java/org/springframework/boot/cli/SampleIntegrationTests.java
View file @
6c9c4e0a
...
...
@@ -29,6 +29,7 @@ import org.junit.BeforeClass;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.springframework.boot.OutputCapture
;
import
org.springframework.boot.cli.command.CleanCommand
;
import
org.springframework.boot.cli.command.RunCommand
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
...
...
@@ -66,8 +67,9 @@ public class SampleIntegrationTests {
}
@Before
public
void
setup
()
{
public
void
setup
()
throws
Exception
{
System
.
setProperty
(
"disableSpringSnapshotRepos"
,
"true"
);
new
CleanCommand
().
run
(
"org.springframework"
);
}
@After
...
...
spring-boot-dependencies/pom.xml
View file @
6c9c4e0a
...
...
@@ -7,7 +7,7 @@
<version>
0.5.0.BUILD-SNAPSHOT
</version>
<packaging>
pom
</packaging>
<properties>
<spring.version>
4.0.0.
M2
</spring.version>
<spring.version>
4.0.0.
BUILD-SNAPSHOT
</spring.version>
<spring.security.version>
3.2.0.M2
</spring.security.version>
<spring.integration.version>
2.2.4.RELEASE
</spring.integration.version>
<spring.batch.version>
2.2.0.RELEASE
</spring.batch.version>
...
...
@@ -273,6 +273,11 @@
<artifactId>
spring-tx
</artifactId>
<version>
${spring.version}
</version>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-websocket
</artifactId>
<version>
${spring.version}
</version>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-web
</artifactId>
...
...
spring-boot-integration-tests/pom.xml
View file @
6c9c4e0a
...
...
@@ -119,6 +119,10 @@
<configuration>
<settingsFile>
src/it/settings.xml
</settingsFile>
<projectsDirectory>
${main.basedir}/spring-boot-samples/
</projectsDirectory>
<pomExcludes>
<!-- temporarily suspend integration test (Bamboo doesn't like it, WTF?) -->
<pomExclude>
spring-boot-sample-websocket/pom.xml
</pomExclude>
</pomExcludes>
<localRepositoryPath>
${project.build.directory}/local-repo
</localRepositoryPath>
<skipInvocation>
${skipTests}
</skipInvocation>
</configuration>
...
...
spring-boot-samples/pom.xml
View file @
6c9c4e0a
...
...
@@ -26,6 +26,7 @@
<module>
spring-boot-sample-traditional
</module>
<module>
spring-boot-sample-web-static
</module>
<module>
spring-boot-sample-web-ui
</module>
<module>
spring-boot-sample-websocket
</module>
<module>
spring-boot-sample-xml
</module>
</modules>
<build>
...
...
spring-boot-samples/spring-boot-sample-websocket/
_
om.xml
→
spring-boot-samples/spring-boot-sample-websocket/
p
om.xml
View file @
6c9c4e0a
...
...
@@ -14,8 +14,8 @@
<properties>
<java.version>
1.7
</java.version>
<tomcat.version>
8.0
-SNAPSHOT
</tomcat.version>
<start-class>
org.springframework.boot.samples.websocket.config.
ApplicationConfigur
ation
</start-class>
<tomcat.version>
8.0
.0-RC1
</tomcat.version>
<start-class>
org.springframework.boot.samples.websocket.config.
SampleWebSocketsApplic
ation
</start-class>
</properties>
...
...
@@ -23,14 +23,10 @@
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-websocket
</artifactId>
<version>
${spring.boot.version}
</version>
</dependency>
<!-- For SockJS -->
<dependency>
<groupId>
org.eclipse.jetty.websocket
</groupId>
<artifactId>
websocket-client
</artifactId>
<version>
9.0.3.v20130506
</version>
<scope>
test
</scope>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-actuator
</artifactId>
</dependency>
</dependencies>
...
...
@@ -43,17 +39,4 @@
</plugins>
</build>
<repositories>
<repository>
<id>
tomcat-snapshots
</id>
<url>
https://repository.apache.org/content/repositories/snapshots
</url>
<snapshots>
<enabled>
true
</enabled>
</snapshots>
<releases>
<enabled>
false
</enabled>
</releases>
</repository>
</repositories>
</project>
spring-boot-samples/spring-boot-sample-websocket/src/main/java/org/springframework/boot/samples/websocket/config/SampleWebSocketsApplication.java
View file @
6c9c4e0a
...
...
@@ -16,38 +16,24 @@
package
org
.
springframework
.
boot
.
samples
.
websocket
.
config
;
import
java.util.HashMap
;
import
java.util.Map
;
import
org.apache.catalina.Context
;
import
org.apache.catalina.startup.Tomcat
;
import
org.apache.tomcat.websocket.server.WsSci
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory
;
import
org.springframework.boot.samples.websocket.client.GreetingService
;
import
org.springframework.boot.samples.websocket.client.SimpleGreetingService
;
import
org.springframework.boot.samples.websocket.echo.DefaultEchoService
;
import
org.springframework.boot.samples.websocket.echo.EchoService
;
import
org.springframework.boot.samples.websocket.echo.EchoWebSocketHandler
;
import
org.springframework.boot.samples.websocket.snake.SnakeWebSocketHandler
;
import
org.springframework.boot.web.SpringServletInitializer
;
import
org.springframework.boot.web.Spring
Boot
ServletInitializer
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
;
import
org.springframework.web.servlet.DispatcherServlet
;
import
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
;
import
org.springframework.web.socket.WebSocketHandler
;
import
org.springframework.web.socket.server.support.WebSocketHttpRequestHandler
;
import
org.springframework.web.socket.sockjs.SockJsService
;
import
org.springframework.web.socket.sockjs.support.DefaultSockJsService
;
import
org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler
;
import
org.springframework.web.socket.support.PerConnectionWebSocketHandler
;
@Configuration
public
class
SampleWebSocketsApplication
extends
SpringServletInitializer
{
@EnableAutoConfiguration
public
class
SampleWebSocketsApplication
extends
SpringBootServletInitializer
{
@Override
protected
Class
<?>[]
getConfigClasses
()
{
return
new
Class
<?>[]
{
SampleWebSocketsApplication
.
class
};
...
...
@@ -57,22 +43,6 @@ public class SampleWebSocketsApplication extends SpringServletInitializer {
SpringApplication
.
run
(
SampleWebSocketsApplication
.
class
,
args
);
}
@ConditionalOnClass
(
Tomcat
.
class
)
@Configuration
@EnableAutoConfiguration
protected
static
class
InitializationConfiguration
{
@Bean
public
TomcatEmbeddedServletContainerFactory
tomcatEmbeddedServletContainerFactory
()
{
TomcatEmbeddedServletContainerFactory
factory
=
new
TomcatEmbeddedServletContainerFactory
()
{
@Override
protected
void
postProcessContext
(
Context
context
)
{
context
.
addServletContainerInitializer
(
new
WsSci
(),
null
);
}
};
return
factory
;
}
}
@Bean
public
EchoService
echoService
()
{
return
new
DefaultEchoService
(
"Did you say \"%s\"?"
);
...
...
@@ -83,47 +53,14 @@ public class SampleWebSocketsApplication extends SpringServletInitializer {
return
new
SimpleGreetingService
();
}
@Bean
public
SimpleUrlHandlerMapping
handlerMapping
()
{
SockJsService
sockJsService
=
new
DefaultSockJsService
(
sockJsTaskScheduler
());
Map
<
String
,
Object
>
urlMap
=
new
HashMap
<
String
,
Object
>();
urlMap
.
put
(
"/echo"
,
new
WebSocketHttpRequestHandler
(
echoWebSocketHandler
()));
urlMap
.
put
(
"/snake"
,
new
WebSocketHttpRequestHandler
(
snakeWebSocketHandler
()));
urlMap
.
put
(
"/sockjs/echo/**"
,
new
SockJsHttpRequestHandler
(
sockJsService
,
echoWebSocketHandler
()));
urlMap
.
put
(
"/sockjs/snake/**"
,
new
SockJsHttpRequestHandler
(
sockJsService
,
snakeWebSocketHandler
()));
SimpleUrlHandlerMapping
handlerMapping
=
new
SimpleUrlHandlerMapping
();
handlerMapping
.
setOrder
(-
1
);
handlerMapping
.
setUrlMap
(
urlMap
);
return
handlerMapping
;
}
@Bean
public
DispatcherServlet
dispatcherServlet
()
{
DispatcherServlet
servlet
=
new
DispatcherServlet
();
servlet
.
setDispatchOptionsRequest
(
true
);
return
servlet
;
}
@Bean
@Bean
(
name
=
"/echo"
)
public
WebSocketHandler
echoWebSocketHandler
()
{
return
new
PerConnectionWebSocketHandler
(
EchoWebSocketHandler
.
class
);
}
@Bean
@Bean
(
name
=
"/snake"
)
public
WebSocketHandler
snakeWebSocketHandler
()
{
return
new
SnakeWebSocketHandler
();
}
@Bean
public
ThreadPoolTaskScheduler
sockJsTaskScheduler
()
{
ThreadPoolTaskScheduler
taskScheduler
=
new
ThreadPoolTaskScheduler
();
taskScheduler
.
setThreadNamePrefix
(
"SockJS-"
);
return
taskScheduler
;
}
}
spring-boot-samples/spring-boot-sample-websocket/src/main/resources/static/echo.html
View file @
6c9c4e0a
...
...
@@ -49,6 +49,7 @@
margin
:
0
;
}
</style>
<script
src=
"http://cdn.sockjs.org/sockjs-0.3.min.js"
></script>
<script
type=
"text/javascript"
>
var
ws
=
null
;
...
...
@@ -60,15 +61,7 @@
function
connect
()
{
var
target
=
document
.
getElementById
(
'target'
).
value
;
target
=
"ws://"
+
window
.
location
.
host
+
target
if
(
'WebSocket'
in
window
)
{
ws
=
new
WebSocket
(
target
);
}
else
if
(
'MozWebSocket'
in
window
)
{
ws
=
new
MozWebSocket
(
target
);
}
else
{
alert
(
'WebSocket is not supported by this browser.'
);
return
;
}
ws
=
new
SockJS
(
target
);
ws
.
onopen
=
function
()
{
setConnected
(
true
);
log
(
'Info: WebSocket connection opened.'
);
...
...
spring-boot-samples/spring-boot-sample-websocket/src/main/resources/static/snake.html
View file @
6c9c4e0a
...
...
@@ -49,6 +49,7 @@
margin
:
0
;
}
</style>
<script
src=
"http://cdn.sockjs.org/sockjs-0.3.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
...
...
@@ -110,11 +111,7 @@
}
}
},
false
);
if
(
window
.
location
.
protocol
==
'http:'
)
{
Game
.
connect
(
'ws://'
+
window
.
location
.
host
+
'/snake'
);
}
else
{
Game
.
connect
(
'wss://'
+
window
.
location
.
host
+
'/snake'
);
}
Game
.
connect
();
};
Game
.
setDirection
=
function
(
direction
)
{
...
...
@@ -185,15 +182,8 @@
};
})();
Game
.
connect
=
(
function
(
host
)
{
if
(
'WebSocket'
in
window
)
{
Game
.
socket
=
new
WebSocket
(
host
);
}
else
if
(
'MozWebSocket'
in
window
)
{
Game
.
socket
=
new
MozWebSocket
(
host
);
}
else
{
Console
.
log
(
'Error: WebSocket is not supported by this browser.'
);
return
;
}
Game
.
connect
=
(
function
()
{
Game
.
socket
=
new
SockJS
(
"/snake"
);
Game
.
socket
.
onopen
=
function
()
{
// Socket open.. start the game loop.
...
...
spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/S
tandardClientApp
.java
→
spring-boot-samples/spring-boot-sample-websocket/src/test/java/org/springframework/boot/samples/websocket/echo/S
ampleWebSocketsApplicationTests
.java
View file @
6c9c4e0a
...
...
@@ -17,32 +17,64 @@ package org.springframework.boot.samples.websocket.echo;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.TimeUnit
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.junit.AfterClass
;
import
org.junit.BeforeClass
;
import
org.junit.Test
;
import
org.springframework.boot.CommandLineRunner
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.samples.websocket.client.GreetingService
;
import
org.springframework.boot.samples.websocket.client.SimpleClientWebSocketHandler
;
import
org.springframework.boot.samples.websocket.client.SimpleGreetingService
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.boot.samples.websocket.config.SampleWebSocketsApplication
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.web.socket.client.WebSocketConnectionManager
;
import
org.springframework.web.socket.client.endpoint.StandardWebSocketClient
;
public
class
S
tandardClientApp
{
public
class
S
ampleWebSocketsApplicationTests
{
private
static
Log
logger
=
LogFactory
.
getLog
(
S
tandardClientApp
.
class
);
private
static
Log
logger
=
LogFactory
.
getLog
(
S
ampleWebSocketsApplicationTests
.
class
);
private
static
final
String
WS_URI
=
"ws://localhost:8080/echo"
;
private
static
final
String
WS_URI
=
"ws://localhost:8080/echo/websocket"
;
private
static
ConfigurableApplicationContext
context
;
@BeforeClass
public
static
void
start
()
throws
Exception
{
Future
<
ConfigurableApplicationContext
>
future
=
Executors
.
newSingleThreadExecutor
().
submit
(
new
Callable
<
ConfigurableApplicationContext
>()
{
@Override
public
ConfigurableApplicationContext
call
()
throws
Exception
{
return
(
ConfigurableApplicationContext
)
SpringApplication
.
run
(
SampleWebSocketsApplication
.
class
);
}
});
context
=
future
.
get
(
30
,
TimeUnit
.
SECONDS
);
}
@AfterClass
public
static
void
stop
()
{
if
(
context
!=
null
)
{
context
.
close
();
}
}
@Test
public
void
runAndWait
()
throws
Exception
{
ApplicationContext
context
=
SpringApplication
.
run
(
ClientConfiguration
.
class
,
"--spring.main.web_environment=false"
);
assertEquals
(
0
,
context
.
getBean
(
ClientConfiguration
.
class
).
latch
.
getCount
());
ConfigurableApplicationContext
context
=
(
ConfigurableApplicationContext
)
SpringApplication
.
run
(
ClientConfiguration
.
class
,
"--spring.main.web_environment=false"
);
long
count
=
context
.
getBean
(
ClientConfiguration
.
class
).
latch
.
getCount
();
context
.
close
();
assertEquals
(
0
,
count
);
}
@Configuration
...
...
@@ -53,7 +85,7 @@ public class StandardClientApp {
@Override
public
void
run
(
String
...
args
)
throws
Exception
{
logger
.
info
(
"Waiting for response: latch="
+
latch
.
getCount
());
latch
.
await
();
latch
.
await
(
10
,
TimeUnit
.
SECONDS
);
logger
.
info
(
"Got response: latch="
+
latch
.
getCount
());
}
...
...
spring-boot-starters/spring-boot-starter-parent/pom.xml
View file @
6c9c4e0a
...
...
@@ -2,7 +2,7 @@
<!-- This POM file that can be used as a parent for your own builds. It provides
generally useful dependencies and plugins. NOTE: If you are editing a local
checkout of this file, be sure to modify 'spring-boot-starter
s
/src/main/parent/pom.xml'. -->
checkout of this file, be sure to modify 'spring-boot-starter
-parent
/src/main/parent/pom.xml'. -->
<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"
>
...
...
@@ -88,6 +88,11 @@
<artifactId>
spring-boot-starter-security
</artifactId>
<version>
${spring.boot.version}
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-websocket
</artifactId>
<version>
${spring.boot.version}
</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
...
spring-boot-starters/spring-boot-starter-parent/src/main/maven/pom.xml
View file @
6c9c4e0a
...
...
@@ -2,7 +2,7 @@
<!-- This POM file that can be used as a parent for your own builds. It provides
generally useful dependencies and plugins. NOTE: If you are editing a local
checkout of this file, be sure to modify 'spring-boot-starter
s
/src/main/parent/pom.xml'. -->
checkout of this file, be sure to modify 'spring-boot-starter
-parent
/src/main/parent/pom.xml'. -->
<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"
>
...
...
@@ -88,6 +88,11 @@
<artifactId>
spring-boot-starter-security
</artifactId>
<version>
${spring.boot.version}
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-websocket
</artifactId>
<version>
${spring.boot.version}
</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
...
spring-boot-starters/spring-boot-starter-websocket/pom.xml
View file @
6c9c4e0a
...
...
@@ -11,7 +11,7 @@
<packaging>
jar
</packaging>
<properties>
<main.basedir>
${basedir}/../..
</main.basedir>
<tomcat.version>
8.0
-SNAPSHOT
</tomcat.version>
<tomcat.version>
8.0
.0-RC1
</tomcat.version>
</properties>
<dependencyManagement>
<dependencies>
...
...
@@ -35,14 +35,13 @@
<exclusions>
<exclusion>
<groupId>
${project.groupId}
</groupId>
<artifactId>
spring-boot-
up
-tomcat
</artifactId>
<artifactId>
spring-boot-
starter
-tomcat
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-websocket
</artifactId>
<version>
${spring.version}
</version>
</dependency>
<dependency>
<groupId>
org.apache.tomcat.embed
</groupId>
...
...
@@ -53,16 +52,4 @@
<artifactId>
tomcat-embed-logging-juli
</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>
tomcat-snapshots
</id>
<url>
https://repository.apache.org/content/repositories/snapshots
</url>
<snapshots>
<enabled>
true
</enabled>
</snapshots>
<releases>
<enabled>
false
</enabled>
</releases>
</repository>
</repositories>
</project>
spring-boot/src/main/java/org/springframework/boot/BeanDefinitionLoader.java
View file @
6c9c4e0a
...
...
@@ -16,9 +16,11 @@
package
org
.
springframework
.
boot
;
import
java.io.IOException
;
import
java.util.HashSet
;
import
java.util.Set
;
import
org.springframework.beans.factory.BeanDefinitionStoreException
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.BeanNameGenerator
;
import
org.springframework.beans.factory.xml.XmlBeanDefinitionReader
;
...
...
@@ -26,7 +28,6 @@ import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import
org.springframework.context.annotation.ClassPathBeanDefinitionScanner
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.core.env.ConfigurableEnvironment
;
import
org.springframework.core.io.DefaultResourceLoader
;
import
org.springframework.core.io.Resource
;
import
org.springframework.core.io.ResourceLoader
;
import
org.springframework.core.io.support.PathMatchingResourcePatternResolver
;
...
...
@@ -49,7 +50,7 @@ import org.springframework.util.StringUtils;
*/
class
BeanDefinitionLoader
{
private
static
final
ResourceLoader
DEFAULT_RESOURCE_LOADER
=
new
DefaultResourceLoad
er
();
private
static
final
ResourceLoader
DEFAULT_RESOURCE_LOADER
=
new
PathMatchingResourcePatternResolv
er
();
private
Object
[]
sources
;
...
...
@@ -153,22 +154,50 @@ class BeanDefinitionLoader {
}
private
int
load
(
CharSequence
source
)
{
String
sourceString
=
xmlReader
.
getEnvironment
().
resolvePlaceholders
(
source
.
toString
());
try
{
// Use class utils so that period separated nested class names work
return
load
(
ClassUtils
.
forName
(
source
.
toString
()
,
null
));
return
load
(
ClassUtils
.
forName
(
source
String
,
null
));
}
catch
(
ClassNotFoundException
ex
)
{
// swallow exception and continue
}
Resource
loadedResource
=
(
this
.
resourceLoader
!=
null
?
this
.
resourceLoader
:
DEFAULT_RESOURCE_LOADER
).
getResource
(
source
.
toString
());
if
(
loadedResource
!=
null
&&
loadedResource
.
exists
())
{
return
load
(
loadedResource
);
ResourceLoader
loader
=
this
.
resourceLoader
!=
null
?
this
.
resourceLoader
:
DEFAULT_RESOURCE_LOADER
;
int
loadCount
=
0
;
if
(
loader
instanceof
ResourcePatternResolver
)
{
// Resource pattern matching available.
try
{
Resource
[]
resources
=
((
ResourcePatternResolver
)
loader
).
getResources
(
sourceString
);
for
(
Resource
resource
:
resources
)
{
if
(
resource
.
exists
()
)
{
loadCount
+=
load
(
resource
);
}
}
}
catch
(
IOException
ex
)
{
throw
new
BeanDefinitionStoreException
(
"Could not resolve bean definition resource pattern ["
+
sourceString
+
"]"
,
ex
);
}
}
Package
packageResource
=
findPackage
(
source
);
if
(
packageResource
!=
null
)
{
return
load
(
packageResource
);
if
(
!(
loader
instanceof
ResourcePatternResolver
)
)
{
// Can only load single resources by absolute URL.
Resource
loadedResource
=
loader
.
getResource
(
sourceString
);
if
(
loadedResource
!=
null
&&
loadedResource
.
exists
())
{
return
load
(
loadedResource
);
}
}
if
(
loadCount
>
0
)
{
return
loadCount
;
}
else
{
// Attempt to treat the source as a package name, common to all PatternResolver types
Package
packageResource
=
findPackage
(
source
);
if
(
packageResource
!=
null
)
{
return
load
(
packageResource
);
}
}
throw
new
IllegalArgumentException
(
"Invalid source '"
+
source
+
"'"
);
}
...
...
spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java
View file @
6c9c4e0a
...
...
@@ -18,6 +18,7 @@ package org.springframework.boot.context.embedded.tomcat;
import
java.io.File
;
import
java.io.IOException
;
import
java.lang.reflect.Method
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
...
...
@@ -34,6 +35,7 @@ import org.apache.catalina.loader.WebappLoader;
import
org.apache.catalina.startup.Tomcat
;
import
org.apache.catalina.startup.Tomcat.FixContextListener
;
import
org.apache.coyote.AbstractProtocol
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory
;
import
org.springframework.boot.context.embedded.EmbeddedServletContainer
;
import
org.springframework.boot.context.embedded.EmbeddedServletContainerException
;
...
...
@@ -45,6 +47,7 @@ import org.springframework.context.ResourceLoaderAware;
import
org.springframework.core.io.ResourceLoader
;
import
org.springframework.util.Assert
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.ReflectionUtils
;
/**
* {@link EmbeddedServletContainerFactory} that can be used to create
...
...
@@ -213,11 +216,7 @@ public class TomcatEmbeddedServletContainerFactory extends
context
.
getPipeline
().
addValve
(
valve
);
}
for
(
ErrorPage
errorPage
:
getErrorPages
())
{
org
.
apache
.
catalina
.
deploy
.
ErrorPage
tomcatPage
=
new
org
.
apache
.
catalina
.
deploy
.
ErrorPage
();
tomcatPage
.
setLocation
(
errorPage
.
getPath
());
tomcatPage
.
setExceptionType
(
errorPage
.
getExceptionName
());
tomcatPage
.
setErrorCode
(
errorPage
.
getStatusCode
());
context
.
addErrorPage
(
tomcatPage
);
new
TomcatErrorPage
(
errorPage
).
addToContext
(
context
);
}
for
(
MimeMappings
.
Mapping
mapping
:
getMimeMappings
())
{
context
.
addMimeMapping
(
mapping
.
getExtension
(),
mapping
.
getMimeType
());
...
...
@@ -380,4 +379,67 @@ public class TomcatEmbeddedServletContainerFactory extends
this
.
tomcatContextCustomizers
.
addAll
(
Arrays
.
asList
(
tomcatContextCustomizers
));
}
private
static
class
TomcatErrorPage
{
private
String
location
;
private
String
exceptionType
;
private
int
errorCode
;
private
Object
nativePage
;
public
TomcatErrorPage
(
ErrorPage
errorPage
)
{
this
.
location
=
errorPage
.
getPath
();
this
.
exceptionType
=
errorPage
.
getExceptionName
();
this
.
errorCode
=
errorPage
.
getStatusCode
();
this
.
nativePage
=
createNativePage
(
errorPage
);
}
private
Object
createNativePage
(
ErrorPage
errorPage
)
{
Object
nativePage
=
null
;
try
{
if
(
ClassUtils
.
isPresent
(
"org.apache.catalina.deploy.ErrorPage"
,
null
))
{
nativePage
=
new
org
.
apache
.
catalina
.
deploy
.
ErrorPage
();
}
else
{
if
(
ClassUtils
.
isPresent
(
"org.apache.tomcat.util.descriptor.web.ErrorPage"
,
null
))
{
nativePage
=
BeanUtils
.
instantiate
(
ClassUtils
.
forName
(
"org.apache.tomcat.util.descriptor.web.ErrorPage"
,
null
));
}
}
}
catch
(
ClassNotFoundException
e
)
{
}
catch
(
LinkageError
e
)
{
}
return
nativePage
;
}
public
void
addToContext
(
Context
context
)
{
Assert
.
state
(
this
.
nativePage
!=
null
,
"Neither Tomcat 7 nor 8 detected so no native error page exists"
);
if
(
ClassUtils
.
isPresent
(
"org.apache.catalina.deploy.ErrorPage"
,
null
))
{
org
.
apache
.
catalina
.
deploy
.
ErrorPage
errorPage
=
(
org
.
apache
.
catalina
.
deploy
.
ErrorPage
)
this
.
nativePage
;
errorPage
.
setLocation
(
this
.
location
);
errorPage
.
setErrorCode
(
this
.
errorCode
);
errorPage
.
setExceptionType
(
this
.
exceptionType
);
context
.
addErrorPage
(
errorPage
);
}
else
{
callMethod
(
this
.
nativePage
,
"setLocation"
,
this
.
location
,
String
.
class
);
callMethod
(
this
.
nativePage
,
"setErrorCode"
,
this
.
errorCode
,
int
.
class
);
callMethod
(
this
.
nativePage
,
"setExceptionType"
,
this
.
exceptionType
,
String
.
class
);
callMethod
(
context
,
"addErrorPage"
,
this
.
nativePage
,
this
.
nativePage
.
getClass
());
}
}
private
void
callMethod
(
Object
target
,
String
name
,
Object
value
,
Class
<?>
type
)
{
Method
method
=
ReflectionUtils
.
findMethod
(
target
.
getClass
(),
name
,
type
);
ReflectionUtils
.
invokeMethod
(
method
,
target
,
value
);
}
}
}
spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java
View file @
6c9c4e0a
...
...
@@ -275,6 +275,14 @@ public class SpringApplicationTests {
application
,
"initialSources"
);
assertThat
(
initialSources
.
toArray
(),
equalTo
(
sources
));
}
@Test
public
void
wildcardSources
()
{
Object
[]
sources
=
{
"classpath:org/springframework/boot/sample-${sample.app.test.prop}.xml"
};
TestSpringApplication
application
=
new
TestSpringApplication
(
sources
);
application
.
setWebEnvironment
(
false
);
application
.
run
();
}
@Test
public
void
run
()
throws
Exception
{
...
...
spring-boot/src/test/resources/application.properties
View file @
6c9c4e0a
foo
:
bucket
\ No newline at end of file
foo
:
bucket
sample.app.test.prop
:
*
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment