6.1 理解Web视图
SpringMVC提供了一个ViewResolver接口:
public interface ViewResolver{
View resolveViewName(String viewName,Locale locale)throw Exception;
}
resolveViewName()方法返回一个View实例,View是另外一个接口:
public interface View{
String getContetnType();
void renfer(Map<String,?> model,
HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
view的功能就是接受模型以及Servlet的request和response对象,并将输出结果渲染到response中。
编写这两个接口的实现,然后将渲染的内容放进response中,这个过程就完成了。
Spring底层将这个过程封装好了。并且针对不同场景有多个内置的实现。
视图解析器 | 描述 |
---|---|
BeanNameViewResolver | 将视图解析为Spring应用上下文中的bean,其中 bean的ID与视图的名字相同 |
ContentNegotiatingViewResolver | 通过考虑客户端需要的内容类型来解析视图, 委托给另外一个能够产生对应内容类型的视图 解析器 |
FreeMarkerViewResolver | 将视图解析为FreeMarker模板 |
InternalResourceViewResolver | 将视图解析为Web应用的内部资源(一般为 JSP) |
JasperReportsViewResolver | 将视图解析为JasperReports定义 |
ResourceBundleViewResolver | 将视图解析为资源bundle(一般为属性文件) |
TilesViewResolver | 将视图解析为Apache Tile定义,其中tile ID与视 图名称相同。注意有两个不同的 TilesViewResolver实现,分别对应于Tiles 2.0和 Tiles 3.0 |
UrlBasedViewResolver | 直接根据视图的名称解析视图,视图的名称会 匹配一个物理视图的定义 |
VelocityLayoutViewResolver | 将视图解析为Velocity布局,从不同的Velocity模 板中组合页面 |
VelocityViewResolver | 将视图解析为Velocity模板 |
XmlViewResolve | 将视图解析为特定XML文件中的bean定义。类 似于BeanName-ViewResolver |
XsltViewResolver | 将视图解析为XSLT转换后的结果 |
jsp技术是Web开发中最常使用的技术,所以InternalResourceViewResolver也是最常见的视图解析器。
6.2 创建jsp视图
Spring有两种支持JSP视图的方式:
- InternalResourceViewResolver将视图名解析成jsp
- Spring提供了两个JSP标签库,一个用于表单到模型的绑定,另外一个提供了通用的工具
6.2.1 配置适用于JSP的视图解析器
InternalResourceVIewResolver会在视图前后添加前缀和后缀,进而确定一个视图在应用中的物理路径。
使用@Bean注解配置:
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
在XML中配置:
<bean id="view"
class="org.springframwork.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"/>
- home将会解析为“/WEB-INF/views/home.jsp”
- productList将会解析为“/WEB-INF/views/productList.jsp”
- books/detail将会解析为“/WEB-INF/views/books/detail.jsp”
解析JSTL视图
如果JSP使用了JSTL来处理格式化和信息,InternalResourceVIewResolver会将视图解析为JstlView。
如果需要将视图解析为JstlView,需要设置viewClass属性:
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
return resolver;
}
在XML中可以这样设置:
<bean id="view"
class="org.springframwork.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"
p:viewClass="org.springframework.web.servlet.view.JstlView"/>
这样配置后可以保证JSTL的格式化和信息标签能获得Locale对象和Spring中配置的信息资源
6.2.2 使用Spring的JSP库
Spring提供了2个JSP标签库:一个标签库可以绑定model中的属性,渲染HTML表单标签,另外一个包含了工具类标签。
表单绑定库
首先声明
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
接着就能使用14个相关的标签
jsp界面如何使用:
<sf:form>会渲染一个HTML表单,commandName指定了model里绑定的key为spitter的对象,如果没有这个对象,就无法正常渲染。
@RequestMapping(value="/register",method=GET)
public String showRegistrationForm(Model model){
model.addAttribute(new Spitter());
return "registerForm";
}
这里后台返回了一个new Spitter()对象,前台表单的spitter是通过类型判断得到的。
<sf:errors>用法
<sf:errors>的path指定了firstName,如果Spitter中的firstName属性没有问题,那么<sf:errors>不会显示,否则它会在一个HTML<span>中显示错误信息。如果将path设置成"*",那么它会检查所有的属性的错误
<sf:label>
<sf:label>和其他的表单绑定标签一样,用path来指定model对象中的值,它的cssErrorClass属性设置成了error,当它的path值出现错误的时候,class就会被设置成error。
@NotNull
@Size(min=5,max=16,message="{usename.size}")
为了更好的提示错误信息,@Size中有个message信息,如果用"{}“包起来,说明是某个属性文件中的属性。如果没有使用”{}",就是直接提示的信息。
属性文件ValidationMessages.properties,它位于根类路径下
username.size = Username must be between {min} and {max} chacracters long
文件中的{min}和{max}回去引用@Size注解的值。
spring通用标签库
<%@ taglib uri="http://www.springframework.org/tags" prefix="s"%>
上面标签中的prefix可以是任意值
<s:message>实现国际化
如果web需要满足不同语言切换的需求,可以用<s:message>来实现,首先将原来写死的信息换成这样:
<h1><s:message code="spitter.welcom" /></h1>
这样<s:message>会根据key为spitter.welcom的信息源来渲染文本,接下来配置这样一个信息源:
Spring中的信息源类都实现了MessageSource接口,最常见的是ResourceBundleMessageSource。它会从一个属性文件中加载信息,属性文件是通过基础名称(base name)指定的
@Bean
public void MessageSource messageSource(){
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("message");
return messageSource;
}
上面这个bean将basename属性设置为"message"。指定之后,ResourceBundle-MessageSource就会视图再根路径去查找对应属性文件,然后解析数据。
也可以使用ReloadableResourceBundleMessageSource,使用方法如下:
@Bean
public MessageSource messageSource(){
Reloadable ResourceBundleMessageSource messageSource =
new RelaodableResourceBundleMessageSource();
messageSource.setBasename("file:///etc/spitter/message");
return messageSource;
}
这里和前面最大的区别是,前面是从类路径加载(“classpath: …”),这里是从磁盘中加载。
配置文件中可以指定属性名称:
pitter.welcom = Welcome to Spitter!