Servlet JSP和Spring MVC初学指南

最近系统学习了下servlet,JSP和spring MVC的知识,推荐一本入门参考书《Servlet、JSP和Spring MVC初学指南》,作者是加拿大人Budi Kurniawan和美国人Paul Deck,林仪民、俞黎敏译。该书共24章,主要分为两部分,第一部分讲解Servlet的相关知识;第二部分讲解Spring MVC。书中每一章中都配有代码,可以对着书本敲一下,加深理解。
首先,什么是Servlet?
Servlet是在服务器上运行的小程序.Servlet的主要功能在于交互式的浏览和修改数据,生产动态Web内容.它是Java开发Web应用的底层技术.Servlet创建后(处理第一个请求时)就一直保持在内存中.JSP是构建在Java Web应用程序上第二种技术,是Servlet技术的补充,而不是取代Servlet技术。JSP(Java Server Pages)是一种动态网页开发技术,它使用JSP标签在HTML网页中插入java代码,标签通常以<%开头,以%>结束.JSP是一种Java servlet,主要用于实现Java web应用程序的用户界面部分.网页开发者们通过结合HTML代码\XHTML代码\XML元素以及嵌入JSP操作和命令来编写JSP.
JSP页面会被转换和编译成Servlet程序.JSP与纯Servlet相比,JSP可以很方便的编写或者修改HTML网页而不用去面对大量的println语句.与JavaScript相比,虽然JavaScript可以在客户端动态生成HTML,但是很难与服务器交互,因此不能提供复杂的服务,比如访问数据库和图像处理等.
Servlet应用无法独立运行,必须运行在Servlet容器中.Servlet容器将用户的请求传递给Servlet应用,并将结果返回给用户.Apache Tomcat和Jetty是当前最流行的servlet/JSP容器.由于大部分Servlet应用都帮多个JSP页面,因此更准确的说是"Servlet/JSP应用"

Servlet JSP和Spring MVC初学指南
这个过程为:
1.客户端发送请求至服务器端;
2.服务器将请求信息发送给Servlet;
3.Servlet生产响应内容并将其传给服务器.响应内容动态生成,通常取决于客户端的请求;
4.服务器将响应内容返回给客户端.
其次,Servlet的生命周期是怎样的?
1.客户端请求该Servlet;
2.加载Servlet类到内存;
3.实例化并调用init()方法初始化该Servlet;
4.service()(根据请求方法不通调用doGet()或者doPost(),此外还有doHead()\doPut()\doTrace()\doDelete()\doOptions()\destroy());
5.加载和实例化Servlet.这项操作一般是动态执行的.然而,Servlet通常会提供一个管理的选项,用于在Server启动时强制装载和初始化特定的Servlet.
最后,什么是Spring MVC?
Spring MVC又叫Spring Web MVC,是Spring框架的一个模块,用于快速开发Web应用.MVC代码Model-View-Controller,是一个广泛应用于GUI开发的设计模式.该模式不局限于Web开发,也广泛应用在桌面开发技术上.
我在学习的过程中,将一些需要记忆的信息整理了下,以期用到时不用翻书,直接看记录的信息就可以了。每章内容如下:

