在详细介绍Spring MVC架构之前,让我们首先看看用于Web开发的两种流行的设计模式。
前控制器设计模式
此设计模式对所有传入请求强制执行单个入口点。所有请求都由单个代码处理,然后可以将处理请求的责任进一步委托给其他应用程序对象。
前控制器设计模式
MVC设计模式
这种设计模式通过将各种关注点分离到不同的层中来帮助我们开发松耦合应用程序。MVC设计模式将应用程序强制分为三层,即Model,View和Controller。
Model:代表应用程序数据。
View:这表示应用程序的用户界面。View将模型作为输入,并将其适当地呈现给最终用户。
Controller:控制器负责处理请求并生成模型,并为请求选择适当的视图。
Spring的MVC模块
Spring的MVC模块基于前端控制器设计模式,然后是MVC设计模式。所有传入的请求均由名为DispatcherServlet 的单个Servlet处理,该Servlet 充当Spring的MVC模块中的前端控制器。然后,DispatcherServlet 会引用 HandlerMapping 查找可以处理请求的控制器对象。然后,DispatcherServlet将请求分派到控制器对象,以便它实际上可以执行业务逻辑来满足用户请求。(控制器可以将责任委托给称为服务对象的其他应用程序对象)。控制器返回包含模型对象和视图对象(或视图的逻辑名称)的封装对象。在Spring的MVC中,此封装的对象由ModelAndView 类表示。如果ModelAndView 包含视图的逻辑名称,则 DispatcherServlet 引用ViewResolver 来基于逻辑名称查找实际的View对象。然后,DispatcherServlet 将模型对象传递给视图对象,然后将其呈现给最终用户。
2.DispatcherServlet
DispatcherServlet 在Spring的MVC模块中充当前端控制器。所有用户请求都由该servlet处理。由于这与其他任何Servlet一样,因此必须在应用程序的Web部署描述符文件即web.xml中进行配置。
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Library</display-name>
<servlet>
<servlet-name>myLibraryAppFrontController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myLibraryAppFrontController</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>welcome.htm</welcome-file>
</welcome-file-list>
</web-app>
我们已将该servlet命名为“ myLibraryAppFrontController ”。servlet映射部分中的URI模式是“ * .htm ”。因此,所有与URI模式匹配的请求都将由myLibraryAppFrontController 处理。
3. Spring应用程序上下文
- 默认应用程序上下文文件
- 用户定义的应用程序上下文文件
- 多个应用程序上下文文件
默认应用程序上下文文件
默认情况下,调度程序Servlet从名称为[servlet name] -servlet.xml的 XML文件中加载Spring应用程序上下文。因此,当我们的servlet myLibraryAppFrontController由容器加载时,它将从XML文件“ /WEB-INF/myLibraryAppFrontController-servlet.xml ” 加载Spring应用程序上下文。
用户定义的应用程序上下文文件
通过为调度程序servlet提供初始化参数,我们可以覆盖默认XML文件的名称和位置。初始化参数的名称为contextConfigLocation。参数值指定容器需要加载的应用程序上下文的名称和位置。
<servlet>
<servlet-name>myLibraryAppFrontController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:libraryAppContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
在上面的servlet配置中,我们提供了多个XML文件作为初始化参数值。所有这些XML文件将在初始化servlet myLibraryAppFrontController时由容器加载。
4. Spring Handler映射
- BeanNameUrlHandlerMapping
- SimpleUrlHandlerMapping
顾名思义,处理程序映射将请求与相应的请求处理程序(实际上是处理程序执行链)进行映射。当请求到达Spring的调度程序servlet时,它将请求移交给处理程序映射。然后,处理程序映射检查请求,并标识适当的处理程序执行链,并将其交付给调度程序servlet。处理程序执行链包含与传入请求匹配的处理程序,还可以选择包含应用于该请求的拦截器列表。然后,分派器Servlet执行处理程序和任何关联的处理程序拦截器。
Spring的MVC模块提供了许多处理程序映射的实现。其中一些描述如下。所有处理程序映射类都实现org.springframework.web.servlet.HandlerMapping 接口。
BeanNameUrlHandlerMapping
处理程序映射的此实现将传入请求的URL与控制器bean的名称进行匹配。然后,将匹配的Bean用作请求的控制器。这是Spring的MVC模块使用的默认处理程序映射,即,如果调度程序Servlet在Spring的应用程序上下文中找不到任何定义的处理程序映射bean,则调度程序servlet使用BeanNameUrlHandlerMapping。
让我们假设我们的应用程序中有三个网页。页面的URL为:
- http://服务器名称:端口号/ApplicationContext/welcome.htm
- http://服务器名称:端口号/ApplicationContext/listBooks.htm
- http://服务器名称:端口号/ApplicationContext/displayBookContent.htm
将执行业务逻辑以完成对以上页面做出的请求的控制器是:
- net.codejava.frameorks.spring.mvc.controller.WelcomeController
- net.codejava.frameorks.spring.mvc.controller.ListBooksController
- net.codejava.frameorks.spring.mvc.controller.DisplayBookTOCController
因此,我们需要在Spring的应用程序上下文文件中定义控制器,以使控制器的名称与请求的URL匹配。XML配置文件中的控制器bean如下所示。
<bean
name="/welcome.htm"
class="net.codejava.frameorks.spring.mvc.controller.WelcomeController" />
<bean
name="/listBooks.htm"
class="net.codejava.frameorks.spring.mvc.controller.ListBooksController"/>
<bean
name="/displayBookTOC.htm"
class="net.codejava.frameorks.spring.mvc.controller.DisplayBookTOCController"/>
注意,我们不需要在Spring的应用程序上下文文件中定义BeanNameUrlHandlerMapping,因为这是使用的默认值。
SimpleUrlHandlerMapping
该BeanNameUrlHandlerMapping时提出的限制控制器上的豆子,他们应该匹配传入请求的URL的名称。SimpleUrlHandlerMapping 消除了此限制,并使用属性“ mappings ” 将控制器bean映射为请求URL 。
<bean
id="myHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/welcome.htm">welcomeController</prop>
<prop key="/listBooks.htm">listBooksController</prop>
<prop key="/displayBookTOC.htm">displayBookTOCController</prop>
</props>
</property>
</bean>
<bean name="welcomeController"
class="net.codejava.frameorks.spring.mvc.controller.WelcomeController"/>
<bean name="listBooksController"
class="net.codejava.frameorks.spring.mvc.controller.ListBooksController"/>
<bean name="displayBookTOCController"
class="net.codejava.frameorks.spring.mvc.controller.DisplayBookTOCController"/>
<prop>元素的关键字是传入请求的URL模式。<prop>元素的值是控制器bean的名称,它将执行业务逻辑来满足请求。SimpleUrlHandlerMapping 是最常用的处理程序映射之一。
5. Spring Controllers
- MultiActionController
控制器是执行业务逻辑以满足传入请求的实际代码。控制器也可以将此责任委托给其他服务对象。所有用户定义的控制器都必须实现接口Controller或扩展抽象类AbstractController 。用户定义的控制器需要重写handleRequestInternal 方法。方法handleRequestInternal 以HttpServletRequest 和HTTPServletResponse 作为输入,并返回ModelAndView 的对象。
在Spring的应用程序上下文文件中,我们定义了一个用户定义的自定义控制器,名称为welcomeController。按照SimpleUrlHandlerMApping,所有与URL模式/welcome.htm匹配的请求都将由此控制器处理。所述WelcomeController必须扩展一个AbstractController和提供方法的定义handleRequestInternal。因此,WelcomeController如下所示:
public class WelcomeController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
return new ModelAndView("welcome");
}
}
MultiActionController
在任何中型到大型企业Web应用程序中,都有很多网页。为了满足这些网页的要求,我们需要定义多个控制器,每个控制器一个。有时执行业务逻辑来满足那些请求是相似的。这会在多个控制器中创建业务逻辑冗余,并使维护变得困难。
Spring的MVC模块通过提供一个控制器来满足对多个网页的请求,从而提供了一种处理这种情况的方法。这样的控制器被称为多动作控制器。用户定义的多动作控制器应扩展org.springframework.web.servlet.mvc.multiaction.MultiActionController 类。用户定义的多动作控制器中的每种方法均包含满足特定网页请求的逻辑。
默认情况下,传入请求的URL(不包括扩展部分)将与多动作控制器中方法的名称进行匹配,并且匹配方法将为传入请求执行业务逻辑。因此,对于URL /welcome.htm 的传入请求,将欢迎包含业务逻辑的方法名称。
让我们假设在我们的应用程序的多动作控制器是MyMultiActionController 它满足了这三个网页使用URL请求/welcome.htm ,/listBooks.htm 和/displayBookTOC.htm 。因此,类应该延长了MultiActionController ,并有三种方法名称欢迎,listBooks 和displayBookTOC 。控制器将如下所示:
public class MyMultiActionController extends MultiActionController {
// This method will server all the request matching URL pattern /welcome.htm
public ModelAndView welcome(HttpServletRequest request,
HttpServletResponse response) {
// Business logic goes here
// Return an object of ModelAndView to DispatcherServlet
return new ModelAndView("Welcome");
}
// This method will server all the request matching URL pattern
// /listBooks.htm
public ModelAndView listBooks(HttpServletRequest request,
HttpServletResponse response) {
// Business logic goes here
// Return an object of ModelAndView to DispatcherServlet
return new ModelAndView("listBooks");
}
// This method will server all the request matching URL pattern
// /displayBookTOC.htm
public ModelAndView displayBookTOC(HttpServletRequest request,
HttpServletResponse response) {
// Business logic goes here
// Return an object of ModelAndView to DispatcherServlet
return new ModelAndView("displayBookTOC");
}
}
MethodNameResolver
Spring MVC提供了许多其他方法名称解析器,可帮助根据请求解析多动作控制器方法名称。其中一些是:
ParameterMethodNameResolver
请求中的特定参数包含方法名称。在定义ParameterMethodNameResolver的同时,在Spring的应用程序上下文文件中定义参数的名称。在下面的示例中,请求中的参数controllerMethod将确定将执行以执行请求的多动作控制器方法。
<bean name="parameterMethodNameResolver"
class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="paramName">
<value>controllerMethod</value>
</property>
</bean>
注意:现在,对特定网页的请求应包含一个名为“ controllerMethod ” 的附加参数,并将其值作为要执行的多动作控制器方法名称。请求网址如下:
- http://服务器名称:端口号/ProjectWebContext/welcome.htm?controllerMethod= handleWelcomePage
- http://服务器名称:端口号/ProjectWebContext/listBooks.htm?controllerMethod= handleListBooksPage
- http://服务器名称:端口号/ProjectWebContext/displayBookTOC.htm?controllerMethod= handleDisplayBookTOCPage
在上述配置中,对URL /welcome.htm 的请求将通过多动作控制器的handleWelcomePage 方法来完成。请求URL /listBooks.htm 将由方法满足handleListBooksPage 和URL请求/displayBookTOC.htm 将由方法满足handleDisplayBookTOCPage 。
PropertiesMethodNameResolver
方法的名称由Spring的应用程序上下文文件中提供给方法名称解析器的预定义属性列表确定。Spring应用程序上下文文件中的PropertiesMethodNameResolver 如下所示。
<bean name="propertiesMethodNameResolver"
class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/welcome.htm">handleWelcomePage</prop>
<prop key="/listBooks.htm">handleListBooksPage</prop>
<prop key="/displayBookTOC.htm">handleDisplayBookTOCPage</prop>
</props>
</property>
</bean>
同样,在上述配置中,对URL /welcome.htm 的请求将由多动作控制器的handleWelcomePage 方法来完成。请求URL /listBooks.htm 将由方法满足handleListBooksPage 和URL请求/displayBookTOC.htm 将由方法满足handleDisplayBookTOC 。
我们需要通过设置其属性methodNameResolver 来告诉多动作控制器使用特定的方法名称解析器。因此,多动作控制器的配置如下所示:
<bean name="myMultiActionController"
class="net.codejava.frameworks.spring.mvc.controller.MyMultiActionController">
<property name="methodNameResolver">
<ref bean="propertiesMethodNameResolver"/>
</property>
</bean>
6. ModelAndView和ViewResolver
- 模型和视图
- ViewResolver
- InternalResourceViewResolver
- BeanNameViewResolver
- XMLFileViewResolver
- ResourceBundleViewResolver
模型和视图
Spring的MVC模块将模型对象和视图对象封装在一个由ModelAndView 类的对象表示的实体中。该对象包含模型对象和视图对象或视图的逻辑名称。模型对象是应用程序数据,视图是将输出呈现给用户的对象。控制器将ModelAndView 的对象返回到调度程序servlet,以进行进一步处理。
ViewResolver
如果ModelAndView 对象包含视图的逻辑名称,则DispatcherServlet 需要根据其逻辑名称解析视图对象。为了解析视图对象,DispatcherServlet 借助ViewResolver 的帮助。Spring提供了许多视图解析器的实现。所有视图解析器都实现org.springframework.web.servlet.ViewResolver 接口。
InternalResourceViewResolver
它将视图的逻辑名称解析为内部资源,方法是在逻辑视图名称前添加资源路径,并在其后缀后缀。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"value="/WEB-INF/jsp/" />
<property name="suffix"value=".jsp" />
</bean>
如果控制器在ModelAndView 对象中返回的视图的逻辑名称为Welcome ,则显示给用户的视图为/WEB-INF/jsp/Welcome.jsp
BeanNameViewResolver
它将视图的逻辑名称解析为Bean名称,该名称将输出呈现给用户。该bean应该在Spring应用程序上下文文件中定义。因此,如果控制器在ModelAndView对象中返回的逻辑名是Welcome,那么在应用程序上下文中定义的名称Welcome的bean 将负责将模型呈现给用户。
XMLFileViewResolver
该视图解析器与BeanNameViewResolver相同,唯一的区别在于,它不是在Spring的应用程序上下文文件中查找Bean,而是查找在单独的XML文件(默认为/WEB-INF/views.xml)中定义的bean 。通过在定义XMLFileViewResolver时提供location属性,可以覆盖位置和文件名。
<bean name="propertiesMethodNameResolver"
class="org.springframework.web.servlet.view.XMLFileViewResolver">
<propertyname="location">
<value>classpath:myViews.xml</value>
</property>
</bean>
ResourceBundleViewResolver
它将视图的逻辑名称解析为资源束中定义的实际视图。该视图解析器将基本名称作为输入,这是可以在其中放置视图的属性文件的名称。
<bean name="propertiesMethodNameResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> <property name="basename"> <value>myViews</value> </property></bean>
因此,如果控制器在ModelAndView 对象中返回的逻辑名是Welcome,则视图解析器将在属性文件myViews.properties (或myViews_en_US.properties,取决于用户语言和区域设置)中查找属性Welcome.class 。
7. Sample Application
应用概述
XYZ先生写了一本关于他最喜欢的主题“ Spring-Core ”的书。他写了更多的书,现在正计划建立一个网站- 在线书店,在那里他可以出版他的所有书。该网站非常简单,一个欢迎页面,一个列出其在线书店中所有书籍的页面,以及一个列出表格的页面,该表格包含最终用户选择的特定书籍的内容。
XYZ先生选择使用他最喜欢的框架Spring MVC开发他的在线书店。他已将其应用程序的前端控制器命名为myLibraryAppFrontController,该控制器从多个XML文件(libraryAppContext.xml,books.xml,chapters.xml和titles.xml)加载应用程序上下文。他已经在应用程序中编写了与他的三个页面相对应的三个JSP页面,并将它们放置在WebContent / WEB-INF / jsp文件夹中。
在线书店应用程序中使用的处理程序映射是Spring MVC模块的默认处理程序映射BeanNamURLHandlerMApping。
三个页面的请求由三个不同的控制器处理。
- 欢迎页面(/welcome.htm)– WelcomeController
- 页面显示书籍清单(/listBooks.htm)– ListBooksController
- 页面显示书目表(/displayBookTOC.htm)– DisplayBookTOCController
因此,在XML文件libraryAppContext.xml中定义了三个bean(三个控制器),bean名称为页面URL。此应用程序中使用的视图解析器是Spring的InternalResourceViewResolver,它将前缀/ Web-INF / jsp和后缀.jsp附加到控制器返回的逻辑视图名称中,以解析实际视图(在本例中为jsps)。
在Eclipse IDE中设置工作区
我们将使用Java EE开发人员版本4.2(Juno)的Eclipse IDE来使用Spring版本3.2.0.M2构建示例应用程序。我们将在Apache Tomcat服务器v 7.0上运行示例应用程序,因此请确保Apache Tomcat v7.0已安装在系统上并已与Eclipse IDE集成。
打开Eclipse IDE。从菜单栏中,选择 窗口>打开透视图>其他...> Java EE。
打开项目资源管理器视图。从菜单栏中选择窗口>显示视图>项目浏览器。
右键单击项目资源管理器视图中的任何位置。选择“ 新建”>“动态Web项目”。
将打开一个弹出窗口,我们将输入创建动态Web项目的详细信息。输入项目名称:Library_SpringMVC。选择Target Runtime作为Apache Tomcat v7.0。另外,请确保将 配置 设置 为Apache Tomcat v7.0的默认配置。 请确保Apache Tomcat v7.0已安装在系统上并与Eclipse IDE集成在一起。
单击“ 动态Web项目”对话框中的“ 下一步”按钮。下一个对话框用于项目的Java设置。使用Java对话框右侧的“ 添加文件夹...”按钮添加以下两个源文件夹。
1. SourceCode / JavaSource-我们的示例应用程序的所有Java代码都将驻留在这里。
2. SourceCode / Config-示例应用程序的所有XML和属性文件都将驻留在此处。
单击Java对话框上的Next按钮。下一个对话是针对Web模块的。在此对话框中,确保将上下文根设置为Library,将内容目录设置为WebContent,并确保选中与Generate web.xml部署描述符相对应的 复选框。
当您单击“ 完成”按钮时,将在您的工作空间中创建名称为Library_SpringMVC的动态Web项目。
为JSP页面创建文件夹:我们将所有JSP页面放置在WebContent / WEB-INF / jsp文件夹中。因此,我们需要在WEB-INF文件夹中创建名为jsp的文件夹。右键单击WEB-INF文件夹,然后选择“ 新建”>“文件夹”。输入名称作为jsp。
基于Spring MVC构建和运行示例应用程序所需的各种jar文件如下:
可以从以下位置下载上述jar文件:https : //repo.springsource.org/libs-milestone-local/org/springframework/spring/3.2.0.M2/spring-3.2.0.M2-dist.zip
从上面的位置下载zip文件。解压缩。将相关的jar(如上所述)从 spring-3.2.0.M2 \ libs复制到示例Java应用程序的 lib文件夹中。
我们还需要以下jar:
- commons-logging-1.1.1.jar-此jar需要记录日志。Spring MVC jar(如上所述)需要此jar文件。
http://apache.techartifact.com/mirror/commons/logging/binaries/commons-logging-1.1.1-bin.zip
要在JSP页面中使用Java标记库,需要以下两个jar文件。
- javax.servlet.jsp.jstl-1.2.2.jar
http://search.maven.org/remotecontent?filepath=org/glassfish/web/javax.servlet.jsp.jstl/1.2.2/javax.servlet.jsp.jstl-1.2.2.jar
- javax.servlet.jsp.jstl-api-1.2.1.jar
http://search.maven.org/remotecontent?filepath=javax/servlet/jsp/jstl/javax.servlet.jsp.jstl-api/1.2.1/javax.servlet.jsp.jstl-api-1.2.1。罐
我们的示例应用程序中使用的各种应用程序对象是:
- 书
- 章节
- 标题
书对象包括:
- 标题–由标题对象表示
- 作者–由String表示
- ISBN -代表由整数
- 章节列表–由列表<Chapter>表示
章对象包括:
- 数字–用整数表示的章节编号
- 标题–由标题对象表示
- 内容–用字符串表示的章节内容
标题对象包括:
- titleValue –用字符串表示
应用程序对象的Java类放在源文件夹SourceCode / JavaSource中。我们的应用程序对象的Java代码如下所示:
Title.java
package net.codejava.frameworks.spring.bo;
public class Title {
private String titleValue;
public Title(){
}
public Title(String titleValue){
this.titleValue = titleValue;
}
public String getTitleValue() {
return titleValue;
}
public void setTitleValue(String titleValue) {
this.titleValue = titleValue;
}
}
Chapter.java
package net.codejava.frameworks.spring.bo;
public class Chapter {
private int number;
private Title title;
private String content;
public Chapter(){
}
public Chapter(int number, Title title, String content){
this.number = number;
this.title = title;
this.content = content;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public Title getTitle() {
return title;
}
public void setTitle(Title title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Book.java
package net.codejava.frameworks.spring.bo;
import java.util.List;
public class Book {
private int isbn;
private String author;
private Title title;
private List<Chapter> chapters;
public Book(){
}
public Book(int isbn, String author, Title title, List<Chapter> chapters){
this.isbn = isbn;
this.author = author;
this.title = title;
this.chapters = chapters;
}
public int getIsbn() {
return isbn;
}
public void setIsbn(int isbn) {
this.isbn = isbn;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Title getTitle() {
return title;
}
public void setTitle(Title title) {
this.title = title;
}
public List<Chapter> getChapters() {
return chapters;
}
public void setChapters(List<Chapter> chapters) {
this.chapters = chapters;
}
}
所有book Bean都在XML文件books.xml 中定义,所有Chapter Bean都在chapters.xml 中定义,所有title Bean都在titles.xml 文件中定义。所有这些XML文件都放在SourceCode / Config 文件夹中。
Spring的各种应用程序上下文文件如下所示:
titles.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:beans.properties</value>
</property>
</bean>
<bean id="bookTitle" class="net.codejava.frameworks.spring.bo.Title">
<property name="titleValue">
<value>${myFirstSpringBook.title}</value>
</property>
</bean>
<bean id="chapter1Title" class="net.codejava.frameworks.spring.bo.Title">
<constructor-arg>
<value>${myFirstSpringBook.chapter1.title}</value>
</constructor-arg>
</bean>
<bean id="chapter2Title" class="net.codejava.frameworks.spring.bo.Title">
<constructor-arg>
<value>${myFirstSpringBook.chapter2.title}</value>
</constructor-arg>
</bean>
<bean id="chapter3Title" class="net.codejava.frameworks.spring.bo.Title">
<property name="titleValue">
<value>${myFirstSpringBook.chapter3.title}</value>
</property>
</bean>
</beans>
Chapters.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:beans.properties</value>
</property>
</bean>
<bean id="chapter1" class="net.codejava.frameworks.spring.bo.Chapter">
<property name="number">
<value>1</value>
</property>
<property name="content">
<value>${myFirstSpringBook.chapter1.content}</value>
</property>
<property name="title">
<ref bean="chapter1Title"/>
</property>
</bean>
<!-- injecting the dependencies of chapter 2 using constructor by index -->
<bean id="chapter2" class="net.codejava.frameworks.spring.bo.Chapter">
<constructor-arg index="0">
<value>2</value>
</constructor-arg>
<constructor-arg index="1">
<ref bean="chapter2Title"/>
</constructor-arg>
<constructor-arg index="2">
<value>${myFirstSpringBook.chapter2.content}</value>
</constructor-arg>
</bean>
<!-- injecting the dependencies of chapter 3 using constructor by type -->
<bean id="chapter3" class="net.codejava.frameworks.spring.bo.Chapter">
<constructor-arg type="int">
<value>3</value>
</constructor-arg>
<constructor-arg type="net.codejava.frameworks.spring.bo.Title">
<ref bean="chapter3Title"/>
</constructor-arg>
<constructor-arg type="String">
<value>${myFirstSpringBook.chapter3.content}</value>
</constructor-arg>
</bean>
</beans>
books.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:beans.properties</value>
</property>
</bean>
<bean id="myFirstSpringBook" class="net.codejava.frameworks.spring.bo.Book">
<property name="isbn">
<value>1</value>
</property>
<property name="author">
<value>${myFirstSpringBook.author}</value>
</property>
<property name="title">
<ref bean="bookTitle"/>
</property>
<property name="chapters">
<list>
<ref bean="chapter1"/>
<ref bean="chapter2"/>
<ref bean="chapter3"/>
</list>
</property>
</bean>
</beans>
注意,我们在上述XML文件中使用了beans.properties文件。该beans.properties文件看起来如下:
myFirstSpringBook.title=My First Spring Book
myFirstSpringBook.chapter1.title=Spring framework - Chapter 1
myFirstSpringBook.chapter2.title=Spring framework - Chapter 2
myFirstSpringBook.chapter3.title=Spring framework - Chapter 3
myFirstSpringBook.chapter1.content=The content of chapter 1 goes here.
myFirstSpringBook.chapter2.content=The content of chapter 2 goes here.
myFirstSpringBook.chapter3.content=The content of chapter 3 goes here.
myFirstSpringBook.author=Mr. XYZ
配置Spring的前端控制器(DispatcherServlet)
打开Library项目中位于WebContent / WEB-INF 处的Web.xml 文件。如下所示配置调度程序Servlet和Servlet映射。
<web-app
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Library</display-name>
<servlet>
<servlet-name>myLibraryAppFrontController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:libraryAppContext.xml
classpath:books.xml
classpath:chapters.xml
classpath:titles.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myLibraryAppFrontController</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>welcome.htm</welcome-file>
</welcome-file-list>
</web-app>
此处的servlet名称是myLibraryAppFrontController。Servlet映射中的URI模式为* .htm。
Servlet有一个初始化参数。初始化参数名称为contextConfigLocation,其值为
classpath:libraryAppContext.xml
classpath:books.xml
classpath:chapters.xml
classpath:titles.xml
这样可以确保容器查找提到的XML文件以加载Spring应用程序上下文,而不是查找默认XML文件“ WEB-INB / myLibraryAppFrontController-servelt.xml ”
在文件夹SourceCode / Config中创建名称为libraryAppContext.xml 的XML文件。这是Spring的应用程序上下文文件,其中将包含Spring MVC特定的bean。此文件中定义的各种bean是:
- HandlerMapping 将请求与控制器bean映射。我们已经使用了SimpleUrlHandlerMapping 。网页/welcome.htm 将通过与bean名称控制器送达welcomeController ,/listBooks.htm 将由控制器bean的名称服务listBooksController 和/displayBookTOC.htm 将通过与bean名称控制器送达displayBookTOCController 。
- 三个控制器bean服务于三个网页的请求。
- ViewResolver bean将视图逻辑名解析为JSP文件。我们已使用InternalResourceViewResolver ,其前缀为/ WEB-INF / jsp ,后缀为.jsp 。这是因为我们已将视图对象放置在此文件夹中。
libraryAppContext.xml 文件将如下所示
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:beans.properties</value>
</property>
</bean>
<bean id="myHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/welcome.htm">welcomeController</prop>
<prop key="/listBooks.htm">listBooksController</prop>
<prop key="/displayBookTOC.htm">displayBookTOCController</prop>
</props>
</property>
</bean>
<bean name="welcomeController" class="net.codejava.frameworks.spring.mvc.controller.WelcomeController" />
<bean name="listBooksController" class="net.codejava.frameworks.spring.mvc.controller.ListBooksController">
<property name="books">
<list>
<ref bean="myFirstSpringBook"/>
</list>
</property>
</bean>
<bean name="displayBookTOCController" class="net.codejava.frameworks.spring.mvc.controller.DisplayBookTOCController">
<property name="books">
<list>
<ref bean="myFirstSpringBook"/>
</list>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
编码控制器
让我们快速看一下这三个控制器。这三个控制器都扩展了AbstractController 并覆盖了handleRequestInternal 方法。此方法返回ModelAndView 对象,其中包含视图和模型对象的逻辑名称。
如果使用welcomeBookController ,则视图的逻辑名称为Welcome,并且不返回任何模型对象。
package net.codejava.frameworks.spring.mvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class WelcomeController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("welcome");
}
}
对于listBooksController,视图的逻辑名称为listBooks,返回的模型对象为book对象的列表。
package net.codejava.frameworks.spring.mvc.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.codejava.frameworks.spring.bo.Book;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class ListBooksController extends AbstractController {
private List<Book> books;
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("listBooks","books",books);
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
}
如果使用displayBookTOCController,则视图的逻辑名称为displayBookTOC,并且返回的模型对象是其对象的ISBN在请求中传递的书的对象。
package net.codejava.frameworks.spring.mvc.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.codejava.frameworks.spring.bo.Book;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class DisplayBookTOCController extends AbstractController {
private List<Book> books;
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Book myBook = null;
if(books != null && !books.isEmpty()){
for(Book book : books){
if(book.getIsbn() == Integer.parseInt(request.getParameter("isbn"))){
myBook = book;
break;
}
}
}
return new ModelAndView("displayBookTOC","book",myBook);
}
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
}
编码视图
向用户显示的各种JSP放置在WebContent / WEB-INF / jsp 文件夹中。JSP如下:
Welcome.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>Welcome page</title>
</head>
<body>
<h1>Welcome to the world of books !</h1>
<p>The page content goes here . . .</p>
<a href="/listBooks.htm">List all books.</a>
</body>
</html>
listBooks.jsp
<%@ page language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>List of books</title>
</head>
<body>
<h1 align="center">List of books in my library :</h1>
<table width="50%" align="center">
<tr>
<th width="20%" align="center">S. No.</th>
<th width="50%" align="center">Title</th>
<th width="30%" align="center">Author</th>
</tr>
<%int i = 1; %>
<c:forEach items="${books}" var="book">
<tr>
<td width="20%" align="center"><%= i++ %></td>
<td width="50%" align="center">
<a href="/displayBookTOC.htm?isbn=${book.isbn}">${book.title.titleValue}</a>
</td>
<td width="30%" align="center">${book.author}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
displayBookTOC.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Book Table of Content</title>
</head>
<body>
<h1 align="center">Book : ${book.title.titleValue}, written by ${book.author}</h1>
<h2>Table of content : </h2>
<%int i = 1; %>
<table width="100%">
<c:forEach items="${book.chapters}" var="chapter">
<tr width="100%">
<td width="5%" align="center"><%= i++ %></td>
<td width="95%" align="left">${chapter.title.titleValue}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
8.结论
在本文中,我们了解了Spring框架如何使Web应用程序的开发非常简单和容易。我们已经详细了解了Spring的MVC模块,其架构和各种组件。我们还学习了Spring MVC模块所基于的设计模式。最后,我们使用Eclipse IDE构建了一个简单的应用程序。