Spring MVC : 概念模型 RequestToViewNameTranslator

探讨SpringMVC中RequestToViewNameTranslator接口及其默认实现DefaultRequestToViewNameTranslator的作用,解析如何根据请求生成逻辑视图名称。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

这是Spring MVC定义的一个策略接口,它根据请求对象自身的属性解析出一个逻辑视图名称,通常用在没有针对请求明确指定视图的场景。

RequestToViewNameTranslatorDispatcherServlet使用 :

	/**
	 * Translate the supplied request into a default view name.
     * 尝试从请求本身信息翻译出一个视图名称,用以作为处理该请求的缺省视图
	 * @param request current HTTP servlet request
	 * @return the view name (or {@code null} if no default found)
	 * @throws Exception if view name translation failed
	 */
	@Nullable
	protected String getDefaultViewName(HttpServletRequest request) throws Exception {
		return (this.viewNameTranslator != null ? this.viewNameTranslator.getViewName(request) : null);
	}

源代码

源代码版本 : spring-webmvc-5.1.5.RELEASE

1. 接口RequestToViewNameTranslator

package org.springframework.web.servlet;

import javax.servlet.http.HttpServletRequest;

import org.springframework.lang.Nullable;


public interface RequestToViewNameTranslator {

	/**
	 * Translate the given {@link HttpServletRequest} into a view name.
	 * 从指定的请求对象中翻译出相应的视图名称
	 * @param request the incoming {@link HttpServletRequest} providing
	 * the context from which a view name is to be resolved
	 * @return the view name, or {@code null} if no default found
	 * @throws Exception if view name translation fails
	 */
	@Nullable
	String getViewName(HttpServletRequest request) throws Exception;

}

Spring MVCRequestToViewNameTranslator接口提供了一个缺省实现DefaultRequestToViewNameTranslator

2. 缺省实现类 DefaultRequestToViewNameTranslator

package org.springframework.web.servlet.view;

// 省略 import 行

public class DefaultRequestToViewNameTranslator implements RequestToViewNameTranslator {

	private static final String SLASH = "/";


	private String prefix = "";

	private String suffix = "";

	// 指定要使用的分隔符,缺省值使用 /
	private String separator = SLASH;

    // 是否要去除前缀/,缺省值为 true
	private boolean stripLeadingSlash = true;

    // 是否要去除后缀/,缺省值为 true
	private boolean stripTrailingSlash = true;

    // 是否要去除文件扩展名,缺省值为 true
	private boolean stripExtension = true;

    // URL 路径操作小助手,工具类,缺省值为 UrlPathHelper 对象
	private UrlPathHelper urlPathHelper = new UrlPathHelper();


	/**
	 * Set the prefix to prepend to generated view names.
	 * @param prefix the prefix to prepend to generated view names
	 */
	public void setPrefix(@Nullable String prefix) {
		this.prefix = (prefix != null ? prefix : "");
	}

	/**
	 * Set the suffix to append to generated view names.
	 * @param suffix the suffix to append to generated view names
	 */
	public void setSuffix(@Nullable String suffix) {
		this.suffix = (suffix != null ? suffix : "");
	}

	/**
	 * Set the value that will replace '{@code /}' as the separator
	 * in the view name. The default behavior simply leaves '{@code /}'
	 * as the separator.
	 */
	public void setSeparator(String separator) {
		this.separator = separator;
	}

	/**
	 * Set whether or not leading slashes should be stripped from the URI when
	 * generating the view name. Default is "true".
	 */
	public void setStripLeadingSlash(boolean stripLeadingSlash) {
		this.stripLeadingSlash = stripLeadingSlash;
	}

	/**
	 * Set whether or not trailing slashes should be stripped from the URI when
	 * generating the view name. Default is "true".
	 */
	public void setStripTrailingSlash(boolean stripTrailingSlash) {
		this.stripTrailingSlash = stripTrailingSlash;
	}