第1章:Servlets
Servlets,介绍ServletAPI,本章重点关注两个java包:javax.servlet和javax.servlet.http packages.
javax.servlet,其中包含定义Servlet和Servlet容器之间契约的类和接口;
javax.servlet.http,其中包含定义HTTP Servlet和Servlet容器之间契约的类和接口;
javax.servlet.annotation,其中包含标注Servlet\Filter\Listener的标注.它还被标注原件定义元数据;
javax.servlet.descriptor,包含提供程序化登录web应用程序的配置信息的类型.
注:放在应用程序目录下的任何资源,用户只要输入资源URL,都可以直接访问到。如果想让某一个资源可以被Servlet访问,但不可以被用户访问,那么就要把它放在WEB-INF目录下。
Servlet JSP和Spring MVC初学指南
HttpServletRequest表示HTTP环境中的Servlet请求.它扩展javax.servlet.ServletRequest接口,并添加了几个方法.新增的部分方法如下:
java.lang.String getContextPath()—返回表示请求上下文的请求URI部分;
cookie[] getCookies()----返回一个Cookie对象数组;
java.lang.String getHeader(java.lang.String name) —返回指定HTTP标题的值
java.lang.String getMethod()----返回生成这个请求的HTTP方法名称;
java.lang.String getQueryString() —返回请求URL中的查询字符串;
HttpSession getSession() 返回与这个请求相关的会话对象.如果没有,将创建一个新的会话对象
HttpSession getSession(boolean create) 返回与这个请求相关的会话对象.如果有,并且create参数为True,将创建一个新的会话对象.
HttpServletResponse标识HTTP环境中的Servlet响应.
void addCookie(Cookie cookie)—给这个响应对象添加一个cookie;
void addHeader(java.lang.String name, java.lang.String value)----给这个对象添加一个header
void sendRedirect(java.lang.String location) -----发送一条响应码,将浏览器跳转到指定的位置.
部署描述符是配置Servlet应用程序的另一种方法,部署描述符总是命名为web.xml,并且放在WEB-INF目录下.
所有的Servlet都运行在Servlet容器中.容器和Servlet间的接口为javax.servlet.Servlet,javax.servlet包还提供了一个名为GenericServlet的Servlet实现类,该类是一个辅助类,以便可以方便的创建一个Servlet.不过,大部分servlet都运行在HTTP环境中,因此派生了javax.servlet.http.HttpServlet的子类,注意HttpServlet也是GenericServlet的子类.

第2章:会话管理
讨论了会话管理-在web应用开发中非常重要的主题(因为HTTP是无状态的),本章比较了4种不同状态的保持技术:URL重写、隐藏域、Cookies和HTTPSession对象;
由于HTTP的无状态性,使得会话管理或会话跟踪称为Web应用开发一个无可避免的主题.默认下,一个web服务器无法区分一个http请求是否为第一次访问.
URL重写适合于tokens无须在太多URL间传递的情况下,然而它有如下限制:

URL重写
URL在某些浏览器上最大长度为2000字符;

  • 若要传递值到下一个资源,需要将值插入到链接中,换句话说,静态页面很难传值;
  • URL重写需要在服务端上完成,所有的链接都必须带值,因此当一个页面存在很多链接时,处理过程会是一个不小的挑战;
  • 某些字符,例如空格、与和问号等必须用base64编码;
  • 所有的信息都是可见的,某些情况下不合适。
    因为存在如上限制,URL重写仅适合于信息仅在少量页面间传递,且信息本身不敏感。

隐藏域
使用隐藏域来保持状态类似于URL重写技术,但不是将值附加到URL上,而是放到HTML表单的隐藏域中。当表单提交时,隐藏域的值也同时提交到服务器端。隐藏域技术仅当网页有表单时有效。该技术相对于
URL重写的优势在于:没有字符数限制,同时无须额外的编码。但该技术同URL重写一样,不适合跨越多个界面。
Cookies
Cookies是一个很少的信息片段,可自动的在浏览器和web服务器间交互,Cookie作为HTTP header的一部分,其传输由HTTP协议控制.而且可以控制cookies的有效时间.浏览器通常支持每个网站高达20个cookies.Cookies的问题在于用户可以通过改变其浏览器设置来拒绝接受cookies.要使用cookies,需要熟悉javax.servlet.http.Cookie类以及HttpServletRequest和HttpServletResponse两个接口.

Cookie cookie = new Cookie(name, value);

要将cookie发送到浏览器,需要调用HttpServletResponse的add方法:

httpServletResponse.addCookie(cookie);
Cookie[] cookies = request.getCookies();
Cookie maxRecordsCookie = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("maxRecords")) {
maxRecordsCookie = cookie;
break;
}
}
}

目前,还没有类似于getCookieByName这样的方法来帮助简化工作。此外,也没有一个直接的方法来删除一个cookie,你只能创建一个同名的cookie,并将maxAge属性设置为0,并添加到HttpServletResponse接
口中。如下为删除一个名为userName的cookie代码:

Cookie cookie = new Cookie("userName", "");
cookie.setMaxAge(0);
response.addCookie(cookie);

HttpSession对象
在所有的对话跟踪技术中,HttpSession对象是最强大和通用的.一个用户可以有且最多有一个HttpSession,并且不会被其他用户访问到.
不同于URL重新、隐藏域或cookie,放入到HttpSession 的值,是存储在内存中的,因此,不要往HttpSession放入太多对象或大对象。大部分情况下,应该主动销毁无用的HttpSession,以便释放相应的内存.
可以通过调用HttpSession的getMaxInactiveInterval方法来查看会话多久会过期.该方法返回一个数字类型,单位为秒.设置其超时时间
void setMaxInactiveInterval(int seconds),若设置为0,则改HttpSession永不过期.

