2009-12-08 4 views
10

Frühling Version: 2.5.6Spring MVC: Die Lösung der Ansicht basierend auf User-Agent

ich die Ansicht auf eine bestimmte Geschwindigkeit Datei auf dem Wert des User-Agent-Header basierend lösen wollen.

Meine aktuelle Denkweise ist eine dem UrlBasedViewResolver ähnliche Implementierung, bei der der User-Agent-Wert Map'd (über Kontext) einem bestimmten Verzeichnis (Wert) zugeordnet wird, das einem regulären Ausdruck (Schlüssel) entspricht.

Ich bin mir fast sicher, dass es einen einfacheren Weg gibt.

Eine ähnliche Frage wurde bereits zur Themendefinition basierend auf User-Agent gestellt. Ich gehe jedoch davon aus, dass sich Themen eher auf den statischen (css, js) Inhalt beziehen und nicht auf die Datei, die die eigentliche Antwortkonstruktion (HTML, XML, usw.) behandelt.

+1

Eine benutzerdefinierte Ansicht Resolver wäre ziemlich einfach, ich glaube nicht, dass Sie einfacher als das bekommen. – skaffman

+0

Ja, ich stellte nur sicher, dass ich etwas Offensichtliches nicht übersah. –

Antwort

1

Ich gehe mit einem benutzerdefinierten Ansicht Resolver wie in Kommentaren vorgeschlagen. (und Upgrade meiner App auf Frühjahr 3.0.0)

+3

UPDATE: Spring 3.0 bietet eine Out-of-Box-Lösung mit dem neuen ContentNegoatingViewResolver. –

1

Eine Alternative, die keine Konfiguration in einem ViewResolver erfordert, kann eine Velocity-Datei auf oberster Ebene enthalten, die dann Unterdateien bedingt parst, die etwa so aussehen.

#if ($userAgent1) 
    #parse ("user-agent-1.vm") 
#elseif ($userAgent2) 
    #parse ("user-agent-2.vm") 
#end 

jedoch die Umsetzung einer neuen oder Erweiterung eines bestehenden ViewResolver eine ziemlich einfache Lösung ist, und wäre so, wie ich mit gehen würde.

+0

Dies würde funktionieren, wenn es 1) nicht buchstäblich Zehntausende von User Agents gibt 2) User Agent konnte nicht gefälscht werden. Wenn Sie den Benutzeragenten erkennen möchten, tun Sie wahrscheinlich am ehesten etwas falsch. – Esko

+0

@Esko "wahrscheinlich schon etwas falsch machen"? Es gibt viele Anforderungen, und nicht alle betreffen alle ~ zehntausend Benutzeragenten. –

+1

Manchmal müssen Sie Opfer bringen, damit die Dinge mit bestimmten Browsern funktionieren. * hust * Internet Explorer * hust * –

2

Ich hatte das gleiche Problem ein paar Monate zurück!

In unserem mobilen Projekt (mit Spring 2.5.6) verwendeten wir einen Interceptor mit unserem SimpleUrlHandler. Dadurch wurden alle eingehenden Anfragen abgefangen und -m.jsp am Ende aller mobilen Anfragen hinzugefügt.

Dabei handelte es sich in zwei Schritten:

1) einen Abfangjäger zu unserem Standard-URL-Mapper erklärt:

<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> 

und 2) die Interceptor Implementierung, die für das Wort 'Handy' in der vom Benutzer angesehen Agent.

public class MultiViewController extends HandlerInterceptorAdapter { 

ich es genauer auf meinem Blog reden (über die neue spannende Welt der mobilen Web-Entwicklung) Beitrag: http://plumnash.com/it/iphone-web-development-using-spring/

2

Es gibt eine andere Option here vorgeschlagen

Jedoch habe ich beschlossen Erweiterung a ContentNegotiatingViewResolver und überschreiben die resolveViewName Methode, rief ich meine ViewResolver HttpHeaderParamViewResolver. Die erweiterte Methode sieht wie folgt aus:

@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); 
} 

Wo headerParam = "User-Agent" (oder eine andere HTTP-Header-Parameter Sie so wollen, ist dies in der Bean-xml definiert), nach, dass Sie bewerten und Bestimmen Sie den viewName. In meinem Fall kann der HttpHeaderParamViewResolver mit einer Map konfiguriert werden, wobei der Schlüssel ein Präfix ist, das an den tatsächlichen viewName angehängt wird, und der Wert ist eine RegExp, die verwendet wird, um den Wert des Header-Parameters zu bewerten.Es sieht so etwas wie dies in der App XML Kontext:

<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> 

auf diese Weise das, wenn mein Controller ruft eine Ansicht Userdetails genannt und ist die Anwendung mit einem IPhone Zugriff auf das erste Muster Fängen einhergehen sie und fügt die Mobile- webkit suffix so die ansicht ist jetzt mobile-webkit-userDetails und seine dann an die tilesViewResolver übergeben, die die tatsächliche Ansicht generiert.

Ich habe viele Möglichkeiten erforscht und ich denke, das ist die einfachste und flexibelste, die ich mir ausgedacht habe. In diesem Fall war die Möglichkeit, eine ganz andere Ansicht auszuwählen, von entscheidender Bedeutung, da wir eine Vielzahl von Benutzeragenten unterstützen, von WAP- bis zu IPhone 4- und WebKit-fähigen Mobiltelefonen, sodass sich Ansichten vom Benutzeragenten zum Benutzeragenten dramatisch ändern. Ein weiterer Vorteil ist, dass Sie dieses Problem nicht mehr in der Ansicht behandeln müssen, da Sie Ansichten so spezialisiert haben können, wie Sie möchten. Eine andere gute Seite ist, dass Sie dies ganz einfach implementieren können, ohne die bereits vorhandenen Ansichtsresolver entfernen oder ändern zu müssen. ContentNegoatingViewResolver hat die Möglichkeit, den Aufruf der Ansicht an andere View Resolver in der von Ihnen definierten Reihenfolge zu delegieren.

Der Nachteil ist, dass Sie versucht werden, die Ansichten zu spezialisieren und am Ende mit einer Menge von View-Dateien enden, die die App zu einem wartbaren Alptraum machen.

Ich hoffe, es ist hilfreich.

+1

Dies funktioniert nur mit Spring 3.0, da in früheren Versionen kein ContentNotiatingViewResolver vorhanden war – Chepech