Spring Mobile是如何判断访问设备的类型的-阿里云开发者社区

开发者社区> hengyunabc> 正文

Spring Mobile是如何判断访问设备的类型的

简介:
+关注继续查看

Spring最近换域名了,去转转,发现了一个有意思的项目:spring mobile。

http://projects.spring.io/spring-mobile/

这个项目有很多实用的功能,如识别访问我们网站的设备是什么类型的(手机,平板,PC),据域名或者url来切换不同访问内容,据不同的访问设备转到不同的view中。


识别访问设备类型的核心代码在org.springframework.mobile.device.LiteDeviceResolver 类中,这个类实际上根据http请求头部的User-Agent的内容来判断设备到底是哪种类型的。

可以看到,这个类实际上是很简单的。不过字符串的匹配算法可能可以优化下。

public class LiteDeviceResolver implements DeviceResolver {

	private final List<String> mobileUserAgentPrefixes = new ArrayList<String>();

	private final List<String> mobileUserAgentKeywords = new ArrayList<String>();

	private final List<String> tabletUserAgentKeywords = new ArrayList<String>();

	private final List<String> normalUserAgentKeywords = new ArrayList<String>();

	public LiteDeviceResolver() {
		init();
	}

	public LiteDeviceResolver(List<String> normalUserAgentKeywords) {
		init();
		this.normalUserAgentKeywords.addAll(normalUserAgentKeywords);
	}

	public Device resolveDevice(HttpServletRequest request) {
		String userAgent = request.getHeader("User-Agent");
		// UserAgent keyword detection of Normal devices
		if (userAgent != null) {
			userAgent = userAgent.toLowerCase();
			for (String keyword : normalUserAgentKeywords) {
				if (userAgent.contains(keyword)) {
					return resolveFallback(request);
				}
			}
		}
		// UAProf detection
		if (request.getHeader("x-wap-profile") != null || request.getHeader("Profile") != null) {
			return LiteDevice.MOBILE_INSTANCE;
		}
		// User-Agent prefix detection
		if (userAgent != null && userAgent.length() >= 4) {
			String prefix = userAgent.substring(0, 4).toLowerCase();
			if (mobileUserAgentPrefixes.contains(prefix)) {
				return LiteDevice.MOBILE_INSTANCE;
			}
		}
		// Accept-header based detection
		String accept = request.getHeader("Accept");
		if (accept != null && accept.contains("wap")) {
			return LiteDevice.MOBILE_INSTANCE;
		}
		// UserAgent keyword detection for Mobile and Tablet devices
		if (userAgent != null) {
			userAgent = userAgent.toLowerCase();
			// Android special case 
			if (userAgent.contains("android") && !userAgent.contains("mobile")) {
				return LiteDevice.TABLET_INSTANCE;
			}
			// Kindle Fire special case 
			if (userAgent.contains("silk") && !userAgent.contains("mobile")) {
				return LiteDevice.TABLET_INSTANCE;
			}
			for (String keyword : tabletUserAgentKeywords) {
				if (userAgent.contains(keyword)) {
					return LiteDevice.TABLET_INSTANCE;
				}
			}
			for (String keyword : mobileUserAgentKeywords) {
				if (userAgent.contains(keyword)) {
					return LiteDevice.MOBILE_INSTANCE;
				}
			}
		}
		// OperaMini special case
		@SuppressWarnings("rawtypes")
		Enumeration headers = request.getHeaderNames();
		while (headers.hasMoreElements()) {
			String header = (String) headers.nextElement();
			if (header.contains("OperaMini")) {
				return LiteDevice.MOBILE_INSTANCE;
			}
		}
		return resolveFallback(request);
	}

	// subclassing hooks

	/**
	 * List of user agent prefixes that identify mobile devices.
	 * Used primarily to match by operator or handset manufacturer.
	 */
	protected List<String> getMobileUserAgentPrefixes() {
		return mobileUserAgentPrefixes;
	}

	/**
	 * List of user agent keywords that identify mobile devices.
	 * Used primarily to match by mobile platform or operating system.
	 */
	protected List<String> getMobileUserAgentKeywords() {
		return mobileUserAgentKeywords;
	}

	/**
	 * List of user agent keywords that identify tablet devices.
	 * Used primarily to match by tablet platform or operating system.
	 */
	protected List<String> getTabletUserAgentKeywords() {
		return tabletUserAgentKeywords;
	}

	/**
	 * List of user agent keywords that identify normal devices.
	 * Any items in this list take precedence over the mobile and
	 * tablet user agent keywords, effectively overriding those. 
	 */
	protected List<String> getNormalUserAgentKeywords() {
		return normalUserAgentKeywords;
	}

