精通 Grails: Grails 与移动 Web

M 是新型的 WWW

全球的手机用户为 33 亿,并且呈上升趋势,而通过手机上网也越来越走俏。因此有开发移动 Web 的特殊需求。在本期的 精通 Grails中,Scott Davis 向您讲述了如何让 Grails 应用程序便于手机浏览。

Scott Davis, 主编, AboutGroovy.com

Scott DavisScott Davis 是国际知名作家、演讲家、软件开发人员。他出版的书籍有 Groovy Recipes: Greasing the Wheels of JavaGIS for Web Developers: Adding Where to Your ApplicationThe Google Maps APIJBoss At Work



2008 年 7 月 15 日

目前,几乎所有的网站都宣称 “ 使用 [Browser X] 提供最佳视图”。现代的 Ajax 库,比如 Prototype、Dojo 和 YUI,有效地缩小了 Firefox、Internet Explorer 和 Safari 之间的差距。但是使用 Nokia、Motorola 或者 Apple 手机的人可能不会喜欢浏览器的独立性。即使是最新的呼吁 “支持完整 HTML ” 的移动浏览器也可以从简单更改网络内容中获益。本文将向您展示如何优化 Grails 应用程序,使其适用于移动浏览器。

移动 Web 的使用率正在增长

据 Internet World Stats 称,目前 Internet 用户为 14 亿 —约为全球总人口的 20%(请参阅 参考资料)。在北美洲,有 3/4 的人都是使用移动互联网。

在全球 66 亿人口当中,就有一半的人拥有手机。在北美洲,手机与 Internet 的市场占有率几乎相等,但在其他的地方则有所不同。在香港,手机的市场占有率为 140%,而在欧盟的部分国家(立陶宛,意大利和卢森堡公国)其市场占有率已高达 150%。的确,在某些地方手机比人还要多。

IDG Communications 的 Colin Crawfordsays 说到了要点(参见 参考资料):“在接下来的几年里,手机会作为上网的主要设备而逐步取代个人电脑。现在,通过手机访问互联网的比例已达到 30%,而在某些国家(比如日本)这个比例已高达 70%”。

如果您还在疑虑为什么非要使网站便于移动浏览的话,看一看 移动 Web 的使用率正在增长 边栏里面的数字就会明白了。这份全球的统计数字确实让人过目难忘,但热衷移动 Web 源于我个人的兴趣。我在 2007 年春天买了一个 iPhone,那时它刚刚上市。从那以后,我就一直在寻找可以用它来浏览的网站。当然,我可以用它访问任何的网站(只要不是基于 Flash 或者 Java™applet 的网站,因为它不支持)。问题是,适合在分辨率为 800x600 (或更高)的显示器上显示的内容,在 3.5 英寸的屏幕上显示效果就没有那么好了。

我经常访问的那些带有 UI 的网站,因为它们符合我的手机的特定限制。我的手机会用 m代替普通站点中传统的 URL www,这就是一个很好的起点。http://m.cnn.com、http://m.yahoo.com 和 http://m.google.com 这样的页面就能在我的手机上显示。有些网站,比如 http://www.twitter.com,则会做出相应的调整,以输出合适的内容:在电脑上浏览,我可以获得全部功能;而在手机上浏览时,则删剪了一些内容,使它刚好适合我的屏幕。我将向您展示如何实现不改变 URL,但提供最佳 UI。

针对移动 Web 开发人员的技术

作为一个 Java 开发人员,我已经被 “只写一次,到处运行(Write Once,Run Anywhere)” 的承诺给宠坏了。我甚至从来没有考虑过优化 Java 应用程序使其适合某一特定的操作系统或硬件型号。但是如果是要开发移动 Web 的话,就应该熟悉三种支持不同型号移动设备的主要技术:

  • 无线标记语言(Wireless Markup Language 1.x,WML 1.x)
  • WML 2.x 或 Mobile Profile(XHTML-MP)
  • 针对 iPhone 的 HTML 标记

