您的位置:首页 > 编程语言 > Java开发

spring in action 4 第6章 视图分发

2016-11-19 13:12 435 查看
spring 4.0 原生支持13种视图解析器




从spring3.2版本开始,spring支持上述13种解析器,但是spring 3.1不支持Tiles 3 TilesViewResolver,其它的12种都支持.

视图解析器所在的配置文件
@Configuration
@EnableWebMvc
@ComponentScan("_5BuildingSpringwebapplications")
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
配置视图解析器核心代码
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
对应在xml中配置时,如下示,配置在spring应用上下文中
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceViewResolver" />
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
下面是示例的逻辑视图名与物理文件的对应关系,注意最后的示例与前两个示例的区别

home resolves to /WEB-INF/views/home.jsp
productList resolves to /WEB-INF/views/productList.jsp
books/detail resolves to /WEB-INF/views/books/detail.jsp
通常在使用jsp的时候都使用JSTL,但是InternalResourceViewResolver的功能相对比较简单,因此需要将其替换为JstlView,如下示,
在使用jstlview之前,需要在项目里引入jstl相关的jar包
build.gradle配置
compile "javax.servlet:jstl:$jstlVersion"
gradle.properties配置
jstlVersion = 1.2
InternalResourceViewResolver被JstlView替换

@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 class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
spring提供两种jsp标签库.

One tag library renders HTML
form tags that are bound to a model attribute. The other has a hodgepodge of utility
tags that come in handy from time to time.
第一种标签库,即表单绑定的jsp标签库包含14个标签,这些标签与html原生标签是有区别的,spring的标签可以获取model对象的属性值.其中一个标签可以将error信息反馈到结果页面中,即下文中提到的errors.
使用这些Spring标签的方法就是在jsp页面中声明.如下示
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
在上述的声明语句中,prefix="sf"里的"sf"由用户自定义,用于与原生的html标签做区别,比如也可以定义成这样,
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="springformtag" %>
这14个标签如下图示,注意标签前的前缀,这里的前缀是sf,因为之前在spring标签声明时定义了prefix="sf",如果声明时定义的不是sf,在使用时就不能照搬下面的用法了.



很难在一个页面中把上述所有标签的使用都示例出来.下面将结合书中的示例系统说明<sf:form>, <sf:input>, and <sf:password>这三个标签的使用方法.
在第5章中写过一个用户注册页面,当时的写法如下所示
<body>
<h1>Register</h1>
<form method="POST">
First Name: <input type="text" name="firstName" /><br />
Last Name: <input  type="text" name="lastName" /><br />
Username: <input type="text"   name="username" /><br />
Password: <input type="password"  name="password" /><br /> <input type="submit" value="Register" />
</form>
</body>
下面是使用了spring标签的写法
<body>
<h1>Register</h1>
<sf:form method="POST" commandName="spitter">
First Name: <sf:input path="firstName" /><br />
Last Name: <sf:input path="lastName" /><br />
Email: <sf:input path="email" /><br />
Username: <sf:input path="username" /><br />
Password: <sf:password path="password" /><br />
<input type="submit" value="Register" />
</sf:form>
</body>
<sf:form> 标签与HTML <form> 标签的功能类似,但是它指定了commandName属性,该属性绑定了一个model对象.这要求逻辑视图包含一个同名的model对象,因此需要对原来的控制器做相应的修改
原contrller SpitterController.java中的showRegistrationForm方法
@RequestMapping(value = "/register", method = RequestMethod.GET)
public String showRegistrationForm() {
return "registerForm";
}
修改后的代码,可以看到修改后,该方法在返回逻辑视图前在逻辑视图中增加了一个名为spitter的model属性,其实可以不用明确指定对象名,因为jsp页面中的对象名与类名一致,这与spring指定的默认对象名相同(类名首字母小写).因此添加属性的代码可写成model.addAttribute(new Spitter())
@RequestMapping(value = "/register", method = RequestMethod.GET)
public String showRegistrationForm(Model model) {
model.addAttribute("spitter",new Spitter());
return "registerForm";
}
回到使用的spring标签的jsp页面中,First Name: <sf:input path="firstName" />表示该输入框绑定的是new Spitter()类的firstName成员变量.注意,该成员变量名JSP页面中不能写错,如果写成First Name: <sf:input path="firstNamexxxx" />,那么运行时会报错.依此类推,
Last Name: <sf:input path="lastName" />表示该输入框对应的是new Spitter()类的lastName成员变量..等等.再次声明,成员变量名在JSP页面中不要写错.
假如在输入框中输入如下内容



