springmvc十六:视图解析

 spring.xml配置视图解析器如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">


		<context:component-scan base-package="com.atchina"></context:component-scan>
		
		<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
			<property name="prefix" value="/WEB-INF/pages/"></property>
			<property name="suffix" value=".jsp"></property>
		</bean>
</beans>

方法执行后的返回值会作为页面地址参考,转发或者重定向到页面。

视图解析器可能会进行页面地址的拼串。

 

forward前缀指定一个转发操作

/**
	 *  forward:转发到一个页面
	 *  /hello.jsp 转发当前项目下的hello.jsp
	 *  
	 *  forward:/hello.jsp, 视图解析器不会在这个返回值加前后缀
	 *  forward:/hello.jsp 一定要加上/,如果不加/就是相对路径,容易出问题
	 */
	@RequestMapping("/hello3")
	public String hello3(){
		
		return "forward:/hello.jsp";
	}
   
    /**
	 *  forward:转发到一个请求
	 */
	@RequestMapping("/hello4")
	public String hello4(){
		
		return "forward:/hello3";
	}

重定向redirect

/**
	 *  重定向到hello.jsp页面 , 视图解析器不会在这个返回值加前后缀
	 *  转发:   forward: 转发的路径
	 *  重定向: redirect:重定向的路径
	 *  	    /hello.jsp 代表就是从当前项目下开始,SpringMvc会为路径自动的拼接上项目名	
	 */
	@RequestMapping("/hello5")
	public String hello5(){
		
		return "redirect:/hello.jsp";
	}
	
	/**
	 *  重定向一个请求
	 */
	@RequestMapping("/hello6")
	public String hello6(){
		
		return "redirect:/hello5";
	}

 

视图解析流程

  1. 任何方法的返回值,最终都会被包装成ModelAndView对象。

2. 该方法处理视图渲染流程,将域中的数据在页面展示:页面就是用来渲染模型数据的。

    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  // 来到页面的方法

3. 调用render(mv, request, response);渲染页面

4. View 和 ViewResolver 

  ViewResolver的作用是根据视图名(方法的返回值)得到View对象。

public interface ViewResolver {

	/**
	 * Resolve the given view by name.
	 * <p>Note: To allow for ViewResolver chaining, a ViewResolver should
	 * return {@code null} if a view with the given name is not defined in it.
	 * However, this is not required: Some ViewResolvers will always attempt
	 * to build View objects with the given name, unable to return {@code null}
	 * (rather throwing an exception when View creation failed).
	 * @param viewName name of the view to resolve
	 * @param locale Locale in which to resolve the view.
	 * ViewResolvers that support internationalization should respect this.
	 * @return the View object, or {@code null} if not found
	 * (optional, to allow for ViewResolver chaining)
	 * @throws Exception if the view cannot be resolved
	 * (typically in case of problems creating an actual View object)
	 */
	View resolveViewName(String viewName, Locale locale) throws Exception;

}

5. 怎么根据方法的返回值(视图名)得到View对象?

   所有配置的视图解析器都会尝试根据视图名(方法的返回值)得到View(视图)对象;如果能得到View对象就返回,得不到就换下一个视图解析器。

protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
			HttpServletRequest request) throws Exception {

		for (ViewResolver viewResolver : this.viewResolvers) {
            // ViewResolver视图解析器根据方法的返回值,得到一个View对象
			View view = viewResolver.resolveViewName(viewName, locale);
			if (view != null) {
				return view;
			}
		}
		return null;
	}

  

调用View对象的render方法

@Override
	public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		if (logger.isTraceEnabled()) {
			logger.trace("Rendering view with name '" + this.beanName + "' with model " + model +
				" and static attributes " + this.staticAttributes);
		}

		Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
		prepareResponse(request, response);
        // 渲染要给页面输出的所有数据
		renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
	}

 InternalResourceView类

@Override
	protected void renderMergedOutputModel(
			Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// Expose the model object as request attributes.
        // 将模型中的数据放在请求域中
		exposeModelAsRequestAttributes(model, request);

		// Expose helpers as request attributes, if any.
		exposeHelpers(request);

		// Determine the path for the request dispatcher.
		String dispatcherPath = prepareForRendering(request, response);

		// Obtain a RequestDispatcher for the target resource (typically a JSP).
		RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
		if (rd == null) {
			throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
					"]: Check that the corresponding file exists within your web application archive!");
		}

		// If already included or response already committed, perform include, else forward.
		if (useInclude(request, response)) {
			response.setContentType(getContentType());
			if (logger.isDebugEnabled()) {
				logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
			}
			rd.include(request, response);
		}

		else {
			// Note: The forwarded resource is supposed to determine the content type itself.
			if (logger.isDebugEnabled()) {
				logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
			}
			rd.forward(request, response);
		}
	}

  总结: 视图解析器只是为了得到视图对象;视图对象才能真正的转发(将模型数据全部放在请求域中)或者重定向到页面;视图对象才能真正的渲染视图。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值