Spring Boot + Spring Mobile Serve Content Based on Device
This tutorial shows how to use Spring Boot and Spring Mobile to serve content based on device type. We distinguish mobile
, tablet
and normal
devices.
Project Structure
Let’s start by looking at the project structure.
Maven Dependencies
We use Apache Maven to manage our project dependencies. Make sure the following dependencies reside on the class-path.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.memorynotfound.spring.mobile</groupId>
<artifactId>device-resolution</artifactId>
<version>1.0.0-SNAPSHOT</version>
<url>http://memorynotfound.com</url>
<name>Spring Mobile - ${project.artifactId}</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mobile</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Boot
We use spring boot to bootstrap our application. The @SpringBootApplication
triggers the EnableAutoConfiguration
and ComponentScan
. This is a convenience annotation that is equivalent to declaring @Configuration
, @EnableAutoConfiguration
and @Configuration
.
package com.memorynotfound.mobile;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String... args) {
SpringApplication.run(Application.class, args);
}
}
Configure Spring Mobile
We use the application.yml
file, located in the src/main/resources
folder to configure spring-boot and spring-mobile.
spring.mobile.devicedelegatingviewresolver.enable-fallback
– specifies support for fallback resolution.spring.mobile.devicedelegatingviewresolver.enable
– enables/disables device view resolver.spring.mobile.devicedelegatingviewresolver.mobile-prefix
– prefix that gets prepended to view names for mobile devices.spring.mobile.devicedelegatingviewresolver.mobile-suffix
– suffix that gets appended to view names for mobile devices.spring.mobile.devicedelegatingviewresolver.normal-prefix
– prefix that gets prepended to view names for normal devices.spring.mobile.devicedelegatingviewresolver.normal-suffix
– suffix that gets appended to view names for normal devices.spring.mobile.devicedelegatingviewresolver.tablet-prefix
– prefix that gets prepended to view names for tablet devices.spring.mobile.devicedelegatingviewresolver.tablet-suffix
– suffix that gets appended to view names for tablet devices.
Internally, LiteDeviceDelegatingViewResolver
makes use of the Device
resolved by DeviceResolverHandlerInterceptor
to determine whether to return normal
, mobile
or tablet
specific views for a request. in this case, LiteDeviceDelegatingViewResolver
is configured to delegate requests to ThymeleafViewResolver
. ThymeleafViewResolver
is a type of ViewResolver
, which is used by Spring to perform server-side rendering of HTM.
server:
port: ${PORT:8081}
spring:
mobile:
devicedelegatingviewresolver:
enabled: true
enable-fallback: true
mobile-prefix: /mobile/
# mobile-suffix: .mob
normal-prefix: /
# normal-suffix: .nor
tablet-prefix: /tablet/
# tablet-suffix: .tab
Device Resolution
We can inject a Device
in our controller. We can inspect this object to learn which device is accessing our website.
package com.memorynotfound.mobile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
public class GreetingController {
private static final Logger log = LoggerFactory.getLogger(GreetingController.class);
@RequestMapping("/")
public String greeting(Device device, HttpServletRequest request) {
Device deviceFromRequest = DeviceUtils.getCurrentDevice(request);
if (device.isMobile()) {
log.info("Hello mobile user!");
} else if (device.isTablet()) {
log.info("Hello tablet user!");
} else {
log.info("Hello desktop user!");
}
log.info("device: " + device);
log.info("device form request: " + deviceFromRequest);
log.info("device platform: " + device.getDevicePlatform());
return "greeting";
}
}
Different Devices Thymeleaf Templates
src/main/resources/templates/greeting.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Boot + Spring Mobile Serving Content Based on Device</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1 th:text="'Hello standard view!'" />
</body>
</html>
src/main/resources/templates/mobile/greeting.html
<h1 th:text="'Hello mobile view!'" />
src/main/resources/templates/tablet/greeting.html
<h1 th:text="'Hello tablet view!'" />
Demo
When we access http://localhost:8081/
on a mobile device.
When we access http://localhost:8081/
on a tablet device.
When we access http://localhost:8081/
on a normal device.
Console Output
The example prints the following output to the console.
Hello desktop user!
device: [LiteDevice type=NORMAL]
device form request: [LiteDevice type=NORMAL]
device platform: UNKNOWN
Hello tablet user!
device: [LiteDevice type=TABLET]
device form request: [LiteDevice type=TABLET]
device platform: IOS
Hello mobile user!
device: [LiteDevice type=MOBILE]
device form request: [LiteDevice type=MOBILE]
device platform: IOS
:)