第3章:JavaServer Pages(JSP)
JSP是Servlet技术的补充完善,是Servlet技术的重要组成部分,本章包括了JSP语法、指令、脚本元素和动作;
JSP页面本质上是一个Servlet,但是用JSP页面比用Servlet更容易.主要有两个原因.首先,不必编译JSP页面;其次,JSP页面是一个以.jsp为扩展名的文本文件.可以使用任何文本编辑器来编写他们.
指令:
page指令
include指令
include指令的语法如下:
<%@ include file=“url”%>
指令是JSP语法元素的第一种类型.他们指示JSP转换器如何翻译JSP页面为Servlet.

脚本元素:
表达式:“<%”是一个元素,因为它表示在JSP页面中的Java代码块的开始。“%>”也是一个元素,因为它是Java代码块的结束符。除去语法元素外的一切是模板数据。模板数据会原样发送给浏览器。
声明:可以声明能在JSP页面中使用的变量和方法。声明以“<%!”开始,并以“%>”结束,随着JSP 2.0对表达式语言的加强,推荐的实践是:在JSP页面中用EL访问服务器端对象且不写Java代码。
JSP注释以“<%–”开始,以“–%>”结束。下面是一个例子:

<%-- retrieve products to display --%>

表3.1 JSP隐式对象
对象类型
request -----javax.servlet.http.HttpServletRequest
response ----- javax.servlet.http.HttpServletResponse
out ----- javax.servlet.jsp.JspWriter
session -----javax.servlet.http.HttpSession
application -----javax.servlet.ServletContext
config----- javax.servlet.ServletConfig
pageContext----- javax.servlet.jsp.PageContext
page ----- javax.servlet.jsp.HttpJspPage
exception ----- java.lang.Throwable
动作:
include动作用来动态地引入另一个资源。可以引入另一个JSP页面,也可以引入一个Servlet或一个静态的HTML页面

<html>
<head>
<title>Include action</title>
</head>
<body>
<jsp:include page="jspf/menu.jsp">
<jsp:param name="text" value="How are you?"/>
</jsp:include>
</body>
</html>

forward将当前页面转向到其他资源。下面代码将从当前页转向到login.jsp页

<jsp:forward page="jspf/login.jsp">
<jsp:param name="text" value="Please login"/>
</jsp:forward>

第4章:表达式语言
本章介绍了JSP2.0中最重要的特性“表达式语言”。该特性的目标是帮助开发人员编写无脚本的JSP页面,让JSP页面更加简洁而且有效。本章将帮助你学会通过EL来访问Java Bean和上下文对象。
EL表达式以 ${ 开头,并以 } 结束。EL表达式的结构如下:
${expression}
${pageContext.session}
对象描述
Servlet JSP和Spring MVC初学指南
pageContext对象表示当前JSP页面的javax.servlet.jsp.PageContext。它包含了所有其他的JSP隐式对象,见表4.2。
表4.2 JSP隐式对象
对象EL中的类型
Servlet JSP和Spring MVC初学指南
有了EL、JavaBeans和定制标签,就可以编写免脚本的JSP页面了。JSP 2.0及其更高的版本中还提供了一个开关,可以使所有的JSP页面都禁用脚本。现在,软件架构师们可以强制编写免脚本的JSP页面了。

第5章:“JSTL”
本章介绍了JSP技术中最重要的类库:标准标签库—一组帮助处理常见问题的标签。具体内容包括访问Map 或集合对象、条件判断、XML处理、以及数据库访问和数据处理;
JSP标准标签库(JavaServer Pages Standard TagLibrary,JSTL)是一个定制标签库的集合,用来解决像遍历Map或集合、条件测试、XML处理,甚至数据库访问和数据操作等常见的问题。
JSTL是标准标签库,但它是通过多个标签库来暴露其行为的。JSTL 1.2中的标签可以分成5类区域,如表5.1所示。
Servlet JSP和Spring MVC初学指南
例如,要使用Core库,必须在JSP页面的开头处做以下声明:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

