当前位置: 首页 > news >正文

Spring MVC 源码- RequestToViewNameTranslator 组件

RequestToViewNameTranslator 组件

RequestToViewNameTranslator 组件,视图名称转换器,用于解析出请求的默认视图名。就是说当 ModelAndView 对象不为 null,但是它的 View 对象为 null,则需要通过 RequestToViewNameTranslator 组件根据请求解析出一个默认的视图名称。

回顾

先来回顾一下在 DispatcherServlet 中处理请求的过程中哪里使用到 RequestToViewNameTranslator 组件,可以回到《一个请求的旅行过程》中的 DispatcherServletdoDispatch 方法中看看,如下:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;try {ModelAndView mv = null;try {// ... 省略相关代码// <6> 真正的调用 handler 方法,也就是执行对应的方法,并返回视图mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// ... 省略相关代码// <8> 无视图的情况下设置默认视图名称applyDefaultViewName(processedRequest, mv);// ... 省略相关代码}catch (Exception ex) {dispatchException = ex; // <10> 记录异常}// <11> 处理正常和异常的请求调用结果processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) { // <12> 已完成处理 拦截器 }finally { }
}private void applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) throws Exception {if (mv != null && !mv.hasView()) {String defaultViewName = getDefaultViewName(request);if (defaultViewName != null) {mv.setViewName(defaultViewName);}}
}@Nullable
protected String getDefaultViewName(HttpServletRequest request) throws Exception {return (this.viewNameTranslator != null ? this.viewNameTranslator.getViewName(request) : null);
}

在上面方法的<8>处,会调用 applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) 方法,如果返回的 ModelAndView 对象不为 null,但是他的 View 对象为 null,则需要通过 viewNameTranslatorgetViewName(HttpServletRequest request) 方法,从请求中获取默认的视图名,如果获取到了则设置到 ModelAndView 对象中

applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) 这个方法还会在处理异常的时候调用,因为处理异常也返回 ModelAndView 对象,所以需要做“类似”的处理

RequestToViewNameTranslator 接口

org.springframework.web.servlet.RequestToViewNameTranslator,视图名称转换器,用于解析出请求的默认视图名,代码如下:

public interface RequestToViewNameTranslator {/*** 根据请求,获得其视图名*/@NullableString getViewName(HttpServletRequest request) throws Exception;
}

Spring MVC 就提供一个实现类:org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

我看了一下,Spring Boot 没有提供其他的实现类

初始化过程

DispatcherServletinitRequestToViewNameTranslator(ApplicationContext context) 方法,初始化 RequestToViewNameTranslator 组件,方法如下:

private void initRequestToViewNameTranslator(ApplicationContext context) {try {this.viewNameTranslator =context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);if (logger.isTraceEnabled()) {logger.trace("Detected " + this.viewNameTranslator.getClass().getSimpleName());}else if (logger.isDebugEnabled()) {logger.debug("Detected " + this.viewNameTranslator);}}catch (NoSuchBeanDefinitionException ex) {// We need to use the default./*** 如果未找到,则获取默认的 RequestToViewNameTranslator 对象* {@link org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator}*/this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);if (logger.isTraceEnabled()) {logger.trace("No RequestToViewNameTranslator '" + REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME +"': using default [" + this.viewNameTranslator.getClass().getSimpleName() + "]");}}
}
  1. 获得 Bean 名称为 "viewNameTranslator",类型为 RequestToViewNameTranslator 的 Bean ,将其设置为 viewNameTranslator

  1. 如果未获得到,则获得默认配置的 RequestToViewNameTranslator 实现类,调用 getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) 方法,就是从 DispatcherServlet.properties 文件中读取 RequestToViewNameTranslator 的默认实现类,如下:

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

DefaultRequestToViewNameTranslator

org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator 实现 RequestToViewNameTranslator 接口,默认且是唯一的 RequestToViewNameTranslator 实现类

构造方法

public class DefaultRequestToViewNameTranslator implements RequestToViewNameTranslator {private static final String SLASH = "/";/*** 前缀*/private String prefix = "";/*** 后缀*/private String suffix = "";/*** 分隔符*/private String separator = SLASH;/*** 是否移除开头 {@link #SLASH}*/private boolean stripLeadingSlash = true;/*** 是否移除末尾 {@link #SLASH}*/private boolean stripTrailingSlash = true;/*** 是否移除拓展名*/private boolean stripExtension = true;/*** URL 路径工具类*/private UrlPathHelper urlPathHelper = new UrlPathHelper();
}

getViewName

实现 getViewName(HttpServletRequest request) 方法,代码如下:

@Override
public String getViewName(HttpServletRequest request) {// 获得请求路径String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);// 获得视图名return (this.prefix + transformPath(lookupPath) + this.suffix);
}@Nullable
protected String transformPath(String lookupPath) {String path = lookupPath;// 移除开头 SLASHif (this.stripLeadingSlash && path.startsWith(SLASH)) {path = path.substring(1);}// 移除末尾 SLASHif (this.stripTrailingSlash && path.endsWith(SLASH)) {path = path.substring(0, path.length() - 1);}// 移除拓展名if (this.stripExtension) {path = StringUtils.stripFilenameExtension(path);}// 替换分隔符if (!SLASH.equals(this.separator)) {path = StringUtils.replace(path, SLASH, this.separator);}return path;
}
  1. 通过 urlPathHelper 获取该请求的请求路径

  1. 调用 transformPath(String lookupPath) 方法,获得视图名,并添加前后缀(默认都是空的)。实际上就是你的请求 URI

总结

本文对 Spring MVC 的RequestToViewNameTranslator 组件进行了分析,视图名称转换器,用于解析出请求的默认视图名。当 ModelAndView 对象不为 null,但是它的 View 对象为 null,则需要通过 RequestToViewNameTranslator 组件根据请求解析出一个默认的视图名称。默认的 DefaultRequestToViewNameTranslator 实现类返回的就是请求的 URI。

我们目前最常用的 @ResponseBody 注解,对应的 RequestResponseBodyMethodProcessor 返回值处理器,所得到的 ModelAndView 对象为 null,所以不会用到该组件,也不会进行视图渲染,前后端分离嘛~

http://www.lryc.cn/news/20331.html

相关文章:

  • Linux--TCP编程--0216 17
  • 关于设计模式的记录
  • Lambda-常见的函数式接口
  • P1196 [NOI2002] 银河英雄传说 带权并查集
  • 【项目实战】快来入门Groovy的基础语法吧
  • Mybatis中的动态SQL
  • VUE常用API
  • 25 openEuler管理网络-使用nmcli命令配置ip
  • 如何安装和使用A-ops工具?
  • MySql数据库环境部署
  • 极品笔记,阿里P7爆款《K8s+Jenkins》技术笔记,职场必备
  • 数据结构:各种排序方法的综合比较
  • 【设计模式】 策略模式介绍及C代码实现
  • 【数据库】第二章 关系数据库
  • oracle和mysql的分页
  • 深拷贝与浅拷贝的理解
  • Shell变量
  • Android 8请求权限时弹窗BUG
  • 路漫漫:网络空间的监管趋势
  • 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
  • 数据库的基本查询
  • 10 分钟把你的 Web 应用转为桌面端应用
  • Delphi RSA加解密(二)
  • pytorch 深度学习早停设置
  • 【Vue学习】Vue高级特性
  • Android 12.0 系统Settings去掉开发者模式功能
  • buu [NCTF2019]babyRSA 1
  • Java:如何选择一个Java API框架
  • mt6735 MIC 音量的调整及原理介绍
  • 【深度学习】什么是线性回归逻辑回归单层神经元的缺陷