Spring实战(第4版)Spring In Action - 第6章 渲染Web视图

15 篇文章 0 订阅

第6章 渲染Web视图

6.1 理解视图解析

ViewResolver视图解析器基类

public interface ViewResolver {

	View resolveViewName(String viewName, Locale locale) throws Exception;

}

View接口,接收model以及Servlet的request和response对象,并将输出结果渲染到response中。

public interface View {

	String getContentType();

	void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

}

Spring自带13个视图解析器: 下面是部分解析器:

  • InternalResourceViewResolver
  • TilesViewResolver

下面未测试:

  • XmlViewResolver
  • FreeMarkerViewResolver对应FreeMarker
  • ResourceBundleViewResolver解析资源Bundle(一般为属性文件)
  •  

Thymeleaf一种新来代替JSP的新兴技术。

6.2 创建JSP视图

Spring提供2种支持JSP视图的方式:

  • JSTL标准标签库
  • JSP标签库

6.2.1 配置适用于JSP的视图解析器

InternalResourceViewResolver基础配置和解析JSTL视图

    @Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/");
		resolver.setSuffix(".jsp");
		resolver.setViewClass(JstlView.class);
		return resolver;
	}

6.2.2 使用Spring的JSP库

将表单绑定模型

表单绑定库:14个标签

  • <sf:checkbox>
  • <sf:checkboxes>
  • <sf:errors>
  • <sf:form>
  • <sf:hidden>
  • <sf:input>
  • <sf:label>
  • <sf:option>
  • <sf:options>
  • <sf:password>
  • <sf:radiobutton>
  • <sf:radiobuttons>
  • <sf:select>
  • <sf:textarea>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>

程序使用代码:

    <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" /><sf:errors path="password" /><br/>
		<input type="submit" value="Register" />
	</sf:form>

commandName属性设置spitter

    @RequestMapping(value="/register", method=RequestMethod.GET)
	public String showRegistrationForm(Model model) {
		model.addAttribute(new Spitter());
		return "registerForm";
	}

展现错误

  • 方式1:错误内容单独显示
    <sf:form method="POST" commandName="spitter">
		First Name: <sf:input path="firstName" /><sf:errors path="firstName" /><br/>
		Last Name: <sf:input path="lastName" /><sf:errors path="lastName" /><br/>
		Email: <sf:input path="email" /><sf:errors path="email" /><br/>
		Username: <sf:input path="username" /><sf:errors path="username" /><br/>
		Password: <sf:password path="password" /><sf:errors path="password" /><br/>
		<input type="submit" value="Register" />
	</sf:form>
  • 方式2:错误内容集中显示
    <sf:form method="POST" commandName="spitter">
		<sf:errors path="*" element="div" cssClass="errors" />
		
		<sf:label path="firstName" cssErrorClass="error">First Name</sf:label>
			<sf:input path="firstName" cssErrorClass="error"/><br/>
		
		<sf:label path="lastName" cssErrorClass="error">Last Name</sf:label>
			<sf:input path="lastName" cssErrorClass="error"/><br/>
		
		<sf:label path="email" cssErrorClass="error">Email</sf:label>
			<sf:input path="email" cssErrorClass="error"/><br/>
		
		<sf:label path="username" cssErrorClass="error">Username</sf:label>
			<sf:input path="username" cssErrorClass="error"/><br/>
		
		<sf:label path="password" cssErrorClass="error">Password</sf:label>
			<sf:password path="password" cssErrorClass="error"/><br/>
		
		<input type="submit" value="Register" />
	</sf:form>

使用属性文件: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.

Spitter类中的校验注解添加message属性

package spittr;

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

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
	@Email(message="{email.valid}")
	private String email;
	
	@NotNull
	@Size(min=2, max=30, message="{firstName.size}")
	private String firstName;
	
	@NotNull
	@Size(min=2, max=30, message="{lastName.size}")
	private String lastName;
	
	public Spitter() {
		
	}
	
	public Spitter(String username, String password, String firstName, String lastName) {
		this.username = username;
		this.password = password;
		this.firstName = firstName;
		this.lastName = lastName;
	}
	
	public Spitter(Long id, String username, String password, String firstName, String lastName) {
		this.id = id;
		this.username = username;
		this.password = password;
		this.firstName = firstName;
		this.lastName = lastName;
	}

	public Long getId() {
		return id;
	}

	public String getUsername() {
		return username;
	}

	public String getPassword() {
		return password;
	}

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

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

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

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

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

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

	public String getEmail() {
		return email;
	}

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

