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

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

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

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

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

[java] view
plain
copy

  1. public class LiteDeviceResolver implements DeviceResolver {
  2. private final List<String> mobileUserAgentPrefixes = new ArrayList<String>();
  3. private final List<String> mobileUserAgentKeywords = new ArrayList<String>();
  4. private final List<String> tabletUserAgentKeywords = new ArrayList<String>();
  5. private final List<String> normalUserAgentKeywords = new ArrayList<String>();
  6. public LiteDeviceResolver() {
  7. init();
  8. }
  9. public LiteDeviceResolver(List<String> normalUserAgentKeywords) {
  10. init();
  11. this.normalUserAgentKeywords.addAll(normalUserAgentKeywords);
  12. }
  13. public Device resolveDevice(HttpServletRequest request) {
  14. String userAgent = request.getHeader("User-Agent");
  15. // UserAgent keyword detection of Normal devices
  16. if (userAgent != null) {
  17. userAgent = userAgent.toLowerCase();
  18. for (String keyword : normalUserAgentKeywords) {
  19. if (userAgent.contains(keyword)) {
  20. return resolveFallback(request);
  21. }
  22. }
  23. }
  24. // UAProf detection
  25. if (request.getHeader("x-wap-profile") != null || request.getHeader("Profile") != null) {
  26. return LiteDevice.MOBILE_INSTANCE;
  27. }
  28. // User-Agent prefix detection
  29. if (userAgent != null && userAgent.length() >= 4) {
  30. String prefix = userAgent.substring(0, 4).toLowerCase();
  31. if (mobileUserAgentPrefixes.contains(prefix)) {
  32. return LiteDevice.MOBILE_INSTANCE;
  33. }
  34. }
  35. // Accept-header based detection
  36. String accept = request.getHeader("Accept");
  37. if (accept != null && accept.contains("wap")) {
  38. return LiteDevice.MOBILE_INSTANCE;
  39. }
  40. // UserAgent keyword detection for Mobile and Tablet devices
  41. if (userAgent != null) {
  42. userAgent = userAgent.toLowerCase();
  43. // Android special case
  44. if (userAgent.contains("android") && !userAgent.contains("mobile")) {
  45. return LiteDevice.TABLET_INSTANCE;
  46. }
  47. // Kindle Fire special case
  48. if (userAgent.contains("silk") && !userAgent.contains("mobile")) {
  49. return LiteDevice.TABLET_INSTANCE;
  50. }
  51. for (String keyword : tabletUserAgentKeywords) {
  52. if (userAgent.contains(keyword)) {
  53. return LiteDevice.TABLET_INSTANCE;
  54. }
  55. }
  56. for (String keyword : mobileUserAgentKeywords) {
  57. if (userAgent.contains(keyword)) {
  58. return LiteDevice.MOBILE_INSTANCE;
  59. }
  60. }
  61. }
  62. // OperaMini special case
  63. @SuppressWarnings("rawtypes")
  64. Enumeration headers = request.getHeaderNames();
  65. while (headers.hasMoreElements()) {
  66. String header = (String) headers.nextElement();
  67. if (header.contains("OperaMini")) {
  68. return LiteDevice.MOBILE_INSTANCE;
  69. }
  70. }
  71. return resolveFallback(request);
  72. }
  73. // subclassing hooks
  74. /**
  75. * List of user agent prefixes that identify mobile devices.
  76. * Used primarily to match by operator or handset manufacturer.
  77. */
  78. protected List<String> getMobileUserAgentPrefixes() {
  79. return mobileUserAgentPrefixes;
  80. }
  81. /**
  82. * List of user agent keywords that identify mobile devices.
  83. * Used primarily to match by mobile platform or operating system.
  84. */
  85. protected List<String> getMobileUserAgentKeywords() {
  86. return mobileUserAgentKeywords;
  87. }
  88. /**
  89. * List of user agent keywords that identify tablet devices.
  90. * Used primarily to match by tablet platform or operating system.
  91. */
  92. protected List<String> getTabletUserAgentKeywords() {
  93. return tabletUserAgentKeywords;
  94. }
  95. /**
  96. * List of user agent keywords that identify normal devices.
  97. * Any items in this list take precedence over the mobile and
  98. * tablet user agent keywords, effectively overriding those.
  99. */
  100. protected List<String> getNormalUserAgentKeywords() {
  101. return normalUserAgentKeywords;
  102. }
  103. /**
  104. * Initialize this device resolver implementation.
  105. * Registers the known set of device signature strings.
  106. * Subclasses may override to register additional strings.
  107. */
  108. protected void init() {
  109. getMobileUserAgentPrefixes().addAll(Arrays.asList(KNOWN_MOBILE_USER_AGENT_PREFIXES));
  110. getMobileUserAgentKeywords().addAll(Arrays.asList(KNOWN_MOBILE_USER_AGENT_KEYWORDS));
  111. getTabletUserAgentKeywords().addAll(Arrays.asList(KNOWN_TABLET_USER_AGENT_KEYWORDS));
  112. }
  113. /**
  114. * Fallback called if no mobile device is matched by this resolver.
  115. * The default implementation of this method returns a "normal" {@link Device} that is neither mobile or a tablet.
  116. * Subclasses may override to try additional mobile or tablet device matching before falling back to a "normal" device.
  117. */
  118. protected Device resolveFallback(HttpServletRequest request) {
  119. return LiteDevice.NORMAL_INSTANCE;
  120. }
  121. // internal helpers
  122. private static final String[] KNOWN_MOBILE_USER_AGENT_PREFIXES = new String[] { "w3c ", "w3c-", "acs-", "alav",
  123. "alca", "amoi", "audi", "avan", "benq", "bird", "blac", "blaz", "brew", "cell", "cldc", "cmd-", "dang",
  124. "doco", "eric", "hipt", "htc_", "inno", "ipaq", "ipod", "jigs", "kddi", "keji", "leno", "lg-c", "lg-d",
  125. "lg-g", "lge-", "lg/u", "maui", "maxo", "midp", "mits", "mmef", "mobi", "mot-", "moto", "mwbp", "nec-",
  126. "newt", "noki", "palm", "pana", "pant", "phil", "play", "port", "prox", "qwap", "sage", "sams", "sany",
  127. "sch-", "sec-", "send", "seri", "sgh-", "shar", "sie-", "siem", "smal", "smar", "sony", "sph-", "symb",
  128. "t-mo", "teli", "tim-", "tosh", "tsm-", "upg1", "upsi", "vk-v", "voda", "wap-", "wapa", "wapi", "wapp",
  129. "wapr", "webc", "winw", "winw", "xda ", "xda-" };
  130. private static final String[] KNOWN_MOBILE_USER_AGENT_KEYWORDS = new String[] { "blackberry", "webos", "ipod",
  131. "lge vx", "midp", "maemo", "mmp", "mobile", "netfront", "hiptop", "nintendo DS", "novarra", "openweb",
  132. "opera mobi", "opera mini", "palm", "psp", "phone", "smartphone", "symbian", "up.browser", "up.link",
  133. "wap", "windows ce" };
  134. private static final String[] KNOWN_TABLET_USER_AGENT_KEYWORDS = new String[] { "ipad", "playbook", "hp-tablet",
  135. "kindle" };
  136. }

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

  1. Java判断访问设备为手机、微信、PC工具类

    package com.lwj.util; import javax.servlet.http.HttpServletRequest; /** * 判断访问设备为PC或者手机--工具类 * * @de ...

  2. JS判断访问设备、客户端操作系统类型

    先给出一个实例:判断windows.linux.android 复制以下代码另存为html文件即可. <html> <head> <title>判断操作系统< ...

  3. [转]JS判断访问设备、客户端操作系统类型

    本文转自:http://www.cnblogs.com/duanguyuan/p/3534470.html 先给出一个实例:判断windows.linux.android 复制以下代码另存为html文 ...

  4. JS判断访问设备(userAgent)加载不同页面 JS判断客户端操作系统类型(platform)

    //平台.设备和操作系统 var system ={ win : false, mac : false, xll : false }; //检测平台 var p = navigator.platfor ...

  5. PHP和js判断访问设备是否是微信浏览器实例

    PHP和js判断访问设备是否是微信浏览器实例,代码非常精简,适合新手学习. js判断是否是微信浏览器: 1 function is_weixin() { 2 var ua = window.navig ...

  6. 判断访问浏览器客户端类型(pc,mac,ipad,iphone,android)

    <script type="text/javascript"> //平台.设备和操作系统 var system = { win: false, mac: false, ...

  7. JS判断访问设备是移动设备还是pc

    <scripttype="text/javascript"> function browserRedirect() { var sUserAgent= navigato ...

  8. 如何判断 ios设备的类型(iphone,ipod,ipad)

    功能函数: -(bool)checkDevice:(NSString*)name { NSString* deviceType = [UIDevice currentDevice].model; NS ...

  9. Spring Mobile——探测客户端设备和系统

    Spring Mobile--探测客户端设备和系统 今天闲来无事,浏览Spring的官方网站,发现了Spring Mobile项目,之前也看到过,还以为是针对手机端的项目,并没有细看.今天仔细看了一下 ...

随机推荐

  1. JavaScript 高级程序设计(第3版)笔记——chapter3:基本概念(函数部分)

    3.7函数 3.7.1 理解参数 ECMAScript 函数不介意传递进来多个参数,也不在乎传递进来的参数是什么数据类型.因为在 ECMAScript 中的参数在内部是用一个数组来表示的.在函数体内可 ...

  2. BZOJ 2654: tree( 二分 + MST )

    我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下. 不过这道题有点小坑... ------------------------------------------------- ...

  3. 安装帝国CMS遇到“修改php.ini,将:short_open_tag 设为 On”的解决方法+“建立目录不成功!请检查目录权限”问题

    想用安装个帝国CMS来做个网站,于是下载了程序,上传到服务器上,但是在输入安装路径的时候却给出了如下图示: 您的PHP配置文件php.ini配置有问题,请按下面操作即可解决: 1.修改php.ini, ...

  4. Ubantu指令收藏

    Ubuntu常用命令大全,学习ubuntn系统的朋友可以收藏下,用ctrl+F查找即可   一.文件/文件夹管理 ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件) ...

  5. 四级流水线的8bit加法器

    以流水线实现8bit 加法器. //date : 2013/8/23 //designer :pengxiaoen //function : module pipeline ( clock ,rese ...

  6. 最新的QT git代码到code.qt.io/cgit,还有planet.qt.io有许多博客

    http://code.qt.io/cgit/ http://planet.qt.io/

  7. 基于visual Studio2013解决算法导论之012计数排序

     题目 计数排序 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #in ...

  8. 【行业干货】2013中国零售商排名 - 课程公告板 - 京东内部论坛 - Powered by Discuz!

    [行业干货]2013中国零售商排名 - 课程公告板 - 京东内部论坛 - Powered by Discuz! [行业干货]2013中国零售商排名 [复制链接]     bjpanzhoulan   ...

  9. matlab绘图方法汇总

    Matlab画图 强大的画图功能是Matlab的特点之中的一个,Matlab提供了一系列的画图函数,用户不须要过多的考虑画图的细节,仅仅须要给出一些基本參数就能得到所需图形,这类函数称为高层画图函数. ...

  10. Android 属性动画 源码解析 深入了解其内部实现

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42056859,本文出自:[张鸿洋的博客] 我参加了博客之星评选,如果你喜欢我的博 ...