《Spring实战》读书笔记-第6章 渲染Web视图,java基础入门第二版pdf百度云
Spring提供了两种支持JSP视图的方式:
InternalResourceViewResolver会将视图名解析为JSP文件。另外,如果在你的JSP页面中使用了JSP标准标签库(JavaServer Pages Standard Tag Library, JSTL)的话,InternalResourceViewResolver能够将视图名解析为JstlView形式的JSP文件,从而将JSTL本地化和资源bundle变量暴露给JSTL的格式化(formatting)和信息(message) 标签。
Spring提供了两个JSP标签库,一个用于表单到模型的绑定,另一个提供了通用的工具类特性。
不管使用JSTL,还是准备使用Spring的JSP标签库,配置解析JSP的视图解析器都是非常重要的。尽管Spring还有其他的几个视图解析器都能将视图名映射为JSP文件,但就这项任务来讲,InternalResourceViewResolver是最简单和最常用的视图解析器。
配置适用于JSP的视图解析器
InternalResourceViewResolver遵循一种约定,会在视图名上添加前缀和后缀,进而确定一个Web应用中视图资源的物理路径。
通用的实践是将JSP文件放到Web应用的WEB-INF目录下,防止对它的直接访问。假设逻辑视图名为home,那么可以确定物理视图的路径就是逻辑视图名home再加上“/WEB-INF/views/”前缀和“.jsp”后缀。
InternalResourceViewResolver解析视图时,会在视图名上添加前缀和后缀
当使用@Bean注解的时候,我们可以按照如下的方法配置InternalResourceViewResolver,使其在解析视图时,遵循上述的约定。
@Bean
public ViewResolver viewResolver(){ // 配置jsp视图解析器
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
作为替代方案,如果更喜欢使用基于XML的Spring配置,那么可以按照如下的方式配置InternalResourceViewResolver
InternalResourceViewResolver配置就绪之后,它就会将逻辑视图名解析为JSP文件,如下所示:
home将会解析为“/WEB-INF/views/home.jsp”
productList将会解析为“/WEB-INF/views/productList.jsp”
books/detail将会解析为“/WEB-INF/views/books/detail.jsp”
重点看一下最后一个样例。当逻辑视图名中包含斜线时,这个斜线也会带到资源的路径名中。因此,它会对应到prefix属性所引用目录的子目录下的JSP文件。这样的话,我们就可以很方便地将视图模板组织为层级目录,而不是将它们都放到同一个目录之中。
解析JSTL视图
如果JSP使用JSTL标签来处理格式化和信息的话,那么我们会希望InternalResourceViewResolver将视图解析为JstlView。
JSTL的格式化标签需要一个Locale对象,以便于恰当地格式化地域相关的值,如日期和货币。信息标签可以借助Spring的信息资源和Locale,从而选择适当的信息渲染到HTML之中。通过解析JstlView,JSTL能够获得Locale对象以及Spring中配置的信息资源。
如果想让InternalResourceViewResolver将视图解析为JstlView,而不是InternalResourceView的话,那么我们只需设置它的viewClass属性即可:
@Bean
public ViewResolver viewResolver(){ // 配置jsp视图解析器
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
return resolver;
}
同样,我们也可以使用XML完成这一个任务:
不管使用Java配置还是使用XML,都能确保JSTL的格式化和信息标签能够获得Locale对象以及Spring中配置的信息资源。
使用Spring的JSP库
Spring提供了两个JSP标签库,用来帮助定义Spring MVC Web的视图。其中一个标签库会用来渲染HTML表单便签,这些标签可以绑定model中的某个属性。另外一个标签库包含了一些工具类标签,我们随时都可以非常便利地使用它们。
我们将会看到如何将Spittr应用的注册表单绑定到模型上,这样表单就可以预先填充值,并且在表单提交失败后,能够展现校验错误。
将表单绑定到模型上
Spring的表单绑定JSP标签库包含了14个标签,它们中的大多数都用来渲染HTML中的表单标签。但是,它们与原生HTML标签的区别在于它们会绑定模型中的一个对象,能够根据模型中对象的属性填充值。标签库中还包含了一个为用户展示错误的标签,它会将错误信息渲染到最终的HTML之中。
为了使用表单绑定库,需要在JSP页面中对其进行声明:
<%@ taglib prefix=“sf” uri=“http://www.springframework.org/tags/form” %>
需要注意,我们将前缀指定为“sf”,但通常也可能使用“form”前缀,可以自定义前缀。
在声明完表单绑定标签库之后,你就可以使用14个相关的便签了。如下表
| JSP标签 | 描述 |
| — | — |
| <sf:checkbox>
| 渲染成一个HTML 标签,其中type属性设置为checkbox |
| <sf:checkboxes>
| 渲染成多个HTML 标签,其中type属性设置为checkbox |
| <sf:errors>
| 在一个HTML 中渲染输入域的错误 |
| <sf:form>
| 渲染成一个HTML 标签,并为其内部标签暴露绑定路径,用于数据绑定 |
| <sf:hidden>
| 渲染成一个HTML 标签,其中type属性设置为hidden |
| <sf:input>
| 渲染成一个HTML 标签,其中type属性设置为text |
| <sf:label>
| 渲染成一个HTML 标签 |
| <sf:option>
| 渲染成一个HTML 标签,其中selected属性根据所绑定的值进行设置 |
| <sf:options>
| 按照绑定的集合、数组或Map,渲染成一个HTML 标签的列表 |
| <sf:password>
| 渲染成一个标签,其中type属性设置为password |
| <sf:radiobutton>
| 渲染成一个标签,其中type属性设置为radio |
| <sf:select>
| 渲染为一个HTML 标签 |
| <sf:textarea>
| 渲染为一个HTML 标签 |
我们在Spittr的样例中,在注册JSP中可以使用<sf:form>
、<sf:input>
和<sf:password>
WW
<sf:form method=“POST” commandName=“spitter” >
First Name:<sf:input path=“firstName”/>
Last Name:<sf:input path=“lastName” />
Email:<sf:input type=“email” path=“email” />
Username: <sf:input path=“username”/>
Password: <sf:password path=“password”/>
</sf:form>
<sf:form>
会渲染一个HTML <form>
标签,但它也会通过commandName属性构建针对某个模型对象的上下文信息。在其他的表单绑定标签中,会引用这个模型对象的属性。
在之前的代码中,我们将commandName属性设置为spitter。因此,在模型中必须要有一个key为spitter的对象,否则的话,表单不能正常渲染(会出现JSP错误)。这意味着我们需要修改一下SpitterController,以确保模型中存在以spitter为key的Spitter对象:
@RequestMapping(value="/register", method=GET)
public String showRegistrationForm(Model model) {
model.addAttribute(new Spitter());
return “registerForm”;
}
修改后,模型中的key根据对象类型推断得出spitter就是新增的Spitter实例。
回到这个表单中,前四个输入域将HTML<input>
标签改成了<sf:input>
。这个标签会渲染成一个HTML <input>
标签,并且type属性将会设置为text。我们在这里设置了path属性,<input>
标签的value属性值将会设置为模型对象中path属性所对应的值。
对于password输入域,我们使用<sf:password>
来代替<sf:input>
。<sf:password>
与<sf:input>
类似,但是它所渲染的HTML <input>
标签中,会将type属性为password,这样当输入的时候,它的值不会直接明文显示。
值得注意的是,从Spring 3.1开始,<sf:input>
标签能够允许我们指定type属性,这样的话,除了其他可选的类型外,还能指定HTML5特定类型的文本域,如date、range和email。
Email: <sf:input path=“email” type=“email” />
为了指导用户矫正错误,我们需要使用<sf:errors>
如果存在校验错误的话,请求中会包含错误的详细信息,这些信息是与模型数据放到一起的。我们所需要做的就是到模型中将这些数据抽取出来,并展现给用户。
<sf:form method=“POST” commandName=“spitter”>
First Name: <sf:input path=“firstName” />
<sf:errors path=“firstName”/>
…
</sf:form>
尽管值展示了将<sf:errors>
用到First Name输入域的场景,
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
但是它可以按照同样简单的方式用到注册表单的其他输入域中。在这里,它的path属性设置成了firstName,也就是指定了要显示Spitter模型对象中哪个属性的错误。如果firstName属性没有错误的话,那么<sf:errors>
不会渲染任何内容。但如果有校验错误的话,那么将会在HTML<span>
标签中显示错误信息。
现在,我们已经可以为用户展现错误信息,这样他们就能修正这些错误了。我们还可以修改错误的样式,使其更加突出显示。为了做到这一点,可以设置cssClass属性:
<sf:form method=“POST” commandName=“spitter”>
First Name: <sf:input path=“firstName” />
<sf:errors path=“firstName” cssClass=“error”/>
…
</sf:form>
定义这个css样式
span.error {
color: red;
}
展示显示结果
在表单输入域的旁边展现校验错误信息
除了这种方式,还有另一种处理校验错误方式就是将所有的错误信息在同一个地方进行显示。为了做到这一点,我们可以移除每个输入域上的<sf:errors>
元素,并将其放到表单的顶部
<sf:form method=“POST” commandName=“spitter”>
<sf:errors path="*" element=“div” cssClass=“error”/>
…
</sf:form>
跟之前相比,值得注意的不同之处在于它的path被设置成了“*”。这是一个通配符选择器,会告诉<sf:errors>
展现所有属性的所有错误。
同样需要注意的是,我们将element属性设置成了div。默认情况下,错误都会渲染在HTML 标签中,如果只显示一个错误的话,这是不错的选择。但是,如果要渲染所有输入域的错误的话,很可能要展现不止一个错误,这时候使用<span>
标签(行内元素)就不合适了。像<div>
这样的块级元素会更为合适。因此,我们可以将element属性设置成了div。
像之前一样,cssClass属性被设置errors,这样我们就能为<div>
设置样式了。
div.errors {
background-color: #ffcccc;
border: 2px solid red;
}
现在,我们在表单的上方显示所有的错误,这样页面布局可能会更加容易一些。但是,我们还没有着重显示需要修正的输入域。通过为每个输入域设置cssErrorClass属性,这个问题很容易解决。我们也可以将每个label都替换为<sf: label>
,并设置它的cssErrorClass属性。如下就是做完必要修改后的FirstName输入域:
<sf:form method=“POST” commandName=“spitter”>
<sf:label path=“firstName” cssErrorClass=“error”>First Name</sf:label>:
<sf:input path=“firstName” cssErrorClass=“error” />
…
</sf:form>
<sf:label>
标签像其他的表单绑定标签一样,使用path来指定它属于模型对象中的哪个属性。在本例中,我们将其设置为firstName,因此它会绑定Spitter对象的firstName属性。假设没有校验错误的话,它将会渲染为如下的HTML <label>
元素:
First Name
就其自身来说,设置<sf:label>
的path属性并没有完成太多的功能,但是,我们还同时设置了cssErrorClass属性。如果它所绑定的属性有任何错误的话,在渲染得到的<label>
元素中,class属性将会被设置为 error,如下所示:
First Name
与之类似,<sf:input>
标签的cssErrorClass属性被设置为error,如果有任何校验错误,class属性将会被设置为error。下面设置css
label.error {
color: red;
}
input.error {
background-color: #ffcccc;
}
为了让这些错误信息更加易读,我们重新改造Spitter类
@NotNull
@Size(min=5, max=16,message = “{username.size}”)
private String username;
@NotNull
@Size(min=5, max=25,message = “{password.size}”)
private String password;
@NotNull
@Size(min=2, max=30,message = “{firstName.size}”)
private String firstName;
@NotNull
@Size(min=2, max=30,message = “{lastName.size}”)
private String lastName;
@NotNull
@Email(message = “{email.valid}”)
private String email;
对于上面每个域,我们都将其@Size注解的messgae设置为一个字符串,这个字符串是用大括号括起来的。如果没有大括号的话,message中的值将会作为展现给用户的错误信息。但是使用了大括号之后,我们使用的就是属性文件中的某一属性,该属性包含了实际的信息。
接下来需要做的就是创建一个名为ValidationMessage.properties的文件,并将其放在根类路径下:
firstName.size=First name must be between {min} and {max} characters long.
lastName.size=Last name must be between {min} and {max} characters long.
username.size=Username must be between {min} and {max} characters long.
password.size=Password must be between {min} and {max} characters long.
email.valid=The email address must be valid.
ValidationMessage.properties文件中每天信息的key值对应于注解中message属性占位符的值。同时,最小和最大长度以占位符的方式({min}和{max})保存文件中,它们会引用@Size注解上所设置的min和max属性。
当用户提交的注册表单校验失败的话,他们在浏览器中应该可以看到如下界面。
显示校验错误,其中这些对用户友好的信息是从属性文件中获取到的
我们可以按需创建任意数量的ValidationMessage.properties文件,使其涵盖我们想支持的所有语言和地域。
Spring通用的标签库
除了表单绑定标签库之外,Spring还提供了更为通用的JSP标签库。
要使用Spring通用的标签库,我们必须要在页面上对其进行声明:
<%@ taglib uri=“http://www.springframework.org/tags” prefix=“s” %>
标签库声明之后,我们就可以使用下表的十个JSP标签了。
| JSP标签 | 描述 |
| — | — |
| <s:bind>
| 将绑定属性的状态导出到一个名为status的页面作用域属性中,与<s:path>
组合使用获取绑定属性的值 |
| <s:escapeBody>
| 将标签体中的内容进行HTML和/或JavaScript转义 |
| <s:hasBindErrors>
| 根据指定模型对象(在请求属性中)是否有绑定错误,有条件地渲染内容 |
| <s:htmlEscape>
| 为当前页面设置默认的HTML转义值 |
| <s:message>
| 根据给定的编码获取信息,然后要么进行渲染(默认行为),要么将其设置为页面作用域、请求作用域、会话作用域应用作用域的变量(通过使用var和scope属性实现) |
| <s:nestedPath>
| 设置嵌入式的path,用于<s:bind>
之中 |
| <s:theme>
| 根据给定的编码获取主题信息,然后要么进行渲染(默认行为),要么将其设置为页面作用域、请求作用域、会话作用域应用作用域的变量(通过使用var和scope属性实现) |
| <s:transform>
| 使用命名对象的属性编辑器转换命令对象中不包含的属性 |
| <s:url>
| 创建相对于上下文的URL,支持URI模板变量以及HTML/XML/JavaScript转义。可以渲染URL(默认行为),要么将其设置为页面作用域、请求作用域、会话作用域应用作用域的变量(通过使用var和scope属性实现) |
| <s:eval>
| 计算符合Spring表达式语言(Spring Expression Language SpEL)语法的某个表达式的值,然后要么进行渲染(默认行为),要么将其设置为页面作用域、请求作用域、会话作用域应用作用域的变量(通过使用var和scope属性实现) |
展现国际化信息
如果要修改JSP模板中的文本,就不那么容易,而且,没有办法根据用户的语言设置国际化这些文本。
例如:
Welcome to Spitter!
如果想把其中的文本做成国际化的版本,对于渲染文本来说,是很好的方案,文本能够位于一个或多个属性文件中。借助<s:message>
,我们可以将硬编码的欢迎信息替换为如下的形式:
按照这里的方式,<s:message>
将会根据key为spitter.welcome的信息源来渲染文本。
Spring有多个信息源的类,它们都实现了MessageSource接口。在这些类中,更为常见和有用的是ResourceBundleMessageSource。它会从一个属性文件中加载信息,这个属性文件的名称是根据基础名称(base name)衍生而来的。如下的@Bean方法配置了ResourceBundleMessageSource:
@Bean
public MessageSource messageSource(){
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename(“message”);
messageSource.setDefaultEncoding(“UTF-8”);
return messageSource;
}
在这个bean声明中,核心在于设置basename属性。你可以将其设置为任意你喜欢的值,在这里,我将其设置为message。将其设置为message后,ResourceBundleMessageSource就会试图在根路径的属性文件中解析信息,这些属性文件的名称是根据这个基础名称衍生得到的。
另外的可选方案是使用ReloadableResourceBundleMessageSource,它的工作方式与ResourceBundleMessageSource非常类似,但是它能够重新加载信息属性,而不必重新编译或重启应用。如下是配置ReloadableResourceBundleMessageSource的样例:
@Bean
public MessageSource messageSource(){
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename(“file:///etc/spittr/messages”);
messageSource.setCacheSeconds(10);
return messageSource;
}
这里的关键区别在于basename属性设置为在应用的外部查找。basename属性可以设置为类路径下(以“classpath:”作为前缀)、文件系统中(以“file:”作为前缀)或Web应用的根路径下(没有前缀)查找属性。
现在,我们来创建这些属性文件。首先创建默认的属性文件,名为message.properties。它要们位于根类路径下(如果使用ResourceBundleMessageSource的话),要么位于basename属性指定的路径下(如果使用ReloadableResourceBundleMessageSource的话)。对spittr.welcome信息来讲,它需要如下的条目:
spittr.welcome=Welcome to Spittr!
我们已经具备了对信息进行国际化的重要组成部分。例如,如果想要为语言设置为西班牙语的用户展示西班牙语的欢迎信息,那么需要创建另外一个名为message_es.properties的属性文件,并包含如下的条目:
spittr.welcome=Bienvenidos a Spittr!
创建URL
<s:url>
的主要任务就是创建URL,然后将其赋值给一个变量或者渲染到响应中。它是JSTL中<c:url>
标签的替代者,但是它具备几项特殊的技巧。
<s:url>
会接受一个相对Servlet上下文的URL,并在渲染的时候,预先添加上Servlet上下文路径。例如,考虑如下<s:url>
的基本用法:
<a href="<s:url href="/spitter/register" />">Register
如果应用的Servlet上下文名为spittr,那么在响应中将会渲染如下的HTML:
Register
这样,我们在创建URL的时候,就不必再担心Servlet上下文路径是什么了,<s:url>
将会负责这件事。
另外,我们还可以使用<s:url>
创建URL,并将其赋值给一个变量供模板在稍后使用:
<s:url href="/spitter/register" var=“registerUrl” />
Register
默认情况下,URL是在页面作用域内创建的。但是通过设置scope属性,我们可以让<s:url>
在应用作用域内、会话作用域内或请求作用域内创建URL:
<s:url href="/spitter/register" var=“registerUrl” scope=“request” />
《Spring实战》读书笔记-第6章 渲染Web视图,java基础入门第二版pdf百度云相关推荐
- 《图解HTTP》读书笔记--第1章 了解Web及网络基础
写在前面:本文仅供个人学习使用,如有侵权,请联系删除.文章中所用图片绝大多数来源于<图解HTTP>,请读者支持原版. 文章目录 第1章 了解Web及网络基础 1.1 使用HTTP协议访问W ...
- java基础入门第二版第二章课后答案,知识点总结+面试题解析
准备过程 先说说我自己的情况,我2016先在蚂蚁实习了将近三个月,然后去了我现在的老东家,三年多工作经验,可以说毕业后就一直老老实实在老东家打怪升级,虽说有蚂蚁的实习经历,但是因为时间太短,还是有点虚 ...
- spring boot 503_Spring实战读书笔记第4章 面向切面的Spring
本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 在软件开发中,散布于应用中多的功能被称为横切关注点(cross-cutting con ...
- hive实战读书笔记(第9章)Hive性能优化
hive用户面临的一个比较大的问题是,用户需要等待较长的响应时间,与传统关系数据库查询的性能相比,hive响应速度慢的令人发指 本章介绍一套诊断改进hive查询性能的系统方法,通过这个过程,将单个hi ...
- jQuery实战读书笔记(第一章至第四章)
2019独角兽企业重金招聘Python工程师标准>>> 第一章 jQuery 基础 1. 包装器 jQuery对包装器(Wrapper)或包装集(wrapped set)进行操作,即 ...
- maven实战--读书笔记之第一章和第二章
第一章:Maven简介 1.本书为国内社区公认的专家徐晓斌所写,本书基于maven3.0所编写,maven是非常优秀的建模工具,maven最大化的消除了构建的重复,抽象了构建生命,他还有一个优点,帮助 ...
- hive实战读书笔记(第4章)hive表DDL
schema-on-read hadoop提供了存储和处理任何结构化,半结构化,非结构化数据的能力,hive允许用户在这些数据上创建一个元数据层,并使用sql接口来访问该层. hive并不是一个数据库 ...
- Java8实战读书笔记-第3章 λ表达式
可以在函数式接口上使用λ表达式,函数式接口就是只定义一个抽象方法的接口(函数式接口只可以定义一个抽象接口,但是可以定义多个默认方法). Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提 ...
- Spring实战读书笔记 高级装配(1)
一.条件化装配 1. 当你希望你的bean在特殊条件下才能装配时,比如在声明了特定的bean时,或者配置了特定的环境变量的时候.那么就可以使用 @Conditional注解,可以用在 @Bean注解下 ...
最新文章
- 使用Zabbix通过BMC管理口监控HP服务器
- 正则表达式的学习二:正则表达式的匹配规则总结
- BZOJ2743 [HEOI2012]采花 【离线 + 树状数组】
- vc 国际化的资源文件处理
- 作为一个女程序员,有感而发
- zybo上运行linux,Zybo开发板linux作业系统移植
- 前端开发负责人修炼指北
- 计算机恢复数据怎么恢复,电脑数据恢复,详细教您电脑数据如何恢复
- 数字孪生典型应用案例
- 黑马程序员pink老师Javascript语法基础 | 总结
- Win11更新提示安装错误0x80248007怎么办?0x80248007下载错误解决方法汇总
- 联想小新pro16和联想小新pro14 2022款哪个好
- 计算机网络共享后如何设置不输出密码,取消电脑网络共享安全账号密码直接进入的设置方法...
- Android 超高仿微信图片选择器
- codevs 1419 藤原妹红
- 如何用迅雷或QQ旋风下载百度云上的资源?
- php制作万年历的步骤_制作一个php万年历
- Web笔记之移动端开发
- python教学视频m_python学习(33)----Python 中 -m 的典型用法、原理解析与发展演变(转)...
- Linux Shell脚本 Linux C程序 获取指定的范围内 or 系统可用端口
热门文章
- 基于php的bbs论坛教程,基于PHPMySQL技术BBS论坛
- 2016 province java c-1 有奖竞猜
- 秀一款 Python 轻量级搜索工具 -- Whoosh
- 如何找到专业学术期刊的“大牛”
- 2021年危险化学品生产单位安全生产管理人员考试题及危险化学品生产单位安全生产管理人员作业考试题库
- Discuz!开发之判断蜘蛛(机器人)访问函数checkrobot()介绍
- Apache报错0x6eec38dc指令引用的0x00000000内存。该内存不能为read。
- 初学者随记03:uniapp中使用阿里云小图标
- php.ini 优化 oa,OA办公系统常见问题解答
- SSCOM串口调试助手自定义波特率