Introduction
In this post, I will explain how to switch view based on devices on the web application - like pc, smartphone, tablet.
The basic strategy is checking user agenet which is sent from these devices, and building the specific html for the device.
The key issue uis how to check user agent of all coming http requests efficiently and ellegantly.
If you use some web application framework such as Java Spring Framework or PHP Symfony framework, the solution is using &qout;Filter&qout; which every http requests pass through.
Let me show you the example implementation using Spring framework.
Basic Strategy
- In filter
- check if "view_mode" in user cookies, set the view mode based on that cookie value
- if the cookie does not exist, set view mode based on user agent and publish corresponding view mode cookie
- set the selected view mode to HttpServletRequest attribute.
- In controller, set view template based on view mode in the HttpServletRequest attribute
Code Example
Ok now, I will show you the code example for swithing view using filter of Spring framework.
View Mode Filter
I think no special explanation is required because the code example is not so complicated.Only one key point is the ViewModeFilter class extends OncePerRequestFilter of Spring framework.
import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.filter.OncePerRequestFilter; public class ViewModeFilter extends OncePerRequestFilter { public static final String VIEW_MODE_ATTR_KEY = "view_mode"; public static final String VIEW_MODE_COOKIE = "viewMode"; @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException { ViewMode mode = getViewModeFromCookie(req); if(mode == null) { mode = determieViewModeFromUA(req, res); res.addCookie(newViewModeCookie(mode)); } req.setAttribute(VIEW_MODE_ATTR_KEY, mode); chain.doFilter(req, res); } private static ViewMode determieViewModeFromUA(HttpServletRequest req, HttpServletResponse res) { if(isMobile(req)) { return ViewMode.MOBILE; } else { return ViewMode.PC; } } private static Cookie newViewModeCookie(ViewMode mode) { Cookie cookie = new Cookie(VIEW_MODE_COOKIE, mode.getCookieValue()); cookie.setMaxAge(24*60*60); cookie.setPath("/"); return cookie; } private static ViewMode getViewModeFromCookie(HttpServletRequest req) { Cookie[] cookies = req.getCookies(); if(cookies == null) return null; for(Cookie cookie : cookies) { if(cookie.getName().equals(VIEW_MODE_COOKIE) && (cookie.getPath() == null || cookie.getPath().equals("/"))) { return ViewMode.MOBILE.getCookieValue().equals(cookie.getValue()) ? ViewMode.MOBILE : null; } } return null; } // helper method which will be used in Controller. // don't have to put it here. public static String selectView(String view, HttpServletRequest req) { if(req.getAttribute(VIEW_MODE_ATTR_KEY) == ViewMode.MOBILE) { return view + "Mobile"; } return view; } public static Boolean isMobile(HttpServletRequest req) { String agent = req.getHeader("User-Agent"); return agent != null && agent.contains("Mobile"); } }
View Mode
public enum ViewMode { PC { @Override public String getCookieValue() { return "pc"; } }, MOBILE { @Override public String getCookieValue() { return "mobile"; } } ; public abstract String getCookieValue(); }
web.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>ViewModeFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetBeanName</param-name> <param-value>viewModeFilter</param-value> </init-param> </filter> <!-- any url for every requests should pass though ViewModeFilter--> <filter-mapping> <filter-name>ViewModeFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
applicationContext.xml
Just define ViewModeFiler as a bean.<beans xmlns:security="http://www.springframework.org/schema/security" xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <bean id="viewModeFilter" class="your.package.filter.ViewModeFilter"/> </beans>
Controller
After all above preparation is done, you can swicth view based on HttpServeltRequest attribute.In Controller of MVC, if you just prepare top.jsp, topMobile.jsp, you can easily switch view template like below code snippet.
@RequestMapping(value = "/", method = RequestMethod.GET) public ModelAndView top(HttpServletRequest request) throws JDOMException, IOException{ return new ModelAndView(ViewModeFilter.selectView("top", request), new HashMap<String, Object>()); }
コメント