Spring实战-读书笔记(六)-渲染Web视图
2017-12-08 21:39
337 查看
渲染Web视图
理解视图解析
我们知道Controller方法返回逻辑视图的名称,DispatcherServlet将视图逻辑名称传递给视图实现类处理获得物理视图资源。Controller并不直接返回物理视图,而是返回逻辑视图名称,这样就很好的实现了解耦,保证了在不影响请求处理逻辑的情况下维护和修改视图。那么视图实现如果根据逻辑视图名称解析物理视图资源呢?Spring自带了13个视图解析器,能够将逻辑视图名转换为物理实现。BeanNameViewResolver
将视图解析为Spring应用上下文中的bean,其中bean的ID与视图的名字相同
ContentNegotiatingViewResolver
通过考虑客户端需要的内容类型来解析视图,委托给另外一个能够产生对应内容类型的视图解析器
FreeMarkerViewResolver
将视图解析为FreeMarker模板
InternalResourceViewResolver
将视图解析为Web应用的内部资源(一般为JSP)
JasperReportsViewResolver
将视图解析为JasperReports定义
ResourceBundleViewResolver
将视图解析为资源bundle(一般为属性文件)
TilesViewResolver
将视图解析为Apache Tile定义,其中tileID与视图名称相同。注意有两个不同的TilesViewResolver实现,分别对应于Tiles 2.0和Tiles 3.0
UrlBasedViewResolver
直接根据视图的名称解析视图,视图的名称会匹配一个物理视图的定义
VelocityLayoutViewResolver
将视图解析为Velocity布局,从不同的Velocity模板中组合页面
VelocityViewResolver
将视图解析为Velocity模板
XmlViewResolver
将视图解析为特定XML文件中的bean定义。类似于BeanName-ViewResolver
XsltViewResolver
将视图解析为XSLT转换后的结果
以上所有的视图实现类都是些了ViewResolver接口。这个接口的作用就是根据逻辑视图名称返回物理视图(即View接口)。
package org.springframework.web.servlet; import java.util.Locale; public interface ViewResolver { View resolveViewName(String viewName, Locale locale) throws Exception; }View接口的任务就是接受模型以及Servlet的request和response对象,并将输出结果渲染到response中。View接口有两个核心方法:
String getContentType(); void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
InternalResourceViewResolver视图实现
我们在java中最常用的视图技术就是jsp。InternalResourceViewResolver视图实现的作用就是将逻辑视图名称解析成一个jsp资源。我么看一下如果在Spring MVC中使用InternalResourceViewResolver。/** * 配置视图解析器 * * @return */ @Bean public ViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); // 在视图路径添加前缀 viewResolver.setSuffix(".jsp"); // 在视图路径添加后缀 viewResolver.setExposePathVariables(true); viewResolver.setExposeContextBeansAsAttributes(true); viewResolver.setViewClass(JstlView.class); //jsp中使用JSTL,将物理视图解析成JstlView return viewResolver; }
我们对InternalResourceViewResolver的配置都很基础和简单。它最终会将逻辑视图名解析为InternalResourceView实例,这个实例会引用JSP文件。但是如果这些JSP使用JSTL标签来处理格式化和信息的话,那么我们会希望InternalResourceViewResolver将视图解析为JstlView。JSTL的格式化标签需要一个Locale对象,以便于恰当地格式化地域相关的值,如日期和货币。信息标签可以借助Spring的信息资源和Locale,从而选择适当的信息渲染到HTML之中。通过解析JstlView,JSTL能够获得Locale对象以及Spring中配置的信息资源。如果想让InternalResourceViewResolver将视图解析为JstlView,而不是InternalResourceView的话,那么我们只需设置它的viewClass属性即可。
使用Spring的JSP库
Spring提供了两个JSP标签库,用来帮助定义Spring MVC Web的视图。其中一个标签库会用来渲染HTML表单标签,这些标签可以绑定model中的某个属性。另外一个标签库包含了一些工具类标签。表单标签
使用表单标签需要在jsp导入如下两行代码:<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%>
Sping web MVC提供的的表单标签库
<sf:checkbox>
渲染成一个HTML <input>标签,其中type属性设置为checkbox
<sf:checkboxes>
渲染成多个HTML <input>标签,其中type属性设置为checkbox
<sf:errors>
在一个HTML <span>中渲染输入域的错误
<sf:form>
渲染成一个HTML <form>标签,并为其内部标签暴露绑定路径,用于数据绑定
<sf:hidden>
渲染成一个HTML <input>标签,其中type属性设置为hidden
<sf:input>
渲染成一个HTML <input>标签,其中type属性设置为text
<sf:label>
渲染成一个HTML <label>标签
<sf:option>
渲染成一个HTML <option>标签,其selected属性根据所绑定的值进行设置
<sf:options>
按照绑定的集合、数组或Map,渲染成一个HTML <option>标签的列表
<sf:password>
渲染成一个HTML <input>标签,其中type属性设置为password
<sf:radiobutton>
渲染成一个HTML <input>标签,其中type属性设置为radio
<sf:radiobuttons>
渲染成多个HTML <input>标签,其中type属性设置为radio
<sf:select>
渲染为一个HTML <select>标签
<sf:textarea>
渲染为一个HTML <textarea>标签
使用表单标签
我们使用Spring提供的表单标签实现博客发布功能。实现后的界面如下。jsp代码实现。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf"%> <%@ taglib uri="http://www.springframework.org/tags" prefix="s"%> <%@ page session="false"%> <%@page isELIgnored="false"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="UTF-8"> <title>博客发布</title> <style type="text/css"> div .error { color: red; } </style> </head> <body> <h2> <s:message code="showWirteForm.title"></s:message> </h2> <%-- modelAttribute="aboutBlog" commandName="aboutBlogModel" --%> <sf:form method="POST" commandName="aboutBlog"> <div> <sf:label path="name" cssErrorClass="error"> <s:message code="showWirteForm.form.name"></s:message> </sf:label> <sf:input path="name" /> <sf:errors path="name" cssClass="error"></sf:errors> </div> <div> <sf:label path="title" cssErrorClass="error"> <s:message code="showWirteForm.form.title"></s:message> </sf:label> <sf:input path="title" /> <sf:errors path="title" cssClass="error"></sf:errors> </div> <div> <sf:label path="content" cssErrorClass="error"> <s:message code="showWirteForm.form.content"></s:message> </sf:label> <br> <sf:input type="textarea" path="content" style="width:300px;height:140px;" /> <sf:errors path="content" cssClass="error"></sf:errors> </div> <div> <sf:label path="description" cssErrorClass="error"> <s:message code="showWirteForm.form.description"></s:message> </sf:label> <sf:input path="description" /> <sf:errors path="description" cssClass="error"></sf:errors> </div> <div> <sf:label path="keyword" cssErrorClass="error"> <s:message code="showWirteForm.form.keyword"></s:message> </sf:label> <sf:input path="keyword" /> <sf:errors path="keyword" cssClass="error"></sf:errors> </div> <div> <button type="submit"><s:message code="showWirteForm.form.submit"></s:message></button> </div> </sf:form> </body> </html>
sf:from标签的commandName属性指定model名称,sf:from标签中的其它绑定标签会以这个model作为上下文。
sf:label标签中的path属性表示model中的属性值,如果这个属性没有通过校验,标签内容会按cssErrorClass指定的样式显示。一般配合Spring校验一起使用。
sf:input标签中的path属性表示model中的属性值。
sf:erors标签中的path属性表示model中的属性值,如果这个属性没有通过校验,将会显示不通过提示信息,提示信息会按cssClass指定的样式显示。一般配合Spring校验一起使用。
cssErrorClass
返回视图的Controller方法。
/** * 博客发布视图 * @param request * @return */ @RequestMapping(value = "/wirte", method = GET) public String showWirteForm(HttpServletRequest request,Model model) { model.addAttribute("aboutBlog", new AboutBlogModel()); return "showWirteForm"; }
在返回视图的同时想model里添加了new AboutBlogModel()对象,并以aboutBlog为key。这样在转发到jsp视图中sf:from的commandName属性不会因为找不到aboutBlog而报错。
处理博客发布的Controller方法。
/** * 博客发布操作 * 使用Spring MVC处理表单参数 * @param aboutBlogModel * @param errors * @param request * @return */ @RequestMapping(value = "/wirte", method = POST) public String wirte(@Valid @ModelAttribute("aboutBlog") AboutBlogModel aboutBlogModel,Errors errors,Model model) { if(errors.hasErrors()) { return "showWirteForm"; } String id = aboutBlogReq.add(aboutBlogModel); // 这里使用重定向,防止用户重复提交(比如多次点击刷新按钮) return "redirect:/blogManager/queryOne/" + id; }@Valid注解表示对AboutBlogModel进行校验,如果有校验不通过将会产生一个Errors对象,不通过的提示信息封装在Errors对象中。注意AboutBlogModel aboutBlogModel形参使用了@Valid注解标记,那么这个参数后边要紧跟着一个Errors对象,表示errors对象代表的是aboutBlogModel对象校验不通过信息。wirte()方法如果还有User对象需要校验,添加@Valid
User user,Errors userErrors参数即可。
@ModelAttribute注解表示aboutBlogModel对象在model中的key名称。如果不指定名称Spring将会按照对象类型生成key名称,例如AboutBlogModel对象的key名称为aboutBlogModel,User对象的key名称为user。
注意:这里@ModelAtrribute注解将aboutBlogModel对象在model里的key命名为aboutBlog,是为了能够在效验不通过的时候回显用户填写的信息(<sf:form method="POST" commandName="aboutBlog">)。
Spring web 实现国际化
我们注意到博客发布功能的jsp界面利用<s:message code=""/>标签引用了国际化信息。这里的国际化包括界面文字和效验不通过的提示信息。web是世界性的网络,应该根据不同地域用户在界面显示对应的语言,提供良好的交互,我们来看一下Spring如何实现信息的国际化。第一步:编写国际化资源文件
message目录下的文件是国际化文件。validationMessages目录是效验提示信息的国际化资源文件。文件名称带_zh_CH后缀的是简体中文的国际化资源文件,zh表示中国,CH表示大陆城市。不带有后缀的message.properties、ValidationMessages.properties为默认的国际化资源文件(我这里默认是英文)。
第二步:在Spring中配置国际化资源
/** * 配置国际化资源资源 * @return */ @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); //设置国际化资源文件的基础名称,默认在classpath查找指定的properties文件 //"message/message"表示在classpath路径下的message目录查询已message开头properties文件 //"validationMessages/ValidationMessages"表示在classpath路径下的validationMessages目录查询已ValidationMessages开头properties文件 messageSource.setBasenames("message/message","validationMessages/ValidationMessages"); //设置国际化资源文件编码 //注意:国际化资源文件的编码也要已UTF-8编码,否则会出现乱码 messageSource.setDefaultEncoding("UTF-8"); return messageSource; } /** * 配置Spring web效验功能提示信息的国际化资源 */ @Override public Validator getValidator() { LocalValidatorFactoryBean lv = new LocalValidatorFactoryBean(); lv.setProviderClass(HibernateValidator.class); lv.setValidationMessageSource(messageSource()); return lv; }
另外的可选方案是使用ReloadableResourceBundleMessageSource,它的工作方式与ResourceBundleMessageSource非常类似,但是它能够重新加载信息属性,而不必重新编译或重启应用。如下是配置ReloadableResourceBundleMessageSource的样例:
/** * 配置国际化资源资源 * @return */ @Bean public MessageSource messageSource() { ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); messageSource.setBasenames("classpath:message/message","classpath:validationMessages/ValidationMessages"); messageSource.setDefaultEncoding("UTF-8"); return messageSource; }
这里的关键区别在于basename属性设置为在应用的外部查找(而不ResourceBundleMessageSource那样在类路径下查找)。basename属性可以设置为在类路径下(以“classpath:”作为前缀)、文件系统中(以“file:”作为前缀)或Web应用的根路径下(没有前缀)查找属性。
第三部:引用国际化资源
在jsp中使用<s:message code="showWirteForm.form.name"></s:message>标签引用国际资源。
<sf:errors path="description" cssClass="error"></sf:errors>标签引用效验提示信息国际化资源。通过在效验注解的message属性引用,例如:
@NotBlank(message="{blog.model.AboutBlogModel.name.NotBlank}") private String name;国际化相关知识点可以参考:http://blog.csdn.net/gaoshanliushui2009/article/details/46276583
中文国际化效果展示。
相关文章推荐
- Spring实战4 (6)渲染Web视图
- 第6章 渲染Web视图---Apache Tiles 笔记2
- Spring Boot 与 kotlin 使用Thymeleaf模板引擎渲染web视图的方法
- Spring Boot 与 Kotlin使用Freemarker模板引擎渲染web视图
- Spring Boot☞ 使用freemarker模板引擎渲染web视图
- spring boot(三):使用JSP渲染Web视图
- spring(6) 渲染web视图
- Spring In Action 05 ---渲染Web视图
- Spring Boot 与 Kotlin使用Freemarker模板引擎渲染web视图
- 一头扎进springboot之使用Freemarker模板引擎渲染web视图
- 第6章-渲染WEB视图
- SpringMVC入门之五:渲染Web视图概述
- Spring学习笔记之渲染Web视图
- 《Spring实战》学习笔记-第六章:web视图解析
- Spring 实战-第六章-渲染Web视图-6.3使用Apache Tiles视图定义布局
- Spring Boot☞ 使用Thymeleaf模板引擎渲染web视图
- spring实战-将模型传递到视图中渲染
- Spring boot 使用Thymeleaf对web视图进行渲染
- web表单(1)--表单类&将表单渲染为HTML&在视图函数中处理表单
- 5-Spring Boot ( 使用JSP渲染Web视图 )