本章介绍了比较重要的一些标签,如操作有界对象的标签(out、set、remove)、执行条件测试的标签(if、choose、when、otherwise)、遍历集合或token的标签(forEach、forTokens)、解析和格式化日期与数字的标签(parseNumber、formatNumber、parseDate、formatDate等),以及可以在EL表达式中使用的JSTL 1.2函数。
在JSP 2.3中,有两种标签处理器可以使用:经典标签处理器和简单标签处理器。前者需要实现Tag、IterationTag及BodyTag的接口或者扩展TagSupport、BodyTagSupport这两个基类。另一方面,简单标签处理器,需要实现SimpleTag或者扩展SimpleTagSupport。相对经典标签处理器来说,简单标签处理器更容易实现,它拥有更简单的生命周期。简单标签处理器是推荐的使用方法。

第6章:自定义标签
大多数时候,JSTL用于访问上下文对象并处理各种任务。但对于特定的任务,我们需要编写自定义标签,本章将介绍如何编写标签;

第7章:标签文件
本章介绍在JSP2.0中引入的新特性—标签文件,标签文件可以简化自定义标签的编写。
本章介绍了如何使用tag file更简单地进行标签自定义。通过tag file,可无须编写标签库描述文件和标签处理类。同时,本章还介绍了如何使用invoke和doBody动作元素。

第8章:监听器
本章介绍了Servlet中的事件驱动编程,展示了Servlet API中的事件类以及监控器接口,以及如何使用;
监听器接口主要在javax.servlet和javax.servlet.http包中.有以下的接口:

  • javax.servlet.ServletContextListener:它能够响应ServletContext生命周期事件,它提供了ServletContext创建之后和ServletContext关闭之前的会被调用的方法;
  • javax.servlet.ServletContextAttributeListener:它能够响应ServletContext范围的属性添加\删除\替换事件;
  • javax.servlet.http.HttpSessionListener: 它能够响应HttpSession的创建\超时和失效事件;
  • javax.servlet.http.HttpSessionAttributeListener:它能够响应HttpSession范围的属性添加\删除\替换事件.
  • javax.servlet.http.HttpSessionActivationListener:它在一个HttpSession**或者失效时被调用;
  • javax.servlet.http.HttpSessionBindingListener:可以实现这个接口来保存HttpSession范围内的属性.当有属性从HttpSession添加或者删除时,HttpSessionBindingListener接口能够做出响应;
  • javax.servlet.ServletRequestListener:它能够响应一个ServletRequest的创建或删除;
  • javax.servlet.ServletRequestAttributeListener:它能够响应ServletRequest范围内的属性值添加\删除\修改事件;
  • javax.servlet.AsyncListener:一个用于异步操作的监听器.
    本章,我们学习了Servlet API提供的多个监听器类型。这些监听器可以分成三类:application范围、session范围和request范围。监听器的使用很简单,可以通过两种方式注册监听器:在实现类上使用
    @WebListener注解或者在部署描述文件中增加listener元素。

第9章:Filters
本章介绍了Filter API,包括Filer、FilerConfig和FilterChain接口,并展示了如何编写一个Filter实现;
Filter是拦截Request请求的对象:在用户的请求访问资源前处理ServletRequest以及ServletResponse,它可用于日志记录、加解密、Session检查、图像文件保护等。通过Filter可以拦截处理某个资源或者某些资源。Filter的配置可以通过Annotation或者部署描述来完成。当一个资源或者某些资源需要被多个Filter所使用到,且它的触发顺序很重要时,只能通过部署描述来配置。
接下来几节主要介绍Filter相关的接口,包含Filter、FilterConfg、FilterChain。Filter的实现必须继承javax.servlet.Filter接口。这个接口包含了Filter的3个生命周期:init、doFilter、destroy。

第10章:修饰Requests”和“Responses
本章介绍如何用修饰器模式来包装Servlet请求和响应对象,并改变Servlet请求和响应的行为;
Servlet API包含4个可修饰的类,用于改变ServletRequest以及Servlet Response。这种修饰允许修改ServletRequest以及ServletResponse或者HTTP中的等价类(即HttpServletRequest和HttpServletResponse)中的任务方法。这种修饰遵循Decorator模式或者Wrapper模式,因此在使用修饰前,需要了解一下该模式的内容。本章从解释Decorator模式开始,说明如何通过修饰
HttpServletRequest来修改HttpServletRequest对象的行为。该技术同样适用于修饰HttpServletResponse对象。
Servlet JSP和Spring MVC初学指南

