spring in action 4 第6章 视图分发

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为[email protected],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>比如.

时间: 2024-10-06 00:24:33

spring in action 4 第6章 视图分发的相关文章

【Spring】【笔记】《Spring In Action》第4章 面向切面的Spring

前导: 在软件开发中,分布于应用中多处的功能称为:横切关注点(cross-cutting concerns). 横切关注点从概念上是与应用的业务逻辑相分离的,将横切关注点与业务逻辑相分离是面向切面编程AOP要解决的. 4.1 什么是面向切面编程 横切关注点可以被模块化为特殊的类,这些类被称为切面. 4.1.1 AOP术语 通知 Advice 切面的工作 被称为通知. 通知定义了切面是什么.何时使用. Spring切面可以应用5种类型的通知: Before:在方法被调用之前调用通知 After:在

【Spring】【笔记】《Spring In Action》第5章 数据库处理

5.1 Spring数据访问原理 DAO 数据访问对象(data access object). DAO提供了数据读取和写入到数据库中的一种方式.他们应该以接口的方式发布功能,而应用程序的其他部分就可以通过接口来进行访问了. 实现了松耦合代码 5.1.1 Spring数据访问异常体系 不与特定的持久化方式相关联.这意味着可以使用Spring抛出一致的异常,而不用关心所选择的持久化方案. Spring的数据访问异常: CannotAcquireLockException CannotSeriali

导入spring in action 4 第5章源码到eclipse

第5章源码结构 源码里没有.setting文件和.classpath文件以及.project文件,直接导入则不能识别,因此需要新建一个项目,用导入文件的方式将源码的代码导入到Eclipse项目里.其实这种方式比直接把源码导入成项目要好的多,因为导入文件的方式是把源码里的文件复制到新项目里,在新项目里修改内容不会改变源码的内容,而如果直接把源码导入成项目,修改项目的内容时则是直接修改了源码. 很明显,源码中显示项目为Gradle的项目,因此在eclipse里新建一个Gradle项目 新建的项目命名

spring in action 4 第5章

代码结构 域对象 spittle.java package _5BuildingSpringwebapplications.domain; import java.util.Date; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; public class Spittle { private final Long id;

spring in action 4 6.3使用Apache Tiles

配置Tiles视图解析器 需要一个TilesConfigurer bean,该bean用于定位和加载tile定义,还需要一个TilesViewResolver用于将逻辑视图名与tile定义映射起来.在WebConfig.java中 @Configuration @EnableWebMvc @ComponentScan(basePackageClasses={AutoScan.class}) public class WebConfig extends WebMvcConfigurerAdapte

spring in action 4 5.1 Getting started with Spring MVC

5.1.1 Following the life of a request Every time a user clicks a link or submits a form in their web browser, a request goes towork. A request's job description is that of a courier. Just like a postal carrier or aFedEx delivery person, a request liv

Camel In Action 阅读笔记 第一章 认识Camel 1.1 Camel 介绍

1.1 Camel 介绍 Camel 是一个为了您的项目集成变得高效有趣的集成框架,Camel 项目在2007年初开始的,相对来说它还比较年轻,但它已然是一个非常成熟的开源项目,它所使用的是Apache 2开源License, 其背后的社区非常强大. Camel主要目的就是简化集成,当您用心读完本书以后,您会很感谢Camel并把它做为您的一个必需技能. Apache Camel这个项目之所以命名为Camel的主要原因是因为简单好记,有一个小道说法是项目创建者之一在吸了一个叫"骆驼"牌的

Spring in action(Spring实战) 第四版翻译

第一部分 Spring核心 Spring提供了很多功能,但是所有这些功能的基础是是依赖注入(DI)和面向方面编程(AOP). 第一章 Springing into action 本章包括: Spring的bean容器 探索Spring的核心模块 强大的Spring生态系统 Spring的新特性 现在是java程序员的好时代.在长达20年的发展过程中,java经历了一些好时光,也经历了一些坏时光.尽管有一些粗糙的地方,例如applet,Enterprise javabean(EJB),Java数据

Spring实战-Spring in Action, 4th Edition-2015年第4版本

In Action系列中最畅销的Spring图书,近十万读者学习Spring的共同选择!In Action系列中最畅销的Spring图书,有近10万读者选择本书来学习Spring! Spring框架已经成为Java开发人员的必备知识,而且Spring 3引入了强大的新特性,例如SpEL.Spring表达式语言.IoC容器的新注解以及用户急需的对REST的支持.无论你是刚刚接触Spring还是被Spring 3.0的新特性所吸引,本书都是掌握Spring的最佳选择. 下载地址: Spring in