Spring通用的标签库

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>

常用标签:

  • <s:message>
  • <s:url>
  • <s:escapeBody>
  •  

展现国际化信息

实现MessageSource接口

  • 方法1:ResourceBundleMessageSource
	@Bean
	public MessageSource mesasgeSource() {
		ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
		messageSource.setBasename("messages");
		
		return messageSource;
	}
  • 方法2:ReloadableResourceBundleMessageSource
    @Bean
	public MessageSource messageSource() {
		ReloadableResourceBundleMessageSource messageSource 
			= new ReloadableResourceBundleMessageSource();
		messageSource.setBasename("classpath:messages");
		messageSource.setCacheSeconds(10);
		return messageSource;
	}

默认属性文件 messages.properties

spittr.welcome=hello, welcome to spitter.

中文属性文件:messages_zh_CN.properties 英文属性文件:messages_en_US.properties

创建URL

    <s:url value="/spitter/register">

提供变量var

    <s:url value="/spitter/register" var="registerUrl" />
    <a href="${registerUrl}">Register</a>

scope属性

    <s:url value="/spitter/register" var="registerUrl" scope="request" />

<s:param>

    <s:url value="/spittles" var="spittlesUrl">
		<s:param name="max" value="60" />
		<s:param name="count" value="20" />
	</s:url>

路径占位符{}

    <s:url value="/spitter/{username}" var="spitterUrl">
		<s:param name="username" value="jbauer" />
	</s:url>

htmlEscape

    <s:url value="/spittles" htmlEscape="true">
		<s:param name="max" value="60" />
		<s:param name="count" value="20" />
	</s:url>

渲染结果:/spittr/spittles?max=60&count=20

javaScriptescape

    <s:url value="/spittles" var="spittlesUrl" javaScriptEscape="true">
		<s:param name="max" value="60" />
		<s:param name="count" value="20" />
	</s:url>
	<script>
		var spittlesUrl = "${spittlesUrl}";
	</script>

渲染结果:

    <script>
		var spittlesUrl = "\/spittr\/spittles?max=60&count=20";
	</script>

转义内容

<s:escapeBody>

    <s:escapeBody htmlEscape="true">
	<h1>Register</h1>
	</s:escapeBody>

渲染结果:

    <h1>Register</h1>

支持JavaScript转义,

    <s:escapeBody javaScriptEscape="true">
	<h1>Register</h1>
	</s:escapeBody>

渲染结果(?对于结果很疑惑): \n\t\u003Ch1\u003ERegister\u003C/h1\u003E\n\t

使用Apache Tiles视图定义布局

配置Tiles视图解析器

	@Bean
	public ViewResolver ViewResolver() {
		return new TilesViewResolver();
	}
	
	@Bean
	public TilesConfigurer tilesConfigurer() {
		TilesConfigurer tilesConfigurer = new TilesConfigurer();
		tilesConfigurer.setDefinitions(new String[] {
			"/WEB-INF/layout/tiles.xml"
		});
		tilesConfigurer.setCheckRefresh(true);
		return tilesConfigurer;
	}

定义tiles

/WEB-INF/layout/tiles.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE tiles-definitions PUBLIC 
	"-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" 
	"http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
	<definition name="base" template="/WEB-INF/layout/page.jsp">
		<put-attribute name="header"
			value="/WEB-INF/layout/header.jsp"></put-attribute>
		<put-attribute name="footer"
			value="/WEB-INF/layout/footer.jsp"></put-attribute>
	</definition>
	
	<definition name="home" extends="base">
		<put-attribute name="body"
			value="/WEB-INF/layout/home.jsp"></put-attribute>
	</definition>
	<definition name="registerForm" extends="base">
		<put-attribute name="body"
			value="/WEB-INF/layout/registerForm.jsp"></put-attribute>
	</definition>
	<definition name="profile" extends="base">
		<put-attribute name="body"
			value="/WEB-INF/layout/profile.jsp"></put-attribute>
	</definition>
	<definition name="spittles" extends="base">
		<put-attribute name="body"
			value="/WEB-INF/layout/spittles.jsp"></put-attribute>
	</definition>
	<definition name="spittle" extends="base">
		<put-attribute name="body"
			value="/WEB-INF/layout/spittle.jsp"></put-attribute>
	</definition>