第11章:异步处理
本章主要讨论Servlet3.0引入的新特性—异步处理。改特性非常适合于当Servlet应用负载较高且有一个或多个耗时操作,使得当前的web请求处理线程可以处理新的web请求。
异步处理功能可以节约容器线程。你应该将此功能使用在长时间运行的操作上。此功能的作用是释放正在等待完成的线程,使该线程能够被另一请求所使用。
请注意,这个异步支持只适合你有一个长时间运行的任务并且要把运行结果通知给用户。如果你只有一个长期运行任务,但用户并不需要知道处理结果,那么你可以提交一个Runnable给Executor(执行器)并立即返回。例如,如果你需要生成报告(需要一段时间),当它生成完毕时,通过邮件发送这个报告,这时servlet异步处理功能不是最佳的解决方案。相反地,如果你需要生成一个报告,并在报告已经准备好时显示给用户,这时异步处理可能就是你所要的。

第12章:安全
介绍了如何通过声明式以及编程式来保护Java web应用,本章覆盖四个主题:认证、授权、加密和数据完整性。
清单12.2 防止访问特定目录下的资源

在这里插入代码片<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
➥ http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
>
<!-- restricts access to JSP pages -->
<security-constraint>
<web-resource-collection>
<web-resource-name>JSP pages</web-resource-name>
<url-pattern>*.jsp</url-pattern>
</web-resource-collection>
<!-- must have auth-constraint, otherwise the
specified web resources will not be restricted -->
<auth-constraint/>
</security-constraint>
</web-app>

在本章中,你已经学会了如何实现网络安全的四大支柱:身份验证、授权、保密性和数据完整性。Servlet技术允许您以声明或编程的方式保护您的应用程序。

第13章:部署
介绍了Servlet/JSP应用的部署流程,以及部署描述符。
若存在如下场景,则依然需要部署描述符:

  • 需要传递初始参数给ServletContext。
  • 有多个过滤器,并要指定调用顺序。
  • 需要更改会话超时设置。
  • 要限制资源的访问,并配置用户身份验证方式。
    清单13.1展示了部署描述符的框架。它必须被命名为web.xml且合并在应用目录的WEB-INF目录下。
    发布一个应用程序有两种方式:一种是以目录结构的形式;另一种是打包成一个单一的WAR文件进行部署。
    清单13.1 部署描述符
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
➥ http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
[metadata-complete="true|false"]
>
...
</web-app>

web-app元素是文档的根元素,并且可以具有如下
子元素:
Servlet声明
Servlet映射
ServletContext的初始化参数
会话配置
监听器类
过滤器定义和映射
MIME类型映射
欢迎文件列表
错误页面
JSP特定的设置
JNDI设置
WAR文件必须包含所有库文件、类文件、HTML文件、JSP页面、图像文件以及版权声明(如果有的话)等,但不包括Java源文件。任何人都可以获取一个WAR文件的副本,并部署到一个Servlet/JSP容器上。

第14章:动态加载以及Servlet容器加载器
介绍了Servlet3.0中的两个新特性,动态注册支持在无需重启web应用的情况**册新的web对象,以及框架开发人员最关心的容器初始化。
动态加载是Servlet 3.0中的新特性,它可以实现在不重启Web应用的情况下加载新的Web对象(Servlet、Filter、Listener)。Servlet容器加载器也是Servlet 3.0中的新特性,对于框架的开发者来说特别有用。

第二部分:Spring MVC
第15章:Spring框架
介绍了最流行的开源框架;
Spring包含20多个不同的模块。本文主要关注Core和Bean,以及Spring MVC模块。Spring MVC是Spring的一个子框架。
控制反转和依赖注入的区别:
http://martinfowler.com/articles/injection.html
通过提供一个控制反转容器(或者依赖注入容器),Spring为我们提供一种可以“聪明”的管理java对象依赖关系的方法。从2.5版本开始,通过Autowired注解,Spring支持基于field方式的依赖注入,但缺点是程序必须引入org.springframework.beans.factory.annotation.Autowired,这对Sprin*生了依赖,这样程序无法直接迁移到另一个依赖注入容器内。
使用Spring,程序几乎将所有重要对象的创建工作移交给Spring,并配置如何注入依赖。Spring支持XML和注解两种配置方式。此外,还需要创建一个AppliacationContext对象,代表一个Spring控制反转容器,org.springframework.context.ApplicationContext接口有多个实现,包括ClassPathXmlApplicationContext和FileSystemXmlApplicationContext.这两个实现都需要至少一个包含beans信息的XML文件。ClassPathXmlApplicationContext尝试在类加载路径中加载配置文件,而FileSystemXmlApplicationContext则从文件系统中加载。对于Spring MVC应用,可以通过一个Spring Servlet来处理ApplicationContext,而无需直接处理。