	/**
	 * Set whether or not file extensions should be stripped from the URI when
	 * generating the view name. Default is "true".
	 */
	public void setStripExtension(boolean stripExtension) {
		this.stripExtension = stripExtension;
	}

	/**
	 * Shortcut to same property on underlying {@link #setUrlPathHelper UrlPathHelper}.
	 * @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath
	 */
	public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
		this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
	}

	/**
	 * Shortcut to same property on underlying {@link #setUrlPathHelper UrlPathHelper}.
	 * @see org.springframework.web.util.UrlPathHelper#setUrlDecode
	 */
	public void setUrlDecode(boolean urlDecode) {
		this.urlPathHelper.setUrlDecode(urlDecode);
	}

	/**
	 * Set if ";" (semicolon) content should be stripped from the request URI.
	 * @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean)
	 */
	public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
		this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
	}

	/**
	 * Set the {@link org.springframework.web.util.UrlPathHelper} to use for
	 * the resolution of lookup paths.
	 * <p>Use this to override the default UrlPathHelper with a custom subclass,
	 * or to share common UrlPathHelper settings across multiple web components.
	 */
	public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
		Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
		this.urlPathHelper = urlPathHelper;
	}


	/**
	 * Translates the request URI of the incoming {@link HttpServletRequest}
	 * into the view name based on the configured parameters.
	 * @see org.springframework.web.util.UrlPathHelper#getLookupPathForRequest
	 * @see #transformPath
	 */
	@Override
	public String getViewName(HttpServletRequest request) {
       // 使用 urlPathHelper 找到 request 的查找路径,记录到 lookupPath 
		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
        
       //  1. 对 lookupPath 做变形处理,去除前缀后缀/,文件扩展名等 ;
       //  2. 加上指定的前缀后缀 prefix/suffix ;
		return (this.prefix + transformPath(lookupPath) + this.suffix);
	}

	/**
	 * Transform the request URI (in the context of the webapp) stripping
	 * slashes and extensions, and replacing the separator as required.
	 * @param lookupPath the lookup path for the current request,
	 * as determined by the UrlPathHelper
	 * @return the transformed path, with slashes and extensions stripped
	 * if desired
	 */
	@Nullable
	protected String transformPath(String lookupPath) {
		String path = lookupPath;
		if (this.stripLeadingSlash && path.startsWith(SLASH)) {
          // 如果被要求去除前缀/,并且 lookupPath 以/为前缀,则去除该前缀
			path = path.substring(1);
		}
		if (this.stripTrailingSlash && path.endsWith(SLASH)) {
          // 如果被要求去除后缀/,并且 lookupPath 以/为后缀,则去除该后缀
			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;
	}

}

DefaultRequestToViewNameTranslatorSpring MVC对接口RequestToViewNameTranslator的缺省实现。在实现DefaultRequestToViewNameTranslator中,针对请求翻译相应的逻辑视图名称时,它先使用UrlPathHelper获取该请求的lookupPath,然后按要求变形后返回。缺省情况下,具体的变形如下:

  1. 去除前缀/
  2. 去除后缀/
  3. 去除文件扩展名部分
  4. 如果指定的分隔符不是/,则将路径中所有的/替换成/
  5. 添加指定的前缀和后缀

Spring MVC前端控制器DispatcherServlet缺省使用的RequestToViewNameTranslator就是DefaultRequestToViewNameTranslator。在缺省配置文件spring-webmvc-5.1.5.RELEASE.jar!\org\springframework\web\servlet\DispatcherServlet.properties中有这样的定义 :

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

另外在DispatcherServlet对象初始化时,它会在找不到外部定义到容器中的RequestToViewNameTranslator 时使用DefaultRequestToViewNameTranslator :

	// DispatcherServlet 代码实现
	private void initRequestToViewNameTranslator(ApplicationContext context) {
		try {
          // 首先尝试从容器中获取类型为 RequestToViewNameTranslator 的 bean组件供使用
			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 的bean,提取缺省值,也就是
           // DispatcherServlet.properties 文件中定义的 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() + "]");
			}
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值