</tiles-definitions>

/WEB-INF/layout/page.jsp

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="t" %>
<%@ page session="false" %>
<html>
	<head>
		<title>Spittr</title>
		<link rel="stylesheet" type="text/css" href="/resources/style.css" />
	</head>

	<body>
		<div id="header">
			<t:insertAttribute name="header" />
		</div>
		
		<div id="content">
			<t:insertAttribute name="body" />
		</div>
		
		<div id="footer">
			<t:insertAttribute name="footer" />
		</div>
	</body>
</html>

header.jsp

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<a href="<s:url value="/" />">
	<img src="<s:url value="/resources" />/images/spttr_logo_50.png" border="0" />
</a>

footer.jsp

Copyright &copy; Craig Walls

home.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<h1>Welcome to Spittr</h1>
<a href="<s:url value="/spittles" />">Spittles</a> | 
<a href="<s:url value="/spitter/register"></s:url>">Register</a>

6.4.1 配置Thymeleaf视图解析器

  • ThymeleafViewResolver将逻辑视图名称解析为Thymeleaf模板视图
  • SpringTemplateEngine处理模板并渲染结果
  • SpringResourceTemplateResolver加载Thymeleaf模板
    @Bean
	public ViewResolver ViewResolver(SpringTemplateEngine templateEngine) {
		ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
		thymeleafViewResolver.setTemplateEngine(templateEngine);
		
		return thymeleafViewResolver;
	}
	
	@Bean
	public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
		SpringTemplateEngine templateEngine = new SpringTemplateEngine();
		templateEngine.setTemplateResolver(templateResolver);
		return templateEngine;
	}
	
	@Bean 
	public ITemplateResolver templateResolver() {
		SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
		templateResolver.setPrefix("/WEB-INF/templates/");
		templateResolver.setSuffix(".html");
		templateResolver.setTemplateMode("HTML5");
		return templateResolver;
	}

定义Thymeleaf模板

/WEB-INF/templates/home.html

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
	<head>
		<title>Spiter</title>
		<link rel="stylesheet" type="text/css" th:href="@{/resources/style.css}"></link>
	</head>
	<body>
		<h1>Welcome to Spittr</h1>
		<a th:href="@{/spittles}">Spittles</a>
		<a th:href="@{/spitter/register}">Register</a>	
	</body>
</html>

注意:@{}

借助Thymeleaf实现表单绑定

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spiter</title>
<style type="text/css">
div.errors {
	background-color: #ffcccc;
	border: 2px solid red;
}
label.error {
	color: red;
}
input.error {
	background-color: #ffcccc;
}
</style>
</head>
<body>
	<h1>Register</h1>
	<form method="POST" th:object="${spitter}">
		<div class="errors" th:if="${#fields.hasErrors('*')}">
			<ul>
				<li th:echo="err : ${#fields.errors('*')}" 
					th:text="${err}">Input is incorrect</li>
			</ul>
		</div>
		
		<label th:class="${#fields.hasErrors('firstName')}? 'error'">
			FirstName</label>:
			<input type="text" th:field="*{firstName}" 
				th:class="${#fields.hasErrors('firstName')}? 'error'"></input><br></br>
				
		<label th:class="${#fields.hasErrors('lastName')}? 'error'">
			lastName</label>:
			<input type="text" th:field="*{lastName}" 
				th:class="${#fields.hasErrors('lastName')}? 'error'"></input><br></br>
				
		<label th:class="${#fields.hasErrors('email')}? 'error'">
			email</label>:
			<input type="email" th:field="*{email}" 
				th:class="${#fields.hasErrors('email')}? 'error'"></input><br></br>
				
		<label th:class="${#fields.hasErrors('username')}? 'error'">
			username</label>:
			<input type="text" th:field="*{username}" 
				th:class="${#fields.hasErrors('username')}? 'error'"></input><br></br>
				
		<label th:class="${#fields.hasErrors('password')}? 'error'">
			password</label>:
			<input type="password" th:field="*{password}" 
				th:class="${#fields.hasErrors('password')}? 'error'"></input><br></br>
		<input type="submit" value="Register"></input>
	</form>
</body>
</html>

注意:

  • ${} 变量表达式
  • *{} 选择表达式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值