前言

  SpringMVC如果在处理业务的过程中发生了异常,这个时候是没有一个完整的ModelAndView对象返回的,它应该是怎么样处理呢?或者说应该怎么去获取一个视图然后去展示呢。下面就是要讲的RequestToViewNameTranslator。

1.引出问题

  DispathcerServlet在处理完请求获取Me的lAndView之后就会获取相应的视图名称,然后渲染解析。这个是通过调用doDispatch()中的processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);方法来完成的,但是如果在处理这个请求的过程中发生了异常,并且这个异常类型不是ModelAndViewDefiningException类型的话,就会调用processHandlerException来处理一个异常,返回默认缺省的视图:

	protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception { // Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
if (exMv != null) {
if (exMv.isEmpty()) {
return null;
}
// We might still need view name translation for a plain error model...
if (!exMv.hasView()) {
exMv.setViewName(getDefaultViewName(request));
}
if (logger.isDebugEnabled()) {
logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
}
WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
return exMv;
} throw ex;
}

  在处理的过程中有这么一个需要注意exMv.setViewName(getDefaultViewName(request));如果没有提供的视图名字,那么胸膛会根据请求来获取一个默认的视图名。来看下具体获取默认视图的过程。

protected String getDefaultViewName(HttpServletRequest request) throws Exception {
return this.viewNameTranslator.getViewName(request);
}

  原来是通过RequestToViewNameTranslator viewNameTranslator;的getViewName来获取视图名称的。终于讲到今天的主角RequestToViewNameTranslator接口及其的默认实现类DefaultRequestToViewNameTranslator。

2.RequestToViewNameTranslator接口

首先看源码,

public interface RequestToViewNameTranslator {

	String getViewName(HttpServletRequest request) throws Exception;

}

  这个接口只有一个方法,就是根据请求对象获取一个视图名称。具体来讲就是在没有明确指定一个视图名称的时候,根据一个输入的请求获取一个逻辑视图名称。

3.DefaultRequestToViewNameTranslator实现

作为RequestToViewNameTranslator接口唯一的实现类,在没有扩展指定接口时候的时候,系统就会加载这个作为默认的实现。来看看具体时候涉及到的实现代码,