第16章:模式2和MVC模式
讨论了spring MVC所实现的设计模式;
一个实现MVC模式的应用包含模型、视图和控制器三个模块。视图负责应用的展示。模型封装了应用的数据和业务逻辑。控制器负责接收用户输入、改变模型以及调整视图的展示。Spring MVC选择一个Servlet作为控制器,而Struts 2则使用一个Filter作为控制器。大部分采用JSP页面作为应用的视图,当然也有其他技术。模型则采用POJO(Plain Old Java Object)。不同于EJB等,POJO是一个普通对象。实践中会采用一个JavaBean来持有模型状态,并将业务逻辑放到一个Action类中。一个JavaBean必须用于一个无参的构造器,通过get/set方法来访问参数,同时支持持久化。
Servlet JSP和Spring MVC初学指南

第17章:Spring MVC介绍
spring MVC概述。本章编写了第一个Spring MVC应用。
若基于某个框架来开发一个模型2的应用程序,我们要负责编写一个Dispatcher servlet和控制类。其中,Dispatcher servlet必须能够做好如下事情:
(1)根据URI调用相应的action;
(2)实例化正确的控制器类;
(3)根据请求参数值来构造表单bean;
(4)调用控制器对象的相应方法;
(5)转发到一个视图(JSP页面)
使用Spring MVC具有的能加速开发的功能列表:

  • Spring MVC中提供了一个Dispatcher Servlet,无须额外开发;
  • Spring MVC中使用基于XML的配置文件,可以编辑,而无需冲洗编译应用程序;
  • Spring MVC实例化控制器,并根据用户输入来构造bean;
  • Spring MVC可以自动绑定用户输入,并正确的转换数据类型。
  • Spring MVC可以校验用户输入,若校验不通过,则重定向回输入表单。输入校验是可选的,支持编程以及声明方式;
  • Spring MVC支持国际化和本地化
  • Spring MVC支持多种视图技术,包含JSP、Velocity和FreeMarker
    Spring MVC中自带了一个开箱即用的Dispatcher Servlet,该Servlet的全名是org.springframework.web.servlet.Dispatcher.DispatcherServlet
    要使用这个Servlet,需要把它配置在部署描述符(web.xml)中,引用servlet和servlet-mapping元素。

第18章:基于注解的控制器
讨论了MVC模式中最重要的一个对象—控制器。本章,我们将学会如何编写基于注解的控制器,这是Spring MVC2.5版本引入的方法。
使用基于注解的控制器有多个优点:
1.一个控制器类可以处理多个动作(而一个实现了Controller接口的控制器只能处理一个动作)。这就允许将相关的操作写在同一个控制器类中,从而减少应用程序中类的数量;
2.基于注解的控制器的请求映射不需要存储在配置文件中。使用RequestMapping注解类型,可以对一个方法进行请求处理。
Controller和RequestMapping注解类型是Spring MVC API最重要的两个注解类型。
org.springframework.stereotype.Controller注解类型用于指示Spring 类的实例是一个控制器。
Servlet JSP和Spring MVC初学指南
Spring 使用扫描机制来找到应用程序中基于注解的控制器类。为了保证Spring能找到你的控制器,需要完成两件事情。首先,需要在Spring MVC的配置文件中声明spring-context,如下所示:

<bean>
…
Xmlns:context=“http://www.springframework.org/schema/context”
...
</bean>

然后,需要应用元素,如下所示:

<context:component-scan base-package=“basePackage” />

如:

<context:component-scan base-package=“com.example.controller” />