正如我展示的一样,您可以将 WML 和 XHTML-MP 标记与用 Grails 构建的 Groovy Server Pages(GSPs)结合起来,以生成便于移动的页面。此外,我还会向您展示如何修改 Grails 生成的 HTML,使页面在 iPhone 上显示得更好。

结合使用 WML 1.x 和 Grails

WML 是一种类似于 HTML 的标记语言,但它并不是真正的 HTML(WML 1.0 于 1998 年标准化。WML 1.3 为最新版本)。WML 并无法在 Web 浏览器中查看(至少不借助于仿真器是不行的),同样您也无法在 WML 浏览器中查看 HTML。手机供应商通常都会提供在后台实现 HTML 与 WML 之间相互转换的网关。

关于本系列

Grails 是一种新型 Web 开发框架,它将常见的 Spring 和 Hibernate 等 Java 技术与当前流行的实践(比如约定优于配置)相结合。在加入脚本语言的灵活性和动态性的同时,用 Groovy 编写的 Grails 可以无缝地集成遗留的 Java 代码。学习完 Grails 之后,您将改变看待 Web 开发的方式。

WML 通过无线访问协议(Wireless Access Protocol,WAP)传输,这和 HTML 通过 HTTP 传输很相似。WAPWML在临时对话中通常可以相互转换:手机说明书总是会夸耀该手机带有 WAP 浏览器,或者支持 WML 1.x(参阅 参考资料获得 WML 和 WAP 规范的官方链接)。

如果您针对的是 Research in Motion 的 BlackBerry 用户的话,就得提高关于 WML 的知识了。(BlackBerry 大约占了智能手机市场的 40%,iPhones 和 Windows®Mobile 居于第二和第三位)。虽然很多技术过硬的用户也可以下载真正的 Web 浏览器,比如 Opera Mini(参见 参考资料),但是 BlackBerry 智能手机还是配备了 WAP 浏览器。

继续设计旅行计划

如果您一直都在关注 精通 Grails系列文章的话,那么您可以修改已经熟悉的旅行计划应用程序,使它便于在手机上浏览。在旅行计划应用程序的 web-app 目录中创建一个文件,命名为 testwml.gsp,并输入清单 1 中的静态 WML:

清单 1. 静态 WML
 <% response.setContentType("text/vnd.wap.wml") %> 
 <?xml version="1.0"?> 
 <!DOCTYPE wml PUBLIC "-//PHONE.COM//DTD WML 1.1//EN"
   "http://www.phone.com/dtd/wml11.dtd" > 

 <wml> 
  <card id="f1" title="Flight 1"> 
    <p mode="wrap">From: DEN</p> 
    <p mode="wrap">To: ORD</p> 
    <p mode="wrap">UAL 1234</p> 
    <p mode="wrap">Jun 30, 10:30am</p> 
    <p> 
      <anchor>Next<go href="#f2"/></anchor> 
    </p>  
  </card> 

  <card id="f2" title="Flight 2"> 
    <p mode="wrap">From: ORD</p> 
    <p mode="wrap">To: DEN</p> 
    <p mode="wrap">UAL 9876</p> 
    <p mode="wrap">Jul 02, 1:15pm</p> 
    <p> 
      <anchor>Previous<go href="#f1"/></anchor> 
    </p>  
  </card> 
 </wml>

您用手机访问 http://www.davisworld.org/testwml.gsp 同样可以看到这个页面。您可能习惯于在 GSP 中查看 HTML。但在这里使用的是 WML。

当从 GSP 中发送出 WML 时,切记要将默认的 MIME 类型 text/html替换为 text/vnd.wap.wml,如清单 1 中的第一行所示。如果直接提供静态 WML,那么只需赋予文件一个 WML 扩展名,而不是 GSP 扩展名。大多数 Web 服务器会在这之后自动返回一个正确的 MIME 类型,无需调用 response.setContentType。在 $TOMCAT_HOME/conf/web.xml 中,您会发现 MIME 针对 WML 文件的映射已经就位。如果您使用的是 Apache HTTPD 的话,那么您可以在 $APACHE_HOME/conf/mime.types 文件中找到类似的 WML 文件的映射。清单 2 向展示了 Tomcat 的 MIME 类型映射:

清单 2. 在 Tomcat 中设置 MIME 类型
 <mime-mapping> 
  <!-- WML Source --> 
  <extension>wml</extension> 
  <mime-type>text/vnd.wap.wml</mime-type> 
 </mime-mapping>

回过头来在看一下 清单 1,接下来需要注意的是 DOCTYPE。包含文档类型定义(Document Type Definition,DTD)语句可以帮助将 WML 文档识别为 testwml.gsp。

注意该文件并未打包在常见的 <html>标记中。它的开头和结尾为 <wml>。您可能还注意到 清单 1中缺少 <head><body>部分。每一个 WML 页面为一个 card,拥有一个独立的 id属性和便于用户使用的 title属性。

通常情况下,在一个单一文件中可以下载多个页面 / 卡片。早期的手机的数据通道非常狭窄,而这种方法刚好就缓和了这些设备及其网络的局限性。一次下载得越多,手机与服务器之间的数据转就越少。因为一次只能查看一个页面,这样就可以有效地提前获取其余的页面。对于这种情况,导航只发生在客户端。

HTML 开发人员一定要熟悉 <p>标记。WML <anchor>标记在本质上与 HTML <a>标记是类似的,即使它们在语法上有所不同(参阅 参考资料了解更多关于 WML 的信息)。

下面是 WML 的一个小技巧。由于处理的是专用于手机的内容,因此可以创建一个超链接,用户一旦选定链接,就可以拨出电话。清单 3 的中例子可以拨出电话号码 303-555-1212 :

清单 3. WML 拨号链接
 <do type="accept"> 
 <go href="wtai://wp/mc;3035551212"/> 
 </do>

注意该链接使用的协议并非常见的 http://—而是 wtai://,这是无线电话应用程序界面(Wireless Telephony Applications Interface)的缩写。

WML 仿真器