public String getViewName(HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
return (this.prefix + transformPath(lookupPath) + this.suffix);
} protected String transformPath(String lookupPath) {
String path = lookupPath;
if (this.stripLeadingSlash && path.startsWith(SLASH)) {
path = path.substring(1);
}
if (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;
}

  主要实现就是调用UrlPathHelper的getLookupPathForRequest的方法获取一个looup路径。transformPath方法主要是对获取的路径字符串再做个简单处理罢了。主要是UrlPathHelper的getLookupPathForRequest的实现:

	public String getLookupPathForRequest(HttpServletRequest request) {
// Always use full path within current servlet context?
if (this.alwaysUseFullPath) {
return getPathWithinApplication(request);
}
// Else, use path within current servlet mapping if applicable
String rest = getPathWithinServletMapping(request);
if (!"".equals(rest)) {
return rest;
}
else {
return getPathWithinApplication(request);
}
} public String getPathWithinApplication(HttpServletRequest request) {
String contextPath = getContextPath(request);
String requestUri = getRequestUri(request);
String path = getRemainingPath(requestUri, contextPath, true);
if (path != null) {
// Normal case: URI contains context path.
return (StringUtils.hasText(path) ? path : "/");
}
else {
return requestUri;
}
}
public String getPathWithinServletMapping(HttpServletRequest request) {
String pathWithinApp = getPathWithinApplication(request);
String servletPath = getServletPath(request);
String sanitizedPathWithinApp = getSanitizedPath(pathWithinApp);
String path; // if the app container sanitized the servletPath, check against the sanitized version
if(servletPath.indexOf(sanitizedPathWithinApp) != -1) {
path = getRemainingPath(sanitizedPathWithinApp, servletPath, false);
}
else {
path = getRemainingPath(pathWithinApp, servletPath, false);
} if (path != null) {
// Normal case: URI contains servlet path.
return path;
}
else {
// Special case: URI is different from servlet path.
String pathInfo = request.getPathInfo();
if (pathInfo != null) {
// Use path info if available. Indicates index page within a servlet mapping?
// e.g. with index page: URI="/", servletPath="/index.html"
return pathInfo;
}
if (!this.urlDecode) {
// No path info... (not mapped by prefix, nor by extension, nor "/*")
// For the default servlet mapping (i.e. "/"), urlDecode=false can
// cause issues since getServletPath() returns a decoded path.
// If decoding pathWithinApp yields a match just use pathWithinApp.
path = getRemainingPath(decodeInternal(request, pathWithinApp), servletPath, false);
if (path != null) {
return pathWithinApp;
}
}
// Otherwise, use the full servlet path.
return servletPath;
}
} public String getPathWithinApplication(HttpServletRequest request) {
String contextPath = getContextPath(request);
String requestUri = getRequestUri(request);
String path = getRemainingPath(requestUri, contextPath, true);
if (path != null) {
// Normal case: URI contains context path.
return (StringUtils.hasText(path) ? path : "/");
}
else {
return requestUri;
}
}

  

  首先判断当前上下文的完整路径是否为空,如果不为空就会调用getPathWithinApplication()方法返回这个路径名字。如果为空的话,则首先获取到当前请求的映射的完整路径,如果路径不为空就返回这个路径,如果路径为空则返回当前请求的完整路径了。

Spring之SpringMVC的RequestToViewNameTranslator(源码)分析的更多相关文章

  1. Spring之SpringMVC的MethodNameResolver(源码)分析

    前言 在介绍SpringMVC  的Controller的具体实现中,我们讲到了MultiActionController.在获取处理请求对于的方法的时候我们用到了下面的代码,来自于MultiActi ...

  2. Spring之SpringMVC的Controller(源码)分析

    说明: 例子就不举了,还是直接进入主题,本文主要是以SpringMVC的Controller接口为入点,来分析SpringMVC中C的具体实现和处理过程. 1.Controller接口 public ...

  3. Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

    文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...

  4. Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

    文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...

  5. Spring Environment(二)源码分析

    Spring Environment(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Envi ...

  6. SpringMVC由浅入深day01_6源码分析(了解)

    6 源码分析(了解) 通过前端控制器源码分析springmvc的执行过程. 入口 第一步:前端控制器接收请求 调用doDiapatch 第二步:前端控制器调用处理器映射器查找 Handler 第三步: ...

  7. Spring Security(四) —— 核心过滤器源码分析

    摘要: 原创出处 https://www.cnkirito.moe/spring-security-4/ 「老徐」欢迎转载,保留摘要,谢谢! 4 过滤器详解 前面的部分,我们关注了Spring Sec ...

  8. Spring Cloud Eureka服务注册源码分析

    Eureka是怎么work的 那eureka client如何将本地服务的注册信息发送到远端的注册服务器eureka server上.通过下面的源码分析,看出Eureka Client的定时任务调用E ...

  9. spring mvc 启动过程及源码分析

    由于公司开源框架选用的spring+spring mvc + mybatis.使用这些框架,网上都有现成的案例:需要那些配置文件.每种类型的配置文件的节点该如何书写等等.如果只是需要项目能够跑起来,只 ...

随机推荐

  1. flex eclipse综合spring入门

    首先下载FlashBuilder_4_7_LS10_win64.exe试了几eclipse安装没有成功插头,含有myeclipse8.5.spring sts2.9.2.eclipse3.5.j2ee ...

  2. SQL Server 数据库索引

    原文:SQL Server 数据库索引 一.什么是索引 减少磁盘I/O和逻辑读次数的最佳方法之一就是使用[索引] 索引允许SQL Server在表中查找数据而不需要扫描整个表. 1.1.索引的好处: ...

  3. QlikView线图高亮选择尺寸

    作为标题,如今,学生问我一个问题.尺寸Month.expression它是Count(Id). 这个图是一个折线图,不管你选择哪个月的其他下拉列表,销售量.由于Expression里面是这样写的 Co ...

  4. C#+Mapxtreme 实现一些GIS系统基本的功能

    此程序包括了mapxtreme地图相关基本功能的演示其中包括 鹰眼地图,图层控制,发达,缩小,平移地图,地图模糊查询,中点工具,距离测量工具,面积测量工具,图元信息查看工具.适合于企业级开发,可以为您 ...

  5. TestNg它@Factory详细解释------如何更改参数值测试

    原创文章,版权所有所有.转载,归因:http://blog.csdn.net/wanghantong TestNg的@Factory注解从字面意思上来讲就是採用工厂的方法来创建測试数据并配合完毕測试 ...

  6. Ajax基础知识(一)

    随便在百度谷歌上输入Ajax都会出现一大堆的搜索结果,这已经不再是什么新奇的技术了.但若从一开始就学习了ASP.Net,使用功能齐全的Visual Studio集成开发工具,或许未必能对访问一个动态网 ...

  7. android开源应用(主要是博客上带有分析的)收集 【持续更新】

    2014.5.24更新: (android高仿系列)今日头条    http://blog.csdn.net/vipzjyno1/article/details/26514543 CSDN Andro ...

  8. Debian 7设备nginx周围环境、编译并安装和启动

    /*********************************************************************  * Author  : Samson  * Date   ...

  9. 【SSH之旅】一步学习的步Struts1相框(三):分析控制Struts1示例

    部分博客,,先后实施了Struts抽样.现在我们来分析这个样本.具体解释Struts1. Struts1的几个核心组件是值得我们注意的: (1)ActionServlet(核心控制器). (2)Act ...

  10. (大数据工程师学习路径)第三步 Git Community Book----中级技能(下)

    一.追踪分支 1.追踪分支 在Git中‘追踪分支’是用于联系本地分支和远程分支的. 如果你在’追踪分支'(Tracking Branches)上执行推送(push)或拉取(pull)时,它会自动推送( ...