最近在开发项目中遇到springmvc在进行视图渲染时,pc端和移动端不是同一个页面的情况,需要将不同的设备类型解析到不同的视图进行渲染。
一、配置方式
这里我写了一个RequestToViewNameTranslatorImpl类实现了RequestToViewNameTranslator接口,并重写了获取视图名称的方法。
java
@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");
}
@Override
public 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包:
XML
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>1.21</version>
</dependency>
二、原理
要了解此配置的实现机制需要看DispatcherServlet中的定义:
java
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对象,做为请求转换成视图名称的对象。
java
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中返回的有视图名称则不再使用请求获取视图名称。