mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Add Spring Mobile Device Resolver autoconfiguration
This commit is contained in:
parent
f306eda703
commit
5cdaa43912
@ -121,6 +121,11 @@
|
||||
<artifactId>spring-rabbit</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.mobile</groupId>
|
||||
<artifactId>spring-mobile-device</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 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.mobile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver;
|
||||
import org.springframework.mobile.device.DeviceResolver;
|
||||
import org.springframework.mobile.device.DeviceResolverHandlerInterceptor;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Mobile's
|
||||
* {@link DeviceResolver}.
|
||||
*
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ DeviceResolverHandlerInterceptor.class,
|
||||
DeviceHandlerMethodArgumentResolver.class })
|
||||
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
|
||||
public class DeviceResolverAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication
|
||||
protected static class DeviceResolverAutoConfigurationAdapter extends
|
||||
WebMvcConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(DeviceResolverHandlerInterceptor.class)
|
||||
public DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor() {
|
||||
return new DeviceResolverHandlerInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DeviceHandlerMethodArgumentResolver deviceHandlerMethodArgumentResolver() {
|
||||
return new DeviceHandlerMethodArgumentResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(deviceResolverHandlerInterceptor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(
|
||||
List<HandlerMethodArgumentResolver> argumentResolvers) {
|
||||
argumentResolvers.add(deviceHandlerMethodArgumentResolver());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,7 @@ org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
||||
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 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.mobile;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver;
|
||||
import org.springframework.mobile.device.DeviceResolverHandlerInterceptor;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
/**
|
||||
* Tests for {@link DeviceResolverAutoConfiguration}.
|
||||
*
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
public class DeviceResolverAutoConfigurationTests {
|
||||
|
||||
private static final MockEmbeddedServletContainerFactory containerFactory = new MockEmbeddedServletContainerFactory();
|
||||
|
||||
private AnnotationConfigWebApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceResolverHandlerInterceptorCreated() throws Exception {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(DeviceResolverAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertNotNull(this.context.getBean(DeviceResolverHandlerInterceptor.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceHandlerMethodArgumentResolverCreated() throws Exception {
|
||||
this.context = new AnnotationConfigWebApplicationContext();
|
||||
this.context.register(DeviceResolverAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertNotNull(this.context.getBean(DeviceHandlerMethodArgumentResolver.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void deviceResolverHandlerInterceptorRegistered() throws Exception {
|
||||
AnnotationConfigEmbeddedWebApplicationContext context = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
context.register(Config.class, WebMvcAutoConfiguration.class,
|
||||
DeviceResolverAutoConfiguration.class);
|
||||
context.refresh();
|
||||
RequestMappingHandlerMapping mapping = (RequestMappingHandlerMapping) context
|
||||
.getBean("requestMappingHandlerMapping");
|
||||
Field interceptorsField = ReflectionUtils.findField(
|
||||
RequestMappingHandlerMapping.class, "interceptors");
|
||||
interceptorsField.setAccessible(true);
|
||||
List<Object> interceptors = (List<Object>) ReflectionUtils.getField(
|
||||
interceptorsField, mapping);
|
||||
context.close();
|
||||
for (Object o : interceptors) {
|
||||
if (o instanceof DeviceResolverHandlerInterceptor) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
fail("DeviceResolverHandlerInterceptor was not registered.");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class Config {
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerFactory containerFactory() {
|
||||
return containerFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerCustomizerBeanPostProcessor embeddedServletContainerCustomizerBeanPostProcessor() {
|
||||
return new EmbeddedServletContainerCustomizerBeanPostProcessor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
21
spring-boot-cli/samples/device.groovy
Normal file
21
spring-boot-cli/samples/device.groovy
Normal file
@ -0,0 +1,21 @@
|
||||
package org.test
|
||||
|
||||
@Controller
|
||||
@EnableDeviceResolver
|
||||
class Example {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
public String helloWorld(Device device) {
|
||||
if (device.isNormal()) {
|
||||
return "Hello Normal Device!"
|
||||
} else if (device.isMobile()) {
|
||||
return "Hello Mobile Device!"
|
||||
} else if (device.isTablet()) {
|
||||
return "Hello Tablet Device!"
|
||||
} else {
|
||||
return "Hello Unknown Device!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 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.cli.compiler.autoconfigure;
|
||||
|
||||
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 org.codehaus.groovy.ast.ClassNode;
|
||||
import org.codehaus.groovy.control.CompilationFailedException;
|
||||
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||
import org.springframework.boot.cli.compiler.AstUtils;
|
||||
import org.springframework.boot.cli.compiler.CompilerAutoConfiguration;
|
||||
import org.springframework.boot.cli.compiler.DependencyCustomizer;
|
||||
|
||||
/**
|
||||
* {@link CompilerAutoConfiguration} for Spring Mobile.
|
||||
*
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
public class SpringMobileCompilerAutoConfiguration extends CompilerAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public boolean matches(ClassNode classNode) {
|
||||
return AstUtils.hasAtLeastOneAnnotation(classNode, "EnableDeviceResolver");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyDependencies(DependencyCustomizer dependencies)
|
||||
throws CompilationFailedException {
|
||||
dependencies.add("org.springframework.mobile", "spring-mobile-device",
|
||||
dependencies.getProperty("spring-mobile.version"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyImports(ImportCustomizer imports) throws CompilationFailedException {
|
||||
imports.addStarImports("org.springframework.mobile.device");
|
||||
imports.addImports(EnableDeviceResolver.class.getCanonicalName());
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface EnableDeviceResolver {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -10,3 +10,4 @@ org.springframework.boot.cli.compiler.autoconfigure.SpockCompilerAutoConfigurati
|
||||
org.springframework.boot.cli.compiler.autoconfigure.TransactionManagementCompilerAutoConfiguration
|
||||
org.springframework.boot.cli.compiler.autoconfigure.SpringIntegrationCompilerAutoConfiguration
|
||||
org.springframework.boot.cli.compiler.autoconfigure.SpringSecurityCompilerAutoConfiguration
|
||||
org.springframework.boot.cli.compiler.autoconfigure.SpringMobileCompilerAutoConfiguration
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.boot.cli;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.Callable;
|
||||
@ -34,14 +37,12 @@ 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;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Integration tests to exercise the samples.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Greg Turnquist
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
public class SampleIntegrationTests {
|
||||
|
||||
@ -214,4 +215,12 @@ public class SampleIntegrationTests {
|
||||
output.contains("Received Greetings from Spring Boot via RabbitMQ"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deviceSample() throws Exception {
|
||||
start("samples/device.groovy");
|
||||
String result = FileUtil.readEntirely(new URL("http://localhost:8080")
|
||||
.openStream());
|
||||
assertEquals("Hello Normal Device!", result);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
<spring-data-jpa.version>1.4.1.RELEASE</spring-data-jpa.version>
|
||||
<spring-data-mongo.version>1.3.1.RELEASE</spring-data-mongo.version>
|
||||
<spring-rabbit.version>1.2.0.RELEASE</spring-rabbit.version>
|
||||
<spring-mobile.version>1.1.0.RELEASE</spring-mobile.version>
|
||||
<thymeleaf.version>2.0.16</thymeleaf.version>
|
||||
<thymeleaf-extras-springsecurity3.version>2.0.0</thymeleaf-extras-springsecurity3.version>
|
||||
<thymeleaf-layout-dialect.version>1.1.1</thymeleaf-layout-dialect.version>
|
||||
@ -439,6 +440,11 @@
|
||||
<artifactId>spring-rabbit</artifactId>
|
||||
<version>${spring-rabbit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.mobile</groupId>
|
||||
<artifactId>spring-mobile-device</artifactId>
|
||||
<version>${spring-mobile.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
|
Loading…
Reference in New Issue
Block a user