那么该表单提交后,将向后台传递一个firstName为11,lastName为22,email为11@22.com,username为1122的Spitter的对象.
在SpitterController.java的processRegistration方法中增加了一行输出可以用来验证对象的成员变量是否是我们在jsp页面的输入



输出结果



注意,如果在域对象spitter的定义中加入了校验,上述的结果是不可能成功的,因为我们在jsp页面中的输入并不满足校验的条件,因此需要将spitter定义中的校验取消掉,如下图示



补充一个第5章中的知识点.回到上述的JSP页面中,可以看到该form表单中并没有写明action属性,如果没有写明的话,提交该表单时将默认返回打开该页面时使用逻辑视图名,但是与打开该页面时视图对应的get方法不同,提交表单时要求逻辑视图对应post方法.下图示



回到校验的话题,如果在上述实验中我们没有取消在域对象spitter定义时给予的校验,那么在校验失败时,如何在jsp页面中向用户展示错误信息呢?

下面先还原在spitter对象定义中给予的检验,如下图示
package _5BuildingSpringwebapplications.domain;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.validator.constraints.Email;

public class Spitter {
private Long id;

@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;

public Spitter() {
}

public Spitter(String username, String password, String firstName, String lastName, String email) {
this(null, username, password, firstName, lastName, email);
}

public Spitter(Long id, String username, String password, String firstName, String lastName, String email) {
this.id = id;
this.username = username;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

@Override
public boolean equals(Object that) {
return EqualsBuilder.reflectionEquals(this, that, "firstName", "lastName", "username", "password", "email");
}

@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, "firstName", "lastName", "username", "password", "email");
}
}
在classpath根目录下新建ValidationMessages.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.
registerForm.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
<%@ page session="false"%>
<html>
<head>
<title>Spittr</title>
<link rel="stylesheet" type="text/css"
href="<c:url value="/resources/style.css" />">
</head>
<body>
<h1>Register</h1>
<sf:form method="POST" commandName="spitter">
<sf:errors path="*" element="div" cssClass="errors" />
First Name: <sf:input path="firstName" />
<!--             	<span id="firstName.errors">size must be between 2 and 30</span> -->
<br />
Last Name: <sf:input path="lastName" />
<!--             <span id="lastName.errors">size must be between 2 and 30</span> -->
<br />
Email: <sf:input path="email" />
<!--             <span id="email.errors">size must be between 2 and 30</span> -->
<br />
Username: <sf:input path="username" />
<!--             <span id="username.errors">size must be between 2 and 30</span> -->
<br />
Password: <sf:password path="password" />
<!--             <span id="password.errors">size must be between 2 and 30</span> -->
<br />
<input type="submit" value="Register" />
</sf:form>
</body>
</html>
结果




除了表单绑定的标签库外,spring还提供另一种JSP标签库.该标签库是spring最早包含的标签库.
引用方法,在JSP页面中添加
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
与表单绑定的标签库在引用方法上的区别在于uri上,
通用标签库的uri是
uri="http://www.springframework.org/tags"
而表单绑定的标签库的引用uri是
uri="http://www.springframework.org/tags/form"
标签描述



上图中的某些标签在表单绑定的标签库中已经被淘汰了.<s:bind>比如.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  in action srping