若是为控制器类的每一个动作开发相应的处理方法,需要使用org.springframework.web.bind.annotation.RequestMapping注释类型映射的URI与方法。
一个采用@RequestMapping注解的方法将成为一个请求处理方法,并由调度程序在接收到对应URL请求时调用。
@RequestMapping不止可以用来注解方法,也可以用来注解一个控制器类。
下面是可以在请求处理方法中出现的参数类型:

  • javax.servlet.ServletRequest或javax.servlet.http.HttpServletRequest
  • javax.servlet.ServletResponse或javax.servlet.http.HttpServletResponse
  • javax.servlet.http.HttpSession
  • org.springframework.web.context.request.WebRequest或org.springframework.web.context.request.NativeWebRequest
  • Java.util.Locale
  • java.io.InputStream或java.io.Reader
  • java.io.OutputStream或java.io.Writer
  • java.security.Pricipal
  • HttpEntity<?>
  • java.util.Map/org.springframework.ui.Model
  • org.springframework.ui.ModelMap
  • org.springframework.web.servlet.mvc.support.Redirect
  • org.springframework.validation.Errors
  • org.springframework.validation.BindingResult

命令或表单对象:

  • org.springframework.web.bind.support.SessionStatus
  • org.springframework.web.util.UriComponentsBuilder
  • 带@Path Variable ,@Matrix Variable注释的对象
  • @RequestParam,@RequestHeader, @RequestBody或@RequestPart

特别重要的是org.springframework.ui.Model类型。这不是一个Servlet API类型,而是一个包含Map的Spring MVC类型。每次调用请求处理方法时,Spring MVC都创建Model对象并将各种对象注入到Map中
请求处理方法可以返回如下类型的对象:

  • ModelAndView
  • Model
  • Map包含模型的属性
  • View
  • 代表逻辑视图名的String
  • void
  • 提供对Servlet的访问,以响应HTTP头部和内容,HttpEntity或ResponseEntity对象
  • Callable
  • DeferredResult
  • 其他任意类型,Spring将其视作输出给View的对象模型

将依赖注入到Spring MVC控制器最简单的方法是通过注解@Autowired到字段货方法。Autowired注解类型属于org.springframework.beans.factory.annotation包。
此外,为了能被作为依赖注入,类必须要注明为@Service。该类型是org.springframework.stereotype包的成员。Service注解类型指示类是一个服务。此外,在配置文件中,还需要添加一个元素来扫描依赖基本包

第19章:数据绑定和表单标签库
讨论spring MVC最强大的一个特性,并利用它来展示表单数据。
数据绑定是将用户输入绑定到领域模型的一种特性。有了数据绑定,类型总是为String的HTTP请求参数,可用于填充不同类型的对象属性。为了高效的使用数据绑定,还需要Spring的表单标签库。
表单标签库中包含了可以用在JSP页面中渲染HTML元素的标签。为了使用这些标签,必须在JSP页面的开头处声明这个taglib指令:

<%@taglib prefix=“form” uri=“http://www.springframework.org/tags.form” %>

表单标签库中的标签
Servlet JSP和Spring MVC初学指南
form标签的属性
Servlet JSP和Spring MVC初学指南
input标签的属性
Servlet JSP和Spring MVC初学指南
checkBox标签的属性
Servlet JSP和Spring MVC初学指南

radiobuttons标签的属性
Servlet JSP和Spring MVC初学指南

第20章:转换器和格式化
讨论了数据绑定的辅助对象类型。
Converter和Formatter均可用于将一种对象类型转换成另一种对象类型。Converter是通用元件,可以在程序的任意层泗洪,而Formatter则是专门为web层设计的。
为了创建Converter,需要编写一个实现org.springframework.core.convert.converter.Converter接口的 Java 类。这个接口的声明如下:
public interface Converter<S, T>,这里的S表示源类型,T表示目标类型。例如,为了创建一个可以将Long转换成Date的Converter,需要做如下声明:

public class MyConverter implements Converter<Long, Date> {
}

为了使用Spring MVC应用程序定制的Converter,需要在Spring MVC配置文件中编写一个conversionService bean. Bean的类名称必须
org.springframework.context.support.ConversionServiceFactoryBean.这个bean必须包含一个converters属性。它将列出要在应用程序中使用的所有定制Conterter。如

<bean id=“conversionService” class=“org.springframework.context.support.ConversionServiceFactoryBean”>
  <property name=“converters”>
    <list>
      <bean class=“converter.StringToDateConverter”>
        <constructor-arg type=“java.lang.String” value=“MM-dd-yyyy” />
      </bean>
    </list>
  </property>
</bean>

随后,要给annotation-driven元素的conversion-service属性赋bean名称,如下所示:

<mvc:annotation-driven consersion-service=“conversionService”/>

Formatter就像Converter一样,也是将一种类型转换成另一种类型。但是,Formatter的源类型必须是一个String,而Converter则适用于任意的源类型。Formatter更适合web层,而Converter则可以用在任意层中。
为了使用Spring MVC应用程序定制的Formatter,需要编写一个实现org.springframework.format.Formatter接口的Java类。下面是这个接口的声明:

public interface Formatter<T>

为了在Spring MVC应用程序中使用Formatter,需要利用conversionService bean对他进行注册. Bean的类名称必须为org.springframework.format.support.FormattingConversionFactoryBean

<context:component-scan base-package="app20b.formatter" />

<mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService"
   class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
   <property name="formatters">
      <set>
         <bean class="app20b.formatter.DateFormatter">
            <constructor-arg type="java.lang.String" value="MM-dd-yyyy" />
         </bean>
      </set>
   </property>
</bean>

注册Formatter的另一种方法是使用Registrar。
Servlet JSP和Spring MVC初学指南
需要在配置文件中注册Registrar

<mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService"
   class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
   <property name="formatterRegistrars">
      <set>
         <bean class="app20b.formatter.MyFormatterRegistrar">
            <constructor-arg type="java.lang.String" value="MM-dd-yyyy" />
         </bean>
      </set>
   </property>
</bean>

第21章:验证器
本章将展示如何通过验证器来验证用户输入数据。
输入验证是Spring吹的最重要的web开发任务之一。在Spring MVC中,有两种方式可以实现验证输入,即利用spring自带的验证框架,或者利用JSR 303实现。
Converter和Formatter作用于field级,在MVC应用程序总,它们将String转换或格式化成另一种java类型,如java.util.Date.验证器作用于object级。它决定某一个对象中的所有field是否均是有效的,以及师傅遵循某些规则。
org.springframework.validation.ValidationUtils类是一个工具,有助于编写Spring验证器。
JSR 303“Bean Validation”或JSR 349,对于JSR bean validation,目前有两个实现。第一个实现是Hibernate Validator,JSR 303和JSR 349两种它都实现了。可以从以下网站下载:
http://sourceforge.net/projects/hibernate/files/hibernate-validator/

第22章:国际化
本章将展示如何用Spring MVC来构建多语言网站。
java.util.Locale类表示一个语言区域。一个Locale对象包含3个主要元件:language、country和variant。language无疑是最重要的部分,参数variant是一个特定于供应商或者特定于浏览器的代号。例如,用WIN表示Windows,用MAC表示Macintosh。
Java.util.Resource-Bundle类

第23章:上传文件
介绍两种不同的方式来处理文件上传;
上传到Spring MVC应用程序中的文件会被包在一个MultipartFile对象中。需要用类型为MultipartFile的属性编写一个domain类。
org.springframework.web.multipart.MultipartFile接口来处理文件
对于Servlet3.0及其以上版本的容器中进行服务器端文件的上传,是围绕着注解类型MultipartConfig和javax.servlet.http.Part接口进行的。处理已上传文件的Servlets必须以@MultipartConfig进行注解。
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
      xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
       <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>/WEB-INF/config/springmvc-config.xml</param-value>
      </init-param>
        <load-on-startup>1</load-on-startup>
      <multipart-config>
          <max-file-size>20848820</max-file-size>
          <max-request-size>418018841</max-request-size>
          <file-size-threshold>1048576</file-size-threshold>
      </multipart-config>            
   </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Springmvc-config.xml

<bean id="multipartResolver"
    class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>

上面的两种方法不能查看文件上传进度,无法显示已经上传的文件数量。若是需要查看以上两项,HTML5可以实现(实现方法略)

第24章:下载文件
介绍如何用编程方式向客户端传输一个资源。
以下代码将一个文件发送到浏览器

FileInputStream fis = null;
BufferedInputStream bis = null;
// if you're using Java 7, use try-with-resources
try {
    fis = new FileInputStream(file);
    bis = new BufferedInputStream(fis);
    OutputStream os = response.getOutputStream();
    int i = bis.read(buffer);
    while (i != -1) {
        os.write(buffer, 0, i);
        i = bis.read(buffer);
    }
} catch (IOException ex) {
    // do something here
} finally {
    if (bis != null) {
        try {
            bis.close();
        } catch (IOException e) {
            
        }
    }