Add support for @WebFilter, @WebListener, @WebServlet
This commit adds a new annotation, @ServletComponentScan, that can be used to enable scanning for @WebFilter, @WebListener, and @WebServlet annotated classes. Registration beans will be automatically created for any classes that are found, with the configuration derived from the annotation.
This commit is contained in:
parent
07ec9bb849
commit
003268fb4e
|
|
@ -348,15 +348,23 @@ Spring Boot. The definitive list comes from searching the source code for
|
|||
|
||||
|
||||
|
||||
[[howto-add-a-servlet-filter-or-servletcontextlistener]]
|
||||
=== Add a Servlet, Filter or ServletContextListener to an application
|
||||
`Servlet`, `Filter`, `ServletContextListener` and the other listeners supported by the
|
||||
Servlet spec can be added to your application as `@Bean` definitions. Be very careful that
|
||||
they don't cause eager initialization of too many other beans because they have to be
|
||||
installed in the container very early in the application lifecycle (e.g. it's not a good
|
||||
idea to have them depend on your `DataSource` or JPA configuration). You can work around
|
||||
restrictions like that by initializing them lazily when first used instead of on
|
||||
initialization.
|
||||
[[howto-add-a-servlet-filter-or-listener]]
|
||||
=== Add a Servlet, Filter or Listener to an application
|
||||
There are two ways to add `Servlet`, `Filter`, `ServletContextListener` and the other
|
||||
listeners supported by the Servlet spec to your application. You can either provide
|
||||
Spring beans for them, or enable scanning for Servlet components.
|
||||
|
||||
|
||||
|
||||
[[howto-add-a-servlet-filter-or-listener-as-spring-bean]]
|
||||
==== Add a Servlet, Filter or Listener using a Spring bean
|
||||
To add a `Servlet`, `Filter`, or Servlet `*Listener` provide a `@Bean` definition for it.
|
||||
This can be very useful when you want to inject configuration or dependencies. However,
|
||||
you must be very careful that they don't cause eager initialization of too many other
|
||||
beans because they have to be installed in the container very early in the application
|
||||
lifecycle (e.g. it's not a good idea to have them depend on your `DataSource` or JPA
|
||||
configuration). You can work around restrictions like that by initializing them lazily
|
||||
when first used instead of on initialization.
|
||||
|
||||
In the case of `Filters` and `Servlets` you can also add mappings and init parameters by
|
||||
adding a `FilterRegistrationBean` or `ServletRegistrationBean` instead of or as well as
|
||||
|
|
@ -365,7 +373,7 @@ the underlying component.
|
|||
|
||||
|
||||
[[howto-disable-registration-of-a-servlet-or-filter]]
|
||||
=== Disable registration of a Servlet or Filter
|
||||
===== Disable registration of a Servlet or Filter
|
||||
As <<howto-add-a-servlet-filter-or-servletcontextlistener,described above>> any `Servlet`
|
||||
or `Filter` beans will be registered with the servlet container automatically. To disable
|
||||
registration of a particular `Filter` or `Servlet` bean create a registration bean for it
|
||||
|
|
@ -382,6 +390,15 @@ and mark it as disabled. For example:
|
|||
----
|
||||
|
||||
|
||||
[[howto-add-a-servlet-filter-or-listener-using-scanning]]
|
||||
==== Add Servlets, Filters, and Listeners using classpath scanning
|
||||
`@WebServlet`, `@WebFilter`, and `@WebListener` annotated classes can be automatically
|
||||
registered with an embedded servlet container by annotating a `@Configuration` class
|
||||
with `@ServletComponentScan` and specifying the package(s) containing the components
|
||||
that you want to register. By default, `@ServletComponentScan` will scan from the package
|
||||
of the annotated class.
|
||||
|
||||
|
||||
|
||||
[[howto-change-the-http-port]]
|
||||
=== Change the HTTP port
|
||||
|
|
@ -1215,7 +1232,7 @@ using the "logging.config" property.
|
|||
[[howto-configure-logback-for-loggin]]
|
||||
=== Configure Logback for logging
|
||||
If you put a `logback.xml` in the root of your classpath it will be picked up from
|
||||
there
|
||||
there
|
||||
(or `logback-spring.xml` to take advantage of the templating features provided by Boot). Spring Boot provides a default base configuration that you can include if you just
|
||||
want to set levels, e.g.
|
||||
|
||||
|
|
|
|||
|
|
@ -1585,12 +1585,18 @@ instance. By default the embedded server will listen for HTTP requests on port `
|
|||
|
||||
|
||||
|
||||
[[boot-features-embedded-container-servlets-and-filters]]
|
||||
==== Servlets and Filters
|
||||
[[boot-features-embedded-container-servlets-filters-listeners]]
|
||||
==== Servlets, Filters, and listeners
|
||||
When using an embedded servlet container you can register Servlets, Filters and all the
|
||||
listeners from the Servlet spec (e.g. `HttpSessionListener`) directly as
|
||||
Spring beans. This can be particularly convenient if you want to refer to a value from
|
||||
your `application.properties` during configuration.
|
||||
listeners from the Servlet spec (e.g. `HttpSessionListener`) either by using Spring beans
|
||||
or by scanning for Servlet components.
|
||||
|
||||
|
||||
[[boot-features-embedded-container-servlets-filters-listeners-beans]]
|
||||
===== Registering Servlets, Filters, and listeners as Spring beans
|
||||
Any `Servlet`, `Filter` or Servlet `*Listener` instance that is a Spring bean will be
|
||||
registered with the embedded container. This can be particularly convenient if you want to
|
||||
refer to a value from your `application.properties` during configuration.
|
||||
|
||||
By default, if the context contains only a single Servlet it will be mapped to `/`. In the
|
||||
case of multiple Servlet beans the bean name will be used as a path prefix. Filters will
|
||||
|
|
@ -1603,6 +1609,16 @@ the `ServletContextInitializer` interface.
|
|||
|
||||
|
||||
|
||||
[[boot-features-embedded-container-servlets-filters-listeners-scanning]]
|
||||
===== Scanning for Servlets, Filters, and listeners
|
||||
When using an embedded container, automatic registration of `@WebServlet`, `@WebFilter`,
|
||||
and `@WebListener` annotated classes can be enabled using `@ServletComponentScan`.
|
||||
|
||||
TIP: `@ServletComponentScan` will have no effect in a standalone container, where the
|
||||
container's built-in discovery mechanisms will be used instead.
|
||||
|
||||
|
||||
|
||||
[[boot-features-embedded-container-application-context]]
|
||||
==== The EmbeddedWebApplicationContext
|
||||
Under the hood Spring Boot uses a new type of `ApplicationContext` for embedded servlet
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
|
||||
/**
|
||||
* Abstract base class for handlers of Servlet components discovered via classpath
|
||||
* scanning.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
abstract class ServletComponentHandler {
|
||||
|
||||
private final Class<? extends Annotation> annotationType;
|
||||
|
||||
private final TypeFilter typeFilter;
|
||||
|
||||
protected ServletComponentHandler(Class<? extends Annotation> annotationType) {
|
||||
this.typeFilter = new AnnotationTypeFilter(annotationType);
|
||||
this.annotationType = annotationType;
|
||||
}
|
||||
|
||||
TypeFilter getTypeFilter() {
|
||||
return this.typeFilter;
|
||||
}
|
||||
|
||||
protected String[] extractUrlPatterns(String attribute, Map<String, Object> attributes) {
|
||||
String[] urlPatterns = (String[]) attributes.get("urlPatterns");
|
||||
if (urlPatterns.length > 0) {
|
||||
if (((String[]) attributes.get("value")).length > 0) {
|
||||
throw new IllegalStateException("The urlPatterns and value attributes "
|
||||
+ "are mututally exclusive");
|
||||
}
|
||||
return urlPatterns;
|
||||
}
|
||||
return (String[]) attributes.get("value");
|
||||
}
|
||||
|
||||
protected final Map<String, String> extractInitParameters(
|
||||
Map<String, Object> attributes) {
|
||||
Map<String, String> initParameters = new HashMap<String, String>();
|
||||
for (AnnotationAttributes initParam : (AnnotationAttributes[]) attributes
|
||||
.get("initParams")) {
|
||||
String name = (String) initParam.get("name");
|
||||
String value = (String) initParam.get("value");
|
||||
initParameters.put(name, value);
|
||||
}
|
||||
return initParameters;
|
||||
}
|
||||
|
||||
void handle(ScannedGenericBeanDefinition beanDefinition,
|
||||
BeanDefinitionRegistry registry) {
|
||||
Map<String, Object> attributes = beanDefinition.getMetadata()
|
||||
.getAnnotationAttributes(this.annotationType.getName());
|
||||
if (attributes != null) {
|
||||
doHandle(attributes, beanDefinition, registry);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doHandle(Map<String, Object> attributes,
|
||||
BeanDefinition beanDefinition, BeanDefinitionRegistry registry);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
|
||||
|
||||
/**
|
||||
* {@link BeanFactoryPostProcessor} that registers beans for Servlet components found via
|
||||
* package scanning.
|
||||
*
|
||||
* @see ServletComponentScan
|
||||
* @see ServletComponentScanRegistrar
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class ServletComponentRegisteringPostProcessor implements BeanFactoryPostProcessor,
|
||||
ApplicationContextAware {
|
||||
|
||||
private final List<ServletComponentHandler> handlers = Arrays.asList(
|
||||
new WebServletHandler(), new WebFilterHandler(), new WebListenerHandler());
|
||||
|
||||
private final Set<String> packagesToScan;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public ServletComponentRegisteringPostProcessor(Set<String> packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
if (isRunningInEmbeddedContainer()) {
|
||||
ClassPathScanningCandidateComponentProvider componentProvider = createComponentProvider();
|
||||
for (String packageToScan : this.packagesToScan) {
|
||||
for (BeanDefinition candidate : componentProvider
|
||||
.findCandidateComponents(packageToScan)) {
|
||||
if (candidate instanceof ScannedGenericBeanDefinition) {
|
||||
for (ServletComponentHandler handler : this.handlers) {
|
||||
handler.handle(((ScannedGenericBeanDefinition) candidate),
|
||||
(BeanDefinitionRegistry) this.applicationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRunningInEmbeddedContainer() {
|
||||
return this.applicationContext instanceof EmbeddedWebApplicationContext
|
||||
&& ((EmbeddedWebApplicationContext) this.applicationContext)
|
||||
.getServletContext() == null;
|
||||
}
|
||||
|
||||
private ClassPathScanningCandidateComponentProvider createComponentProvider() {
|
||||
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
|
||||
false);
|
||||
for (ServletComponentHandler handler : this.handlers) {
|
||||
componentProvider.addIncludeFilter(handler.getTypeFilter());
|
||||
}
|
||||
return componentProvider;
|
||||
}
|
||||
|
||||
Set<String> getPackagesToScan() {
|
||||
return Collections.unmodifiableSet(this.packagesToScan);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.annotation.WebListener;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Enables scanning for Servlet components ({@link WebFilter filters}, {@link WebServlet
|
||||
* servlets}, and {@link WebListener listeners}). Scanning is only performed when using an
|
||||
* embedded Servlet container.
|
||||
* <p>
|
||||
* Typically, one of {@code value}, {@code basePackages}, or {@code basePackageClasses}
|
||||
* should be specified to control the packages to be scanned for components. In their
|
||||
* absence, scanning will be performed from the package of the class with the annotation.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.3.0
|
||||
* @see WebServlet
|
||||
* @see WebFilter
|
||||
* @see WebListener
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import(ServletComponentScanRegistrar.class)
|
||||
public @interface ServletComponentScan {
|
||||
|
||||
/**
|
||||
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
|
||||
* declarations e.g.: {@code @ServletComponentScan("org.my.pkg")} instead of
|
||||
* {@code @ServletComponentScan(basePackages="org.my.pkg")}.
|
||||
*
|
||||
* @return the base packages to scan
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* Base packages to scan for annotated servlet components. {@link #value()} is an
|
||||
* alias for (and mutually exclusive with) this attribute.
|
||||
* <p>
|
||||
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
|
||||
* package names.
|
||||
*
|
||||
* @return the base packages to scan
|
||||
*/
|
||||
String[] basePackages() default {};
|
||||
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to
|
||||
* scan for annotated servlet components. The package of each class specified will be
|
||||
* scanned.
|
||||
*
|
||||
* @return classes from the base packages to scan
|
||||
*/
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} used by {@link ServletComponentScan}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
private static final String BEAN_NAME = "servletComponentRegisteringPostProcessor";
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
|
||||
if (registry.containsBeanDefinition(BEAN_NAME)) {
|
||||
updatePostProcessor(registry, packagesToScan);
|
||||
}
|
||||
else {
|
||||
addPostProcessor(registry, packagesToScan);
|
||||
}
|
||||
}
|
||||
|
||||
private void addPostProcessor(BeanDefinitionRegistry registry,
|
||||
Set<String> packagesToScan) {
|
||||
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
||||
beanDefinition.setBeanClass(ServletComponentRegisteringPostProcessor.class);
|
||||
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(
|
||||
packagesToScan);
|
||||
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
|
||||
}
|
||||
|
||||
private void updatePostProcessor(BeanDefinitionRegistry registry,
|
||||
Set<String> packagesToScan) {
|
||||
BeanDefinition definition = registry.getBeanDefinition(BEAN_NAME);
|
||||
ValueHolder constructorArguments = definition.getConstructorArgumentValues()
|
||||
.getGenericArgumentValue(String[].class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> mergedPackages = new LinkedHashSet<String>(
|
||||
(Set<String>) constructorArguments.getValue());
|
||||
mergedPackages.addAll(packagesToScan);
|
||||
constructorArguments.setValue(packagesToScan);
|
||||
}
|
||||
|
||||
private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
|
||||
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata
|
||||
.getAnnotationAttributes(ServletComponentScan.class.getName()));
|
||||
String[] value = attributes.getStringArray("value");
|
||||
String[] basePackages = attributes.getStringArray("basePackages");
|
||||
Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
|
||||
if (!ObjectUtils.isEmpty(value)) {
|
||||
Assert.state(ObjectUtils.isEmpty(basePackages),
|
||||
"@ServletComponentScan basePackages and value attributes are"
|
||||
+ " mutually exclusive");
|
||||
}
|
||||
Set<String> packagesToScan = new LinkedHashSet<String>();
|
||||
packagesToScan.addAll(Arrays.asList(value));
|
||||
packagesToScan.addAll(Arrays.asList(basePackages));
|
||||
for (Class<?> basePackageClass : basePackageClasses) {
|
||||
packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
|
||||
}
|
||||
if (packagesToScan.isEmpty()) {
|
||||
return Collections.singleton(ClassUtils.getPackageName(metadata
|
||||
.getClassName()));
|
||||
}
|
||||
return packagesToScan;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Handler for {@link WebFilter}-annotated classes
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class WebFilterHandler extends ServletComponentHandler {
|
||||
|
||||
WebFilterHandler() {
|
||||
super(WebFilter.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doHandle(Map<String, Object> attributes, BeanDefinition beanDefinition,
|
||||
BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(FilterRegistrationBean.class);
|
||||
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
|
||||
builder.addPropertyValue("dispatcherTypes", extractDispatcherTypes(attributes));
|
||||
builder.addPropertyValue("filter", beanDefinition);
|
||||
builder.addPropertyValue("initParameters", extractInitParameters(attributes));
|
||||
String name = determineName(attributes, beanDefinition);
|
||||
builder.addPropertyValue("name", name);
|
||||
builder.addPropertyValue("servletNames", attributes.get("servletNames"));
|
||||
builder.addPropertyValue("urlPatterns",
|
||||
extractUrlPatterns("urlPatterns", attributes));
|
||||
registry.registerBeanDefinition(name, builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private EnumSet<DispatcherType> extractDispatcherTypes(Map<String, Object> attributes) {
|
||||
DispatcherType[] dispatcherTypes = (DispatcherType[]) attributes
|
||||
.get("dispatcherTypes");
|
||||
if (dispatcherTypes.length == 0) {
|
||||
return EnumSet.noneOf(DispatcherType.class);
|
||||
}
|
||||
if (dispatcherTypes.length == 1) {
|
||||
return EnumSet.of(dispatcherTypes[0]);
|
||||
}
|
||||
return EnumSet.of(dispatcherTypes[0],
|
||||
Arrays.copyOfRange(dispatcherTypes, 1, dispatcherTypes.length));
|
||||
}
|
||||
|
||||
private String determineName(Map<String, Object> attributes,
|
||||
BeanDefinition beanDefinition) {
|
||||
return (String) (StringUtils.hasText((String) attributes.get("filterName")) ? attributes
|
||||
.get("filterName") : beanDefinition.getBeanClassName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.annotation.WebListener;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
|
||||
|
||||
/**
|
||||
* Handler for {@link WebListener}-annotated classes
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class WebListenerHandler extends ServletComponentHandler {
|
||||
|
||||
WebListenerHandler() {
|
||||
super(WebListener.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHandle(Map<String, Object> attributes,
|
||||
BeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ServletListenerRegistrationBean.class);
|
||||
builder.addPropertyValue("listener", beanDefinition);
|
||||
registry.registerBeanDefinition(beanDefinition.getBeanClassName(),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.context.embedded.ServletRegistrationBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Handler for {@link WebServlet}-annotated classes
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class WebServletHandler extends ServletComponentHandler {
|
||||
|
||||
WebServletHandler() {
|
||||
super(WebServlet.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doHandle(Map<String, Object> attributes, BeanDefinition beanDefinition,
|
||||
BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(ServletRegistrationBean.class);
|
||||
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
|
||||
builder.addPropertyValue("initParameters", extractInitParameters(attributes));
|
||||
builder.addPropertyValue("loadOnStartup", attributes.get("loadOnStartup"));
|
||||
String name = determineName(attributes, beanDefinition);
|
||||
builder.addPropertyValue("name", name);
|
||||
builder.addPropertyValue("servlet", beanDefinition);
|
||||
builder.addPropertyValue("urlMappings",
|
||||
extractUrlPatterns("urlPatterns", attributes));
|
||||
registry.registerBeanDefinition(name, builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
private String determineName(Map<String, Object> attributes,
|
||||
BeanDefinition beanDefinition) {
|
||||
return (String) (StringUtils.hasText((String) attributes.get("name")) ? attributes
|
||||
.get("name") : beanDefinition.getBeanClassName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
|
||||
|
||||
/**
|
||||
* Tests for {@link ServletComponentRegisteringPostProcessor}
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ServletComponentRegisteringPostProcessorTests {
|
||||
|
||||
private final ServletComponentRegisteringPostProcessor postProcessor = new ServletComponentRegisteringPostProcessor(
|
||||
new HashSet<String>(Arrays.asList(getClass().getPackage().getName())));
|
||||
|
||||
private final EmbeddedWebApplicationContext context = new EmbeddedWebApplicationContext();
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
this.postProcessor.setApplicationContext(this.context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
this.postProcessor.postProcessBeanFactory(this.context.getBeanFactory());
|
||||
this.context.getBeanDefinition("servletWithName");
|
||||
this.context.getBeanDefinition("defaultNameServlet");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ServletComponentScan}
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ServletComponentScanIntegrationTests {
|
||||
|
||||
private AnnotationConfigEmbeddedWebApplicationContext context;
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void componentsAreRegistered() {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
this.context.register(TestConfiguration.class);
|
||||
new ServerPortInfoApplicationContextInitializer().initialize(this.context);
|
||||
this.context.refresh();
|
||||
String port = this.context.getEnvironment().getProperty("local.server.port");
|
||||
String response = new RestTemplate().getForObject("http://localhost:" + port
|
||||
+ "/test", String.class);
|
||||
assertThat(response, is(equalTo("alpha bravo")));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ServletComponentScan(basePackages = "org.springframework.boot.web.servlet.testcomponents")
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public TomcatEmbeddedServletContainerFactory servletContainerFactory() {
|
||||
return new TomcatEmbeddedServletContainerFactory(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ServletComponentScanRegistrar}
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ServletComponentScanRegistrarTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@After
|
||||
public void after() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void packagesConfiguredWithValue() {
|
||||
this.context = new AnnotationConfigApplicationContext(ValuePackages.class);
|
||||
ServletComponentRegisteringPostProcessor postProcessor = this.context
|
||||
.getBean(ServletComponentRegisteringPostProcessor.class);
|
||||
assertThat(postProcessor.getPackagesToScan(),
|
||||
containsInAnyOrder("com.example.foo", "com.example.bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void packagesConfiguredWithBackPackages() {
|
||||
this.context = new AnnotationConfigApplicationContext(BasePackages.class);
|
||||
ServletComponentRegisteringPostProcessor postProcessor = this.context
|
||||
.getBean(ServletComponentRegisteringPostProcessor.class);
|
||||
assertThat(postProcessor.getPackagesToScan(),
|
||||
containsInAnyOrder("com.example.foo", "com.example.bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void packagesConfiguredWithBasePackageClasses() {
|
||||
this.context = new AnnotationConfigApplicationContext(BasePackageClasses.class);
|
||||
ServletComponentRegisteringPostProcessor postProcessor = this.context
|
||||
.getBean(ServletComponentRegisteringPostProcessor.class);
|
||||
assertThat(postProcessor.getPackagesToScan(), containsInAnyOrder(getClass()
|
||||
.getPackage().getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void packagesConfiguredWithBothValueAndBasePackages() {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("@ServletComponentScan basePackages and value"
|
||||
+ " attributes are mutually exclusive");
|
||||
this.context = new AnnotationConfigApplicationContext(ValueAndBasePackages.class);
|
||||
ServletComponentRegisteringPostProcessor postProcessor = this.context
|
||||
.getBean(ServletComponentRegisteringPostProcessor.class);
|
||||
assertThat(postProcessor.getPackagesToScan(), containsInAnyOrder(getClass()
|
||||
.getPackage().getName()));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ServletComponentScan({ "com.example.foo", "com.example.bar" })
|
||||
static class ValuePackages {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ServletComponentScan(basePackages = { "com.example.foo", "com.example.bar" })
|
||||
static class BasePackages {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ServletComponentScan(basePackageClasses = ServletComponentScanRegistrarTests.class)
|
||||
static class BasePackageClasses {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ServletComponentScan(value = "com.example.foo", basePackages = "com.example.bar")
|
||||
static class ValueAndBasePackages {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.annotation.WebInitParam;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
|
||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.arrayWithSize;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link WebFilterHandler}
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class WebFilterHandlerTests {
|
||||
|
||||
private final WebFilterHandler handler = new WebFilterHandler();
|
||||
|
||||
private final SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void defaultFilterConfiguration() throws IOException {
|
||||
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
|
||||
new SimpleMetadataReaderFactory()
|
||||
.getMetadataReader(DefaultConfigurationFilter.class.getName()));
|
||||
this.handler.handle(scanned, this.registry);
|
||||
BeanDefinition filterRegistrationBean = this.registry
|
||||
.getBeanDefinition(DefaultConfigurationFilter.class.getName());
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat(propertyValues.get("asyncSupported"), is((Object) false));
|
||||
assertThat((EnumSet<DispatcherType>) propertyValues.get("dispatcherTypes"),
|
||||
is(EnumSet.of(DispatcherType.REQUEST)));
|
||||
assertThat(((Map<String, String>) propertyValues.get("initParameters")).size(),
|
||||
is(0));
|
||||
assertThat((String[]) propertyValues.get("servletNames"), is(arrayWithSize(0)));
|
||||
assertThat((String[]) propertyValues.get("urlPatterns"), is(arrayWithSize(0)));
|
||||
assertThat(propertyValues.get("name"),
|
||||
is((Object) DefaultConfigurationFilter.class.getName()));
|
||||
assertThat(propertyValues.get("filter"), is(equalTo((Object) scanned)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterWithCustomName() throws IOException {
|
||||
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
|
||||
new SimpleMetadataReaderFactory()
|
||||
.getMetadataReader(CustomNameFilter.class.getName()));
|
||||
this.handler.handle(scanned, this.registry);
|
||||
BeanDefinition filterRegistrationBean = this.registry.getBeanDefinition("custom");
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat(propertyValues.get("name"), is((Object) "custom"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncSupported() throws IOException {
|
||||
BeanDefinition filterRegistrationBean = getBeanDefinition(AsyncSupportedFilter.class);
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat(propertyValues.get("asyncSupported"), is((Object) true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dispatcherTypes() throws IOException {
|
||||
BeanDefinition filterRegistrationBean = getBeanDefinition(DispatcherTypesFilter.class);
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat(propertyValues.get("dispatcherTypes"), is((Object) EnumSet.of(
|
||||
DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void initParameters() throws IOException {
|
||||
BeanDefinition filterRegistrationBean = getBeanDefinition(InitParametersFilter.class);
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat((Map<String, String>) propertyValues.get("initParameters"),
|
||||
hasEntry("a", "alpha"));
|
||||
assertThat((Map<String, String>) propertyValues.get("initParameters"),
|
||||
hasEntry("b", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servletNames() throws IOException {
|
||||
BeanDefinition filterRegistrationBean = getBeanDefinition(ServletNamesFilter.class);
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat((String[]) propertyValues.get("servletNames"),
|
||||
is(arrayContaining("alpha", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlPatterns() throws IOException {
|
||||
BeanDefinition filterRegistrationBean = getBeanDefinition(UrlPatternsFilter.class);
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat((String[]) propertyValues.get("urlPatterns"),
|
||||
is(arrayContaining("alpha", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlPatternsFromValue() throws IOException {
|
||||
BeanDefinition filterRegistrationBean = getBeanDefinition(UrlPatternsFromValueFilter.class);
|
||||
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
|
||||
assertThat((String[]) propertyValues.get("urlPatterns"),
|
||||
is(arrayContaining("alpha", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlPatternsDeclaredTwice() throws IOException {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("The urlPatterns and value attributes are mututally "
|
||||
+ "exclusive");
|
||||
getBeanDefinition(UrlPatternsDeclaredTwiceFilter.class);
|
||||
}
|
||||
|
||||
BeanDefinition getBeanDefinition(Class<?> filterClass) throws IOException {
|
||||
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
|
||||
new SimpleMetadataReaderFactory().getMetadataReader(filterClass.getName()));
|
||||
this.handler.handle(scanned, this.registry);
|
||||
return this.registry.getBeanDefinition(filterClass.getName());
|
||||
}
|
||||
|
||||
@WebFilter
|
||||
class DefaultConfigurationFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter(asyncSupported = true)
|
||||
class AsyncSupportedFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter(dispatcherTypes = { DispatcherType.REQUEST, DispatcherType.FORWARD,
|
||||
DispatcherType.INCLUDE })
|
||||
class DispatcherTypesFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter(initParams = { @WebInitParam(name = "a", value = "alpha"),
|
||||
@WebInitParam(name = "b", value = "bravo") })
|
||||
class InitParametersFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter(servletNames = { "alpha", "bravo" })
|
||||
class ServletNamesFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter(urlPatterns = { "alpha", "bravo" })
|
||||
class UrlPatternsFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter({ "alpha", "bravo" })
|
||||
class UrlPatternsFromValueFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter(value = { "alpha", "bravo" }, urlPatterns = { "alpha", "bravo" })
|
||||
class UrlPatternsDeclaredTwiceFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
@WebFilter(filterName = "custom")
|
||||
class CustomNameFilter extends BaseFilter {
|
||||
|
||||
}
|
||||
|
||||
class BaseFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletContextAttributeEvent;
|
||||
import javax.servlet.ServletContextAttributeListener;
|
||||
import javax.servlet.annotation.WebListener;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
|
||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
||||
|
||||
/**
|
||||
* Tests for {@WebListenerHandler}
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class WebListenerHandlerTests {
|
||||
|
||||
private final WebListenerHandler handler = new WebListenerHandler();
|
||||
|
||||
private final SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
|
||||
@Test
|
||||
public void listener() throws IOException {
|
||||
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
|
||||
new SimpleMetadataReaderFactory().getMetadataReader(TestListener.class
|
||||
.getName()));
|
||||
this.handler.handle(scanned, this.registry);
|
||||
this.registry.getBeanDefinition(TestListener.class.getName());
|
||||
}
|
||||
|
||||
@WebListener
|
||||
static class TestListener implements ServletContextAttributeListener {
|
||||
|
||||
@Override
|
||||
public void attributeAdded(ServletContextAttributeEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(ServletContextAttributeEvent event) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(ServletContextAttributeEvent event) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.annotation.WebInitParam;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
|
||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.arrayWithSize;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@WebServletHandler}
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class WebServletHandlerTests {
|
||||
|
||||
private final WebServletHandler handler = new WebServletHandler();
|
||||
|
||||
private final SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void defaultServletConfiguration() throws IOException {
|
||||
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
|
||||
new SimpleMetadataReaderFactory()
|
||||
.getMetadataReader(DefaultConfigurationServlet.class.getName()));
|
||||
this.handler.handle(scanned, this.registry);
|
||||
BeanDefinition servletRegistrationBean = this.registry
|
||||
.getBeanDefinition(DefaultConfigurationServlet.class.getName());
|
||||
MutablePropertyValues propertyValues = servletRegistrationBean
|
||||
.getPropertyValues();
|
||||
assertThat(propertyValues.get("asyncSupported"), is((Object) false));
|
||||
assertThat(((Map<String, String>) propertyValues.get("initParameters")).size(),
|
||||
is(0));
|
||||
assertThat((Integer) propertyValues.get("loadOnStartup"), is(-1));
|
||||
assertThat(propertyValues.get("name"),
|
||||
is((Object) DefaultConfigurationServlet.class.getName()));
|
||||
assertThat((String[]) propertyValues.get("urlMappings"), is(arrayWithSize(0)));
|
||||
assertThat(propertyValues.get("servlet"), is(equalTo((Object) scanned)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void servletWithCustomName() throws IOException {
|
||||
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
|
||||
new SimpleMetadataReaderFactory()
|
||||
.getMetadataReader(CustomNameServlet.class.getName()));
|
||||
this.handler.handle(scanned, this.registry);
|
||||
BeanDefinition servletRegistrationBean = this.registry
|
||||
.getBeanDefinition("custom");
|
||||
MutablePropertyValues propertyValues = servletRegistrationBean
|
||||
.getPropertyValues();
|
||||
assertThat(propertyValues.get("name"), is((Object) "custom"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncSupported() throws IOException {
|
||||
BeanDefinition servletRegistrationBean = getBeanDefinition(AsyncSupportedServlet.class);
|
||||
MutablePropertyValues propertyValues = servletRegistrationBean
|
||||
.getPropertyValues();
|
||||
assertThat(propertyValues.get("asyncSupported"), is((Object) true));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void initParameters() throws IOException {
|
||||
BeanDefinition servletRegistrationBean = getBeanDefinition(InitParametersServlet.class);
|
||||
MutablePropertyValues propertyValues = servletRegistrationBean
|
||||
.getPropertyValues();
|
||||
assertThat((Map<String, String>) propertyValues.get("initParameters"),
|
||||
hasEntry("a", "alpha"));
|
||||
assertThat((Map<String, String>) propertyValues.get("initParameters"),
|
||||
hasEntry("b", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMappings() throws IOException {
|
||||
BeanDefinition servletRegistrationBean = getBeanDefinition(UrlPatternsServlet.class);
|
||||
MutablePropertyValues propertyValues = servletRegistrationBean
|
||||
.getPropertyValues();
|
||||
assertThat((String[]) propertyValues.get("urlMappings"),
|
||||
is(arrayContaining("alpha", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlMappingsFromValue() throws IOException {
|
||||
BeanDefinition servletRegistrationBean = getBeanDefinition(UrlPatternsFromValueServlet.class);
|
||||
MutablePropertyValues propertyValues = servletRegistrationBean
|
||||
.getPropertyValues();
|
||||
assertThat((String[]) propertyValues.get("urlMappings"),
|
||||
is(arrayContaining("alpha", "bravo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlPatternsDeclaredTwice() throws IOException {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("The urlPatterns and value attributes are mututally "
|
||||
+ "exclusive");
|
||||
getBeanDefinition(UrlPatternsDeclaredTwiceServlet.class);
|
||||
}
|
||||
|
||||
BeanDefinition getBeanDefinition(Class<?> filterClass) throws IOException {
|
||||
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
|
||||
new SimpleMetadataReaderFactory().getMetadataReader(filterClass.getName()));
|
||||
this.handler.handle(scanned, this.registry);
|
||||
return this.registry.getBeanDefinition(filterClass.getName());
|
||||
}
|
||||
|
||||
@WebServlet
|
||||
class DefaultConfigurationServlet extends HttpServlet {
|
||||
|
||||
}
|
||||
|
||||
@WebServlet(asyncSupported = true)
|
||||
class AsyncSupportedServlet extends HttpServlet {
|
||||
|
||||
}
|
||||
|
||||
@WebServlet(initParams = { @WebInitParam(name = "a", value = "alpha"),
|
||||
@WebInitParam(name = "b", value = "bravo") })
|
||||
class InitParametersServlet extends HttpServlet {
|
||||
|
||||
}
|
||||
|
||||
@WebServlet(urlPatterns = { "alpha", "bravo" })
|
||||
class UrlPatternsServlet extends HttpServlet {
|
||||
|
||||
}
|
||||
|
||||
@WebServlet({ "alpha", "bravo" })
|
||||
class UrlPatternsFromValueServlet extends HttpServlet {
|
||||
|
||||
}
|
||||
|
||||
@WebServlet(value = { "alpha", "bravo" }, urlPatterns = { "alpha", "bravo" })
|
||||
class UrlPatternsDeclaredTwiceServlet extends HttpServlet {
|
||||
|
||||
}
|
||||
|
||||
@WebServlet(name = "custom")
|
||||
class CustomNameServlet extends HttpServlet {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet.testcomponents;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
|
||||
@WebFilter("/*")
|
||||
class TestFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
request.setAttribute("filterAttribute", "bravo");
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet.testcomponents;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.annotation.WebListener;
|
||||
|
||||
@WebListener
|
||||
class TestListener implements ServletContextListener {
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
sce.getServletContext().setAttribute("listenerAttribute", "alpha");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 org.springframework.boot.web.servlet.testcomponents;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/test")
|
||||
public class TestServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
resp.getWriter().print(
|
||||
((String) req.getServletContext().getAttribute("listenerAttribute"))
|
||||
+ " " + req.getAttribute("filterAttribute"));
|
||||
resp.getWriter().flush();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue