春季版:2.5.6
我想根据 User-Agent 标头的值将视图解析为特定的速度文件。
我目前的思路是一个类似于 UrlBasedViewResolver 的实现,这样用户代理值根据匹配的正则表达式(键)映射(通过上下文)到特定目录(值)。
我几乎可以肯定有一种更简单的方法。
之前发布了一个类似的问题,关于基于 User-Agent 的主题确定。但是,我的理解是,主题更多地与静态(css、js)内容相关,而不是哪个文件处理实际的响应构造(HTML、XML 等)。
春季版:2.5.6
我想根据 User-Agent 标头的值将视图解析为特定的速度文件。
我目前的思路是一个类似于 UrlBasedViewResolver 的实现,这样用户代理值根据匹配的正则表达式(键)映射(通过上下文)到特定目录(值)。
我几乎可以肯定有一种更简单的方法。
之前发布了一个类似的问题,关于基于 User-Agent 的主题确定。但是,我的理解是,主题更多地与静态(css、js)内容相关,而不是哪个文件处理实际的响应构造(HTML、XML 等)。
这里建议了另一个选项
但是我解决了扩展ContentNegotiatingViewResolver并覆盖了resolveViewName方法,我调用了 ViewResolver HttpHeaderParamViewResolver。扩展方法如下所示:
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
//Get the HTTP Header param "User-Agent"
String headerParamValue = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest().getHeader(headerParam);
viewName = setViewName(viewName, headerParamValue);
return super.resolveViewName(viewName, locale);
}
其中headerParam="User-Agent"(或您喜欢的任何其他 HTTp Header 参数,这是在 bean xml 中定义的),然后您对其进行评估并确定 viewName。在我的情况下,可以使用 Map 配置HttpHeaderParamViewResolver,其中键是要附加到实际 viewName 的前缀,值是用于评估标头参数值的 RegExp。它在 App Context XML 中看起来像这样:
<bean id="HttpHeaderViewResolver" class="com.application.viewresolver.HttpHeaderParamViewResolver">
<property name="viewResolvers">
<list>
<ref bean="tilesViewResolver"/>
</list>
</property>
<property name="headerParam" value="User-Agent"/>
<property name="viewPrefixPattern">
<map>
<entry>
<key>
<value>mobile-webkit</value>
</key>
<value>iPhone.*Apple.*Mobile.*Safari</value>
</entry>
<entry>
<key>
<value>mobile-bb</value>
</key>
<value>BlackBerry([0-9]{0,4})([a-zA-Z])?</value>
</entry>
</map>
</property>
</bean>
这样,如果我的控制器调用一个名为userDetails的视图并使用 iPhone 访问应用程序,第一个模式会捕获它并附加mobile-webkit后缀,因此该视图现在是mobile-webkit-userDetails,然后将其传递给生成的tilesViewResolver实际的看法。
我探索了很多可能性,我认为这是我能想到的最简单、最灵活的方法。在这种情况下,选择完全不同的视图的能力至关重要,因为我们支持各种各样的用户代理,从 WAP 到 iPhone 4 和支持 WebKit 的手机,因此视图从用户代理到用户代理的变化很大。另一个优点是您不再需要在视图上处理此问题,因为您可以拥有任意专业的视图。另一个好的方面是,您可以很容易地实现这一点,而无需删除或更改您可能已经拥有的视图解析器,因为ContentNegotiatingViewResolver能够以您定义的特定顺序将视图调用委托给其他视图解析器。
不利的一面是,您可能会倾向于过度专门化视图并最终得到大量视图文件,从而使应用程序成为可维护的噩梦。
希望它是有帮助的。
几个月前我也遇到了同样的问题!
在我们的移动项目(使用 Spring 2.5.6)中,我们最终使用了带有 SimpleUrlHandler 的拦截器。这会捕获所有传入请求并将 -m.jsp 添加到任何移动请求的末尾。
它涉及两个步骤:
1) 向我们的标准 URL 映射器声明一个拦截器:
<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<!-- This interceptor catches all
requests and redirects them to portal
or mobile html content.
-->
<property name="interceptors"> <list>
<ref bean="MultiViewController"/> </list> </property>
2) 实现拦截器,它在用户代理中寻找“移动”这个词。
public class MultiViewController extends HandlerInterceptorAdapter {
我在我的博客(关于移动 Web 开发的新的激动人心的世界)帖子中更详细地讨论了它:http: //plumnash.com/it/iphone-web-development-using-spring/
不需要在 ViewResolver 中进行配置的替代方法可能涉及顶级 Velocity 文件,然后有条件地解析具有以下内容的子文件。
#if ($userAgent1)
#parse ("user-agent-1.vm")
#elseif ($userAgent2)
#parse ("user-agent-2.vm")
#end
然而,实现一个新的或扩展一个现有的 ViewResolver 是一个非常简单的解决方案,也是我要采用的方式。
我将按照评论中的建议使用自定义视图解析器。(并将我的应用程序升级到 Spring 3.0.0)