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" };

}
时间: 2024-09-19 09:23:43

Spring Mobile是如何判断访问设备的类型的的相关文章

JS判断移动端访问设备并加载对应CSS样式_javascript技巧

JS判断不同web访问环境,主要针对移动设备,提供相对应的解析方案(判断设备代码直接copy腾讯网的) 复制代码 代码如下: // 判断是否为移动端运行环境 if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-

javascript判断移动端访问设备并解析对应CSS的方法_javascript技巧

本文实例讲述了javascript判断移动端访问设备并解析对应CSS的方法.分享给大家供大家参考.具体分析如下: javascript判断不同web访问环境,主要针对移动设备,提供相对应的解析方案(判断设备代码直接copy腾讯网的): 复制代码 代码如下: // 判断是否为移动端运行环境  if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel

JSP判断移动设备的正则

 天猫php判断移动设备的正则(个人猜测),觉得很好用,于是就决定移植到JSP里面,大家可以参考下 看到了一篇很好的文章, <在天猫,前端做什么?>,里面有天猫php判断移动设备的正则(个人猜测),觉得很好用,于是就决定移植到JSP里面.    jsp文件名为 index.jsp,其实也可以使用过滤器来进行拦截,然后跳转到其他域名去.    完整代码如下:  代码如下: <%@page import="java.util.regex.Matcher"%>  &l

怎么判断访问端是电脑还是手机?

  网上现在有三种观点, 一种是基于浏览器发送的 User-Agent, 但明显这种方法是行不通的, 虽然有人列出了大多数的手机发送的User-Agent, 但依然会有很多手机无法识别, 甚至有些手机浏览器不发送User-Agent, 而且也不能保证以后就不会出新牌子. 下面是一个php的例子, 看过之后你就会知道有多么不可靠. 1. function is_wap(){ 2. $ua = strtolower($_SERVER['HTTP_USER_AGENT']); 3. $uachar =

用JS判断访问终端

 <script type="text/javascript"> //判断访问终端 var browser={     versions:function(){         var u = navigator.userAgent, app = navigator.appVersion;         return {             trident: u.indexOf('Trident') > -1, //IE内核             presto

【ASP.NET】判断访问网站的客户端是PC还是手机

原文:[ASP.NET]判断访问网站的客户端是PC还是手机 主要就是通过客户端传递的User-agent来判断访问网站的客户端是PC还是手机,.NET中就是Request.ServerVariables["HTTP_USER_AGENT"]. 比如正常pc是: Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0 常用手机的是: Nokia5320的是: Nokia 5320/UCWEB7.0.1.34/28

JSP判断移动设备的正则_JSP编程

看到了一篇很好的文章, <在天猫,前端做什么?>,里面有天猫php判断移动设备的正则(个人猜测),觉得很好用,于是就决定移植到JSP里面. jsp文件名为 index.jsp,其实也可以使用过滤器来进行拦截,然后跳转到其他域名去. 完整代码如下: 复制代码 代码如下: <%@page import="java.util.regex.Matcher"%> <%@page import="java.util.regex.Pattern"%&

判断访问是否来自搜索引擎的ASP函数

判断访问是否来自搜索引擎的函数,有兴趣的可以试试! <!--'检查当前用户是否是蜘蛛人 Function check(user_agent)     allow_agent=split("Baiduspider,Scooter,ia_archiver,Googlebot,FAST-WebCrawler,MSNBOT,Slurp",",")     check_agent=false     For agenti=lbound(allow_agent) to u

内外网同时访问问题:用JS判断访问计算机IP

js|访问|问题 我在内网搭了两个服务器,一个数据库服务器,一个Web服务器.并且让网管影射个外网IP给Web服务器,使得外网内网可以同时访问.但这样产生了个问题,Web服务器取数据是用内网的相对地址,这样外网访问时就得不到数据,只能显示框架.要是把数据库服务器也映射了的话,那么内网就不能访问了,这样我就没办法调试了.如果把两个服务器合为一个,那么运行的速度就会受到影响,而现在老板也不想再往里投钱,毕竟只是一个演示.而把两台机子搬到实验室的网络机房直接接到外网上也可以解决,但是网络机房是封闭的,