要使这个页面在个人电脑上显示,则需要一个 WAP 仿真器(参阅 参考资料,查看文中提到的所有仿真器的链接)。访问 dotMobi 仿真器,它是一个 Java applet。输入 URL davisworld.org/testwml.gsp(注意 http:// 前缀已提供在输入框的左侧),您将看到类似于图 1 的内容:

图 1. 仿真 WAP 页面
仿真 WAP 页面

注意 dotMobi 仿真器有两种不同的皮肤,它不仅代表着不同设备的外观和感觉,还代表设备的不同功能。如果对仿真某个设备感兴趣的话,它的硬件制造商通常会提供一个开发者网站,您可以从哪里下载安装所需的仿真器。

从 GSP 发送静态 WML

第一个 WML 例子为静态代码。清单 4 是一个使用常见的 <g:each><g:if>标记的例子:

清单 4. 结合 GSP 和 WML
 <% response.setContentType("text/vnd.wap.wml") %> 
 <% 
 def flightList = [] 
 flightList << [iata1:"DEN", iata2:"ORD"] 
 flightList << [iata1:"ORD", iata2:"DEN"] 
 %> 

 <?xml version="1.0"?> 
 <!DOCTYPE wml PUBLIC "-//PHONE.COM//DTD WML 1.1//EN"
   "http://www.phone.com/dtd/wml11.dtd" > 

 <wml> 
  <g:each in="${flightList}" var="${flight}" status="i"> 
    <card id="f${i}" title="Flight ${i}"> 
      <p mode="wrap">From: ${flight.iata1}</p> 
      <p mode="wrap">To: ${flight.iata2}</p>      
      <g:if test="${flightList.size() > i+1}"> 
        <p> 
          <anchor>Next<go href="#f${i}"/></anchor> 
        </p>  
      </g:if>  
    </card> 
  </g:each>  
 </wml>

注意我仅仅模仿了 HashMap 中的一些机载数据,而不是设置完整的 MVC 基础设施。重要的是它能保证了 GSP 标记与 WML 的结合,就像我在 “精通 Grails: 用 Groovy 服务器页面(GSP)改变视图” 中处理 JavaScript 一样(可以在 http://davisworld.org/testwml2.gsp. 中查看到这个页面的示例)。

WML 1.x:一个时代的终结

虽然常有人断言 WML 的生命快到头了,但仅支持 WML 的手机仍在流通。没错! —WML 1.x 正在淡出江湖。越来越多的现代手机开始避免这种 “分离但平等的” WML 平台,转而使用真正的 Web 浏览器。正如下一节所演示的一样,要为 WML 2.x 设备或 iPhones 创建一个便于移动的浏览网站,只需在现存的 HTML 上做些变动,而不是将其转换成完全不同的标记语言。


结合使用 Grails 与 WML 2.X(或 XHTML-MP)

提到 WML 2.x,WML更像是一个品牌的名称,而不是一个独立的标记语言(WML 1.x 才是)。事实上,WML 2.x 只不过是 XHTML 的一个方言:明确地说是 XHTML-MP。

XHTML-MP 严格要求创建格式良好的 XML。这就意味必须正确地关闭每一个容器标记(<p></p><li></li>),属性前后要用引号(<a href="http://somewhere.com">),并且元素名称只能用小写字母(<h1>而不是 <H1>)。

XHTML-MP 是 XHTML-Basic 的一个超集。只要稍作调整,您的网站就遵循 XHTML-Basic 规范。XHTML-MP 不可以使用嵌套的表格或 框架。它只支持 gif 和 png 图像格式。至于其他的最佳实践(比如指定图像大小和替换文本)则是 XHTML-Basic 的要求。很多常见的 HTML 标记(虽然不是全部)都可以找到。参阅 参考资料获得可用于 XHTML-Basic 和 XHTML-MP 的标记的列表链接。

要优化网站使其适合较小屏幕,就必须减少针对每个请求发回的数据。Web 网页(包括 HTML、CSS 和图像)最好小于 20KB。并且要使用 Expires或者 Cache-Controlheader 来主动缓冲文件。当为移动设备提供内容时,要将网页分割为 2 到 3 页。http://m.cnn.com 在这方面做的就很好,它可以将整篇文章分成 3 到 4 页显示,但也提供了 “整篇文章” 的链接,如果您不介意额外开销的话。

就像使用 WML 1.x 一样,必须在文件的开始包含正确的 DTD。同时还要修改 <html>标记,使其包含 xmlns属性,如清单 5 所示:

清单 5. 启动 XHTML-MP 文件
 <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
"http://www.wapforum.org/DTD/xhtml-mobile10.dtd"> 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 
 ... 
 </html>

虽然很多移动设备也接受更加通用的 MIME 类型 application/xhtml+xml,但您仍然要用适当的 MIME 类型 application/vnd.wap.xhtml+xml将其发送。application/xhtml+xml可以帮助您在标准桌面浏览器中调试代码。

查看 XHTML-MP

访问 http://m.yahoo.com 可以查看 XHTML-MP。(虽然它在 Web 浏览其中看起来很简朴,但在手机上的效果却很好)。选择 View > Source,就会在文档顶端看见 XHTML-MP DTD 了。

想要更深入地了解这样的网站在真机上的效果到底如何,您还需要找到另外一个仿真器。例如,Sandip Chitale 的博客提供了 Firefox 插件,它看来真的很象一个 iPhone(参阅 参考资料)。注意,这个仿真器要比真机大一些,但是它显示的网站效果跟在 iPhone 上显示的效果非常接近。(我将指出一些更精确的验证器)。图 2 展示了用 Chitale 的仿真器仿真的 m.yahoo.com:

图 2. 使用 iPhone 仿真器查看 Yahoo 移动 web
使用 iPhone 仿真器查看 Yahoo 移动 web

验证 XHTML-MP

有几个在线验证器可以确保您发出的 XHTML-MP 是格式良好的。您可以尝试一下 W3C mobileOK Basic Checker 或 ready.mobi 测试工具(参阅 参考资料)。二者都很好,但是 ready.mobi 的仿真器提供的信息要比 W3C 多得多。

例如,图 3 展示了 W3C 验证器所提供的关于 http://m.google.com 的信息:

图 3. W3C 验证器提供的有关 Google 的移动 web 的报告
W3C 验证器提供的有关 Google 的移动 web 的报告

图 4 为 ready.mobi 工具提供的关于 http://m.yahoo.com 的报告的前一部分:

图 4. ready.mobi 提供的关于 Yahoo 的移动 web 的报告
ready.mobi 提供的关于 Yahoo 的移动 web 的报告

它显示了 Yahoo! 的 4/5。再往下拉一点点,您就可以看到很多不同的可视化器,使您可以看到网页的真正显示效果。图 5 展示了它在 Nokia N70 的效果:

图 5. 使用仿真器查看 Yahoo 的移动 web
使用仿真器查看 Yahoo 的移动 web

在页面的底部,ready.mobi 验证器展示了一组详细的测试结果,每一个结果都带有这样的标记:通过(绿色)、失败(红色)或警告(黄色)。例如,即使 http://m.yahoo.com 好像在各种设备上都显示得不错,其 XHTML 也不是 100% 遵从的,如图 6 所示:

图 6. 查看 XHTML-MP 遵从性错误
查看 XHTML-MP 遵从性错误

再往下看,如图 7 所示,您会看到 Yahoo! 在图像上遗漏了一些 alt属性,而且在某些情况下没有指定图像的大小:

图 7. 查看具体的错误
查看具体的错误

Grails 与 XHTML-MP

那么,Grails 已经可以直接用于开发移动 Web 了吗?图 8 展示了 ready.mobi 验证器提供的关于旅行计划应用程序的原始清单页面的信息:

图 8. Grails 没有直接遵从 XHTML-MP
Grails 没有直接遵从 XHTML-MP

那就是说,还需要做一些工作。首先,在 grails-app/controllers/AirportController.groovy 中创建一个 mlist闭包。除了会返回 5 个(而不是 10 个)元素外,它与默认的闭包没什么不同。创建一个单独的闭包保留,您就可以原样保持 list.gsp,以进行比较,如清单 6 所示:

清单 6. AirportController中的新闭包
 def mlist = { 
  if(!params.max) params.max = 5 
  [airportList:Airport.list(params)] 
 }

现在将 grails-app/views/airport/list.gsp 复制到 mlist.gsp。(一会儿,我将提供一些策略,从而将移动用户无缝地重定向到正确的内容。这个强有力的方法目前还能满足需求)。

验证器指出网站未返回 XHTML-MP。编辑 mlist.gsp 使它在 <html>标记中包含有必要的 DTD 和 xmlns属性。您还需要禁用 meta标记,因为它会自动将内容类型设置为 text/html。最后一步:将 grails-app/views/layout/main.gsp 中包含 CSS 的行复制到该文件中。(SiteMesh —Grails 使用的模板库 —配置为只在默认情况下修饰 text/html 文件)。清单 7 展示了 mlist.gsp:

清单 7. 将 GSP 页面转变成 XHTML-MP
 <% response.setContentType("application/xhtml+xml")%> 
 <?xml version="1.0" encoding="UTF-8"?> 
 <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" 
        "http://www.wapforum.org/DTD/xhtml-mobile10.dtd"> 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 
  <head> 
    <!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/--> 
    <link rel="stylesheet" href="${createLinkTo(dir:'css',file:'main.css')}" /> 
    <meta name="layout" content="main" /> 
    <title>Airport List</title> 
  </head> 
  ... 
 </html>

在编辑文件时,也可以简化表布局。验证器指出 <thead><tbody>标记有误,所以需要将其删除。由于手机屏幕的纵向空间要比横向空间大,所以清单 8 所示的布局看起来会好一些:

清单 8. 简化表
 <table> 
  <tr> 
    <g:sortableColumn property="id" title="Id" /> 
    <g:sortableColumn property="name" title="Name" /> 
  </tr> 
  <g:each in="${airportList}" status="i" var="airport"> 
  <tr class="${(i % 2) == 0 ? 'odd' : 'even'}"> 
    <td> 
      <g:link action="show" 
              id="${airport.id}">${airport.id?.encodeAsHTML()} 
      </g:link> 
    </td> 
    <td>${airport.iata?.encodeAsHTML()}<br/> 
        ${airport.name?.encodeAsHTML()} 
    </td> 
  </tr> 
  </g:each> 
 </table>

图 9 展示了新页面在 iPhone 仿真器中的显示效果:

图 9. 为 iPhone 定制的列表页面
为 iPhone 定制的列表页面

图 10 展示了此时 ready.mobi 验证器所提供的信息:

图 10. 通过验证的列表页面
通过验证的列表页面

这就好多了!而且针对验证器的必要更改是很少的。回顾 “精通 Grails: 用 Groovy 服务器页面(GSP)改变视图”,可以通过输入 grails install-templates来相应地更改默认模板。


为 iPhone 开发页面

iPhone 可能就是三种类型的设备中最容易支持的设备。它页面的开发与普通的 Web 页面开发完全相同。iPhone 上的 Safari 浏览器与桌面浏览器的代码库完全相同,因此,用户在两者中所看到的东西是一样的。但是您可以去掉一些显示提示,因为通过 iPhone 查看网站时它们会影响外观和感觉。

例如,一个 iPhone 的屏幕尺寸为 320x480,但有趣的是,浏览器设置的 网页的默认宽度为 980 像素。这使文本在手机的景色模式下不能读取,并且在肖像模式下会变得很小。但是不用担心,使用一个简单的只有 iPhone 才能识别的 meta标记,就可以将网页校正到 “正确的尺寸” 了:viewport标记允许为移动 Safari 浏览器添加提示。清单 9 中的代码就在很大程度上提高了在 iPhone 上查看的网页的可读性。(不幸的是,基于 Firefox 的 iPhone 仿真器无法识别这个 meta标记。只有在真正的 iPhone 上才可以看到它的实际运行)。

清单 9. 为 iPhone 设置 viewport
 <meta name="viewport" content="initial-scale=1.0" />

inital-scale的范围为 0 到 10,且支持分数值。也可以输入显式的 widthheight值,上限为 10,000 像素(如清单 10 所示):

清单 10. 为 viewport设置 widthheight
 <meta name="viewport" content="width=600;height=400" />

iPhone 上的超链接

说到超链接,iPhone 提供了一些特殊的性能。如果使用 tel:前缀代替 http://,单击链接就可以拨出一个电话号码,如清单 11 所示:

清单 11. iPhone 上可用于拨号的链接
 <p> 
 telephone number: 
 <a href="tel:303-555-1212">303-555-1212</a> 
 </p>

如果使用传统的 mailto:前缀的话,单击链接就会运行邮件应用程序,如清单 12 所示:

清单 12. 邮件链接
 <p> 
 mail: 
 <a href="mailto:scott@aboutgroovy.com">Scott Davis</a> 
 </p>

如果您为 Google Map 提供一个链接,单击链接就会运行本地 Google Maps 应用程序,而不是将其转交到 Safari 中,如清单 13 所示:

清单 13. Google Map 链接
 <p> 
 local google maps: 
 <a href="http://maps.google.com/maps?q=denver+international+airport">DEN</a> 
 </p>

输入一个起点和终点,单击链接,它就会为用户提供驾驶方向,如清单 14 所示:

清单 14. Google Map 驾驶方向
 <p> 
 driving directions: 
 <a href="http://maps.google.com/maps?daddr= 
    denver+airport&saddr=coors+field+denver,+co">Directions</a> 
 </p>

移动 Web 开发策略

您已经知道为三种基本设备创建内容都需要什么工具,现在的任务是如何根据需要使用它们。有三种基本的策略可供选择。

为移动内容创建独立的、专用的网站

正如前面看到的一样,m是许多 Web 站点所采用的策略。Google、Yahoo! 以及 CNN,都设置了一个 m域,它独立于主站点,用于提供移动内容。如果改动域名系统(Domain Name System,DNS)的话,可以创建一个类似 http://mysite.org/mobile 的 URL。您也可以注册一个移动内容专用的 .mobi 域。

监听用户代理

每一个 Web 浏览器在请求数据时都向服务器表明身份。可以利用这个信息来提供为设备定制的内容。(http://twitter.com 使用的就是这种技术 )。

访问 http://davisworld.org/echo.gsp。清单 15 中的页面只用了个简单的循环,就回应了 HTTP 的请求:

清单 15. 显示 Request Header
 <h2>Request Headers</h2> 
 <table border="1"> 
  <tr> 
    <th>Header</th> 
    <th>Value</th> 
  </tr> 
  
  <g:each in="${request.headerNames}" var="${name}"> 
    <tr> 
      <td>${name}</td> 
      <td>${request.getHeader(name)}</td> 
    </tr> 
  </g:each> 
 </table>

正如您在图 11 中所看到的,当我打开 http://davisworld.org/echo.gsp 时,Firefox 浏览器提供了足够身份提示:

图 11. 查看 HTTP header
查看 HTTP header

根据图 11 中展示的 user-agent字符串,就可以断定请求程序通过 Intel CPU 运行 Mac 系统。对于 OS(10.5)、HTML 呈现引擎(Gecko)、和真实浏览器(Firefox)的版本,您已经很熟悉了。清单 17 展示了其他常见的用户 - 代理字符串:

清单 17. 常见的用户 - 代理字符串
 BlackBerry7520/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 
    UP.Browser/5.0.3.3 UP.Link/5.1.2.12 

 Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) 
    AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 

 Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)

通过捕获 request.getHeader("user-agent")值为请求浏览器提供适当的内容。

发回浏览器接受的内容

第三种策略就是满足浏览器的所有请求。每一个请求都会包含一个 accept值和一个 user-agent值。Firefox 返回的 accept值如下:

text/html,application/xhtml+xml,application/xml;

这告诉服务器 Firefox 偏好 text/html。如果服务器不包含 text/html数据,那么它可以发送 application/xhtml+xml。如果两者都没有的话,服务器会在列表中逐个查找,直到找到一个可以返回的 MIME 类型。

WAP 1.x 浏览器需要 text/vnd.wap.wml,更现代的手机会需要 application/vnd.wap.xhtml+xml。只要多加注意,聪明的开发者便可以返回适当的数据。

当然,这三种策略并不是相互排斥的。您可以全部选用,确保您的网站已经准备好为全球 33 亿的手机用户提供服务了。


结束语

让 Grails 应用程序便于手机使用的方法有很多种,可以不做任何改动(对于 iPhone 而言)、做很小的改动(对于 XHTML-MP 设备而言)、或者全部重写(对于 WML 1.x 设备而言)。借助文中所介绍的这些仿真器和验证器,您一定可以实现顺利支持移动 Web。

在下一篇文章中,您将会学习如何处理 Grails 中的遗留数据库。您将学习 Mapping DSL、使用 Hibernate 注释和 HBM 文件。学会了这些技术,您就可以让 Grails 使用现有的表和字段名,即使它们不符合 Grails 标准命名规定。到时候就尽情享受精通 Grails 的带来的乐趣了。

参考资料

学习

获得产品和技术

  • Grails:下载最新版本的 Grails。
  • Opera Mini:提供免费的移动浏览器。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology, Web development
ArticleID=319908
ArticleTitle=精通 Grails: Grails 与移动 Web
publish-date=07152008