最近在开发项目中遇到springmvc在进行视图渲染时,pc端和移动端不是同一个页面的情况,需要将不同的设备类型解析到不同的视图进行渲染。
一、配置方式
这里我写了一个RequestToViewNameTranslatorImpl类实现了RequestToViewNameTranslator接口,并重写了获取视图名称的方法。
@Component(DispatcherServlet.REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME)
public class RequestToViewNameTranslatorImpl implements RequestToViewNameTranslator {private DefaultRequestToViewNameTranslator defaultRequestToViewNameTranslator = new DefaultRequestToViewNameTranslator();private DefaultRequestToViewNameTranslator mobileRequestToViewNameTranslator = new DefaultRequestToViewNameTranslator();public AuthserverRequestToViewNameTranslator() {mobileRequestToViewNameTranslator.setSuffix("_mobile");}@Overridepublic String getViewName(HttpServletRequest request) throws Exception {if(getDeviceType(request) == DeviceType.MOBILE) {return mobileRequestToViewNameTranslator.getViewName(request);}return defaultRequestToViewNameTranslator.getViewName(request);}private DeviceType getDeviceType(HttpServletRequest request) {return UserAgent.parseUserAgentString(request.getHeader("User-Agent")).getOperatingSystem().getDeviceType();}
}
需要注意的是:
1、Bean的名称必须是viewNameTranslator
(DispatcherServlet.REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME)
2、类中我使用了UserAgent获取了设备类型,需要引入jar包:
<dependency><groupId>eu.bitwalker</groupId><artifactId>UserAgentUtils</artifactId><version>1.21</version>
</dependency>
二、原理
要了解此配置的实现机制需要看DispatcherServlet中的定义:
public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";private void initRequestToViewNameTranslator(ApplicationContext context) {try {this.viewNameTranslator =context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);if (logger.isDebugEnabled()) {logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]");}}catch (NoSuchBeanDefinitionException ex) {// We need to use the default.this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);if (logger.isDebugEnabled()) {logger.debug("Unable to locate RequestToViewNameTranslator with name '" +REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME + "': using default [" + this.viewNameTranslator +"]");}}
}
当DispatcherServlet初始化时会调用initRequestToViewNameTranslator方法,此方法会从ApplicationContext中去查找名称为viewNameTranslator的Bean对象,做为请求转换成视图名称的对象。
private void applyDefaultViewName(HttpServletRequest request, ModelAndView mv) throws Exception {if (mv != null && !mv.hasView()) {mv.setViewName(getDefaultViewName(request));}
}
protected String getDefaultViewName(HttpServletRequest request) throws Exception {return this.viewNameTranslator.getViewName(request);
}
applyDefaultViewName方法用于将请求转换成视图名称,需要注意的是,如果Controller中返回的有视图名称则不再使用请求获取视图名称。