1.Spring MVC如何解析视图
请求处理方法执行完成后,最终返回一个 ModelAndView对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个ModelAndView 对象,它包含了逻辑名和模型对象的视图。
• Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是Excel、JFreeChart 等各种表现形式的视图。
• 对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦。
原理:对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 会在内部将它们装配成一个ModelAndView 对象,Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终调用view对象的render方法得到结果。
2.视图
• 视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。
• 为了实现视图模型和具体实现技术的解耦,Spring 在org.springframework.web.servlet 包中定义了一个高度抽象的 View
接口:
• 视图对象由视图解析器负责实例化。由于视图是无状态(就是每一次请求都会创建一个新的输出对象)的,所以它们不会有线程安全的问题
• 常用的视图实现类:主要是前三个类
3.视图解析器
• SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。
• 视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象。
• 所有的视图解析器都必须实现 ViewResolver 接口:
• 常用的视图解析器实现类:主要前两个
我们可以选择一种视图解析器或混用多种视图解析器
• 每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高。
• SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出 ServletException 异常
4.InternalResourceViewResolver
• JSP 是最常见的视图技术,可以使用InternalResourceViewResolver 作为视图解析器:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--视图路径,转发后会到这去找文件-->
<property name="prefix" value="/WEB-INF/views/"></property>
<!--找后缀为jsp的文件-->
<property name="suffix" value=".jsp"></property>
</bean>
若项目中使用了 JSTL,则 SpringMVC 会自动把视图由InternalResourceView 转为 JstlView
• 若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中配置国际化资源文件
dispatcher-servlet.xml
<!--配置国际化资源文件-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>
在类路径下创建国际化资源文件
i18.properties
i18n.username=Username
i18n.password=Password
i18n_en_US.properties
i18n.username=Username
i18n.password=Password
i18n_zh_CN.properties
i18n.username=用户名
i18n.password=密码
然后导入JSTL的两个jar包
测试类:
private static final String SUCCESS = "success";
@RequestMapping("/testView")
public String testView(){
System.out.println("Test View");
return SUCCESS;
}
success.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:message key="i18n.username"></fmt:message>
<br/>
<fmt:message key="i18n.password"></fmt:message>
- 注意:我一开始运行后随便点击以前的路径,都会出现500,出现 The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml 异常。
- 我的原因是 Tomcat中缺少这两个jar包,虽然刚刚jar已经导入项目,但是没有放入Tomcat下,直接复制两个jar放入项目路径下的out\artifacts\项目名\WEB-INF\lib中,就可以运行了
最后注意不要在谷歌浏览器测试国际化资源,我本以为哪里错了,谷歌浏览器切换成英文国际化资源还是不能变英文,我觉得原因是谷歌浏览器的英文语言为 en而不是en-US吧。在火狐浏览器就没问题
• 若希望直接响应通过 SpringMVC 渲染的页面,可以使用 mvc:viewcontroller 标签实现
注意:假设没有配置mvc:annotation-driven,那么一旦使用mvc:viewcontroller标签那么会导致其他的 Handler方法失效(Handler方法就是@Controller类下的那些方法),所以先加上,以后再学mvc:annotation-driven
dispatcher-servlet.xml
<!--配置直接转发页面-->
<mvc:view-controller path="/su" view-name="success"></mvc:view-controller>
<!--在实际开发中通常要配置 mvc:annotation-driven 标签-->
<mvc:annotation-driven></mvc:annotation-driven>
访问时直接:,就会跳转到目标页面- success.jsp
5. Excel 视图
若希望使用 Excel 展示数据列表,仅需要扩展SpringMVC 提供的 AbstractExcelView 或AbstractJExcel View 即可。实现 buildExcelDocument()方法,在方法中使用模型数据对象构建 Excel 文档就可以了。
• AbstractExcelView 基于 POI API,而AbstractJExcelView 是基于 JExcelAPI 的。
• 视图对象需要配置 IOC 容器中的一个 Bean,使用BeanNameViewResolver 作为视图解析器即可
<!--配置视图 BeanNameViewResolver 解析器:使用视图名来解析视图-->
<!--通过 order 属性来定义 视图解析器的优先级,order值越小优先级越高-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
• 若希望直接在浏览器中直接下载 Excel 文档,则可以设置响应头 Content-Disposition 的值为
attachment;filename=xxx.xls
注意:最好设置一下视图解析的优先级,使用order属性来指定,order的值越低优先级越高,InternalResourceViewResolver的优先级为Integer.MAV_VALUE,也就是优先级最低
例子:先配置好上面那个xml文件先
自定义的View类:
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.View;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class HelloView implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> map, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
httpServletResponse.getWriter().println("My View Time is " + new Date());
}
}
测试类
@RequestMapping("/testMyView")
public String testMyView(){
System.out.println("My View");
return "helloView";
}
如果遇到:HTTP Status 404 - /WEB-INF/views/helloView.jsp,则看看自定义的View是否有加入Spring中:
<!--配置自动扫描的包-->
<context:component-scan base-package="路径"></context:component-scan>
6.关于重定向
• 一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
• 如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理
– redirect:success.jsp:会完成一个到 success.jsp 的重定向的操作
– forward:success.jsp:会完成一个到 success.jsp 的转发操作