	/**
	 * Initialize this device resolver implementation.
	 * Registers the known set of device signature strings.
	 * Subclasses may override to register additional strings.
	 */
	protected void init() {
		getMobileUserAgentPrefixes().addAll(Arrays.asList(KNOWN_MOBILE_USER_AGENT_PREFIXES));
		getMobileUserAgentKeywords().addAll(Arrays.asList(KNOWN_MOBILE_USER_AGENT_KEYWORDS));
		getTabletUserAgentKeywords().addAll(Arrays.asList(KNOWN_TABLET_USER_AGENT_KEYWORDS));
	}

	/**
	 * Fallback called if no mobile device is matched by this resolver.
	 * The default implementation of this method returns a "normal" {@link Device} that is neither mobile or a tablet.
	 * Subclasses may override to try additional mobile or tablet device matching before falling back to a "normal" device.
	 */
	protected Device resolveFallback(HttpServletRequest request) {
		return LiteDevice.NORMAL_INSTANCE;
	}

	// internal helpers

	private static final String[] KNOWN_MOBILE_USER_AGENT_PREFIXES = new String[] { "w3c ", "w3c-", "acs-", "alav",
			"alca", "amoi", "audi", "avan", "benq", "bird", "blac", "blaz", "brew", "cell", "cldc", "cmd-", "dang",
			"doco", "eric", "hipt", "htc_", "inno", "ipaq", "ipod", "jigs", "kddi", "keji", "leno", "lg-c", "lg-d",
			"lg-g", "lge-", "lg/u", "maui", "maxo", "midp", "mits", "mmef", "mobi", "mot-", "moto", "mwbp", "nec-",
			"newt", "noki", "palm", "pana", "pant", "phil", "play", "port", "prox", "qwap", "sage", "sams", "sany",
			"sch-", "sec-", "send", "seri", "sgh-", "shar", "sie-", "siem", "smal", "smar", "sony", "sph-", "symb",
			"t-mo", "teli", "tim-", "tosh", "tsm-", "upg1", "upsi", "vk-v", "voda", "wap-", "wapa", "wapi", "wapp",
			"wapr", "webc", "winw", "winw", "xda ", "xda-" };

	private static final String[] KNOWN_MOBILE_USER_AGENT_KEYWORDS = new String[] { "blackberry", "webos", "ipod",
			"lge vx", "midp", "maemo", "mmp", "mobile", "netfront", "hiptop", "nintendo DS", "novarra", "openweb",
			"opera mobi", "opera mini", "palm", "psp", "phone", "smartphone", "symbian", "up.browser", "up.link",
			"wap", "windows ce" };

	private static final String[] KNOWN_TABLET_USER_AGENT_KEYWORDS = new String[] { "ipad", "playbook", "hp-tablet",
			"kindle" };

}



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
SpringBoot-18-之AOP+log4j 记录访问请求信息
org.springframework.boot spring-boot-starter-aop log4j log4j 1.
1054 0
Spring Boot入门(12)实现页面访问量统计功能
  在日常的网站使用中,经常会碰到页面的访问量(或者访问者人数)统计。那么,在Spring Boot中该如何实现这个功能呢?   我们的想法是比较简单的,那就是将访问量储存在某个地方,要用的时候取出来即可,储存的位置可选择数据库或者其他文件。
2630 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4483 0
SpringBoot-12-之Ajax跨域访问全解析
一.什么是跨域呢? 1.引入: 先讲个故事:从前一个叫8080的大佬和一个8081的大佬各占一方天地,还有一个叫浏览器的大佬和8080还有8081关系都不错。
1165 0
实战DeviceIoControl 之一:通过API访问设备驱动程序
<p>Q 在NT/2000/XP中,我想用VC编写应用程序访问硬件设备,如获取磁盘参数、读写绝对扇区数据、测试光驱实际速度等,该从哪里入手呢? </p> <p>A 在NT/2000/XP中,应用程序可以通过API函数DeviceIoControl来实现对设备的访问—获取信息,发送命令,交换数据等。利用该接口函数向指定的设备驱动发送正确的控制码及数据,然后分析它的响应,就可以达到我们的目的
2113 0
C# 访问USB(HID)设备
原文:C# 访问USB(HID)设备 二话不说,直接给代码,如果您真想做这方面的东西,还是稍微研究下,没有现成的好类用,就需要自己了解其原理 //引用空间using System;using System.
1651 0
SpringBoot实战(四)之使用JDBC和Spring访问数据库
这里演示的是h2databse示例,所以简单的介绍普及下h2database相关知识 H2数据库是一个开源的关系型数据库。 H2是一个嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2提供了一个十分方便的web控制台用于操作和管理数据库内容。
1702 0
+关注
hengyunabc
负责5K+应用,60K+机器的Spring Boot微服务技术落地,关注开发体验,微服务,APM,应用诊断,dubbo开源。Github: https://github.com/hengyunabc
106
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载