`
liyinfeng56
  • 浏览: 94123 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Spring MVC入门

阅读更多
Spring MVC学习指南





以下这个学习案例是我最近学习Spring MVC时跟从一本书上的示例,原文中的示例代码有一些小错误,不过我在调试的过程中已经给予了修正,如还有其它错误,还请各位批评指正。

对于现有较成熟的Model-View-Control(MVC)框架而言,其解决的主要问题无外乎下

面几部分:


1. 将Web页面中的输入元素封装为一个(请求)数据对象。

2. 根据请求的不同,调度相应的逻辑处理单元,并将(请求)数据对象作为参数传入。

3. 逻辑处理单元完成运算后,返回一个结果数据对象。

4. 将结果数据对象中的数据与预先设计的表现层相融合并展现给用户。

各个MVC 实现固然存在差异,但其中的关键流程大致如上。结合一个实例,我们来看看这

几个关键流程在Spring MVC框架中的处理手法。

下面的实例,实现了一个常见的用户登录逻辑,即用户通过用户名和密码登录,系统对用

户名和密码进行检测,如果正确,则在页面上显示几条通知信息。如果登录失败,则返回失败

界面。

(示例中,表示层以JSP2.0实现。)

出于简洁考虑,这里的“用户名/密码”检测以及通知信息的生成均在代码中以硬编码实现。

首先来看登录界面:

对应的index.html:

<html>

<body>

<form method="POST" action="login.do">

<p align="center">登录</p>

<br>

用户名:

<input type="text" name="username" >

<br>

密 码 :

<input type="password" name="password" >

<br>

<p>

<input type="submit" value="提交" name="B1">

<input type="reset" value="重置" name="B2">

</p>

</form>

</body>

</html>




很简单的一个登录界面,其中包含了一个用以输入用户名密码的form,针对此form的提

交将被发送到"login.do"

MVC 关键流程的第一步,即收集页面输入参数,并转换为请求数据对象。这个静态页面提

供了一个基本的输入界面,下面这些输入的数据将被发送至何处,将如何被转换为请求数据对

象?

现在来看接下来发发生的事情:

当用户输入用户名密码提交之后,此请求被递交给Web 服务器处理,上面我们设定form

提交目标为"login.do",那么Web服务器将如何处理这个请求?

显然,标准Http 协议中,并没有以.do 为后缀的服务资源,这是我们自己定义的一种请

求匹配模式。此模式在web.xml中设定:

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"

version="2.4">

<servlet> ⑴

<servlet-name>Dispatcher</servlet-name>

<servlet-class>

org.springframework.web.servlet.DispatcherServlet

</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/Config.xml</param-value>

</init-param>

</servlet>

<servlet-mapping> ⑵

<servlet-name>Dispatcher</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

</web-app>

⑴ Servlet定义

这里我们定义了请求分发Servlet,即:

org.springframework.web.servlet.DispatcherServlet

DispatcherServlet 是Spring MVC 中负责请_____求调度的核心引擎,所有的请求将

由此Servlet 根据配置分发至各个逻辑处理单元。其内部同时也维护了一个

ApplicationContext实例。

我们在<init-param>节点中配置了名为“contextConfigLocation”的

Servlet参数,此参数指定了Spring配置文件的位置“/WEB-INF/Config.xml”。

如果忽略此设定,则默认为“/WEB-INF/<servlet name>-servlet.xml”,其

中<servlet name>以Servlet 名替换(在当前环境下,默认值也就是

“/WEB-INF/Dispatcher-servlet.xml)。

⑵ 请求映射

我们将所有以.do结尾的请求交给Spring MVC进行处理。当然,也可以设为其他值,

如.action、.action等。

通过以上设定,Web 服务器将把登录界面提交的请求转交给Dispatcher 处理,

Dispatcher将提取请求(HttpServletRequest)中的输入数据,分发给对应的处理单元,

各单元处理完毕后,将输出页面返回给Web服务器,再由Web服务器返回给用户浏览器。

Dispatcher 根据什么分发这些请求?显然,我们还需要一个配置文件加以设定。这也就

是上面提及的Config.xml,此文件包含了所有的“请求/处理单元”关系映射设定,以及返回

时表现层的一些属性设置。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!--Definition of View Resolver -->

<bean id="viewResolver" ⑴

class="org.springframework.web.servlet.view.InternalResou

rceViewResolver">

<property name="viewClass"> ⑵

<value>

org.springframework.web.servlet.view.JstlView

</value>

</property>

<property name="prefix"> ⑶

<value>

/WEB-INF/view/

</value>

</property>

<property name="suffix"> ⑷

<value>.jsp</value>

</property>

</bean>

<!--Request Mapping -->

<bean id="urlMapping" ⑸

class="org.springframework.web.servlet.handler.SimpleUr

lHandlerMapping">

<property name="mappings">

<props>

<prop key="/login.do">LoginAction</prop>

</props>

</property>

</bean>

<!---Action Definition-->

<bean id="LoginAction" ⑹

class="net.xiaxin.action.LoginAction">

<property name="commandClass"> ⑺

<value>net.xiaxin.action.LoginInfo</value>

</property>

<property name="fail_view"> ⑻

<value>loginfail</value>

</property>

<property name="success_view">

<value>main</value>

</property>

</bean>

</beans>

⑴ Resolver设定

Resolver将把输出结果与输出界面相融合,为表现层提供呈现资源。

⑵ View Resolver的viewClass参数

这里我们使用JSP页面作为输出,因此,设定为:

org.springframework.web.servlet.view.JstlView

其余可选的viewClass还有:

Ø org.springframework.web.servlet.view.freemarker.FreeMarker

View(用于基于FreeMarker模板的表现层实现)

Ø org.springframework.web.servlet.view.velocity.VelocityView

(用于基于velocity模板的表现层实现)

等。

⑶⑷ View Resolver的prefix和suffix参数

指定了表现层资源的前缀和后缀,运行时,Spring 将为指定的表现层资源自动追加

前缀和后缀,以形成一个完整的资源路径。另参见⑻

⑸ “请求/处理单元”关系映射

可以看到,这里我们将“/login.do”请求映射到处理单元LoginAction。

<props>节点下可以有多个映射关系存在,目前我们只定义了一个。

⑹ LoginAction定义

这里定义了逻辑处理单元LoginAction 的具体实现,这里,LoginAction 的实现

类为net.xiaxin.action.LoginAction。

⑺ LoginAction的请求数据对象

commandClass 参数源于LoginAction 的基类BaseCommandController,

BaseCommandControlle 包含了请求数据封装和验证方法

( BaseCommandController.bindAndValidate ) , 它将根据传入的

HttpServletRequest构造请求数据对象。

这里我们指定commandClass 为net.xiaxin.action.LoginInfo,这是一个非

常简单的Java Bean,它封装了登录请求所需的数据内容:

public class LoginInfo {

private String username;

private String password;

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

}

Spring会根据LoginAction的commandClass定义自动加载对应的LoginInfo

实例。

之后,对Http 请求中的参数进行遍历,并查找LoginInfo 对象中是否存在与之同

名的属性,如果找到,则将此参数值复制到LoginInfo对象的同名属性中.

请求数据转换完成之后,我们得到了一个封装了所有请求参数的Java 对象,并将此

对象作为输入参数传递给LoginAction。

⑻ 返回视图定义

对于这里的LoginAction 而言,有两种返回结果,即登录失败时返回错误界面,登

录成功时进入系统主界面。

对应我们配置了fail_view、success_view两个自定义参数。

参数值将由Resolver进行处理,为其加上前缀后缀,如对于fail_view而言,实

际的视图路径为/WEB-INF/view/loginfail.jsp。

之后,Resolver 会将LoginAction的返回数据与视图相融合,返回最终的显示界

面。

业务逻辑处理单元:

LoginAction.java:

public class LoginAction extends SimpleFormController {

private String fail_view;

private String success_view;

protected ModelAndView onSubmit( ⑴

Object cmd,

BindException ex

)throws Exception {

LoginInfo loginInfo = (LoginInfo) cmd; ⑵

HashMap result_map = new HashMap();

if (login(loginInfo) == 0) {

result_map.put("logininfo", loginInfo);

List msgList = new LinkedList();

msgList.add("msg1");

msgList.add("msg2");

msgList.add("msg3");

result_map.put("messages", msgList);

return new

ModelAndView(this.getSuccess_view(), result_map); ⑶

} else {

result_map.put("failmsg", new String("Sorry, you input the wrong username or password!"));

return new ModelAndView(this.getFail_view(), result_map);

}


}

private int login(LoginInfo loginInfo) {

if ("Erica".equalsIgnoreCase(loginInfo.getUsername())

&& "mypass".equals(loginInfo.getPassword())) {

return 0;

}

return 1;

}

public String getFail_view() {

return fail_view;

}

public String getSuccess_view() {

return success_view;

}

public void setFail_view(String string) {

fail_view = string;

}

public void setSuccess_view(String string) {

success_view = string;

}

}

其中:

⑴ onSubmit方法

我们在子类中覆盖了父类的onSubmit方法;而onSubmit方法用于处理业务请求。

负责数据封装和请求分发的Dispatcher,将对传入的HttpServletRequest进行

封装,形成请求数据对象,之后根据配置文件,调用对应业务逻辑类的入口方法(这

里就是LoginAction)的onSubmit()方法,并将请求数据对象及其他相关资源引

用传入。

protected ModelAndView onSubmit(

Object cmd,

BindException ex

)

onSubmit方法包含了两个参数:Object cmd和BindException ex。

前面曾经多次提到请求数据对象,这个名为cmd的Object型参数,正是传入的请求

数据对象的引用。

BindException ex参数则提供了数据绑定错误的跟踪机制。它作为错误描述工具,

用于向上层反馈错误信息。

在Spring MVC中,BindException将被向上层表现层反馈,以便在表现层统一处

理异常情况(如显示对应的错误提示),这一机制稍后在“输入参数合法性校验”部

分再具体探讨。

onSubmit还有另外一个签名版本:

protected ModelAndView onSubmit(

HttpServletRequest request,

HttpServletResponse response,

Object cmd,

BindException ex

)

可以看到,类似Servlet的doGet/doPost方法,此版本的onSubmit方法签名中

包含了Servlet规范中的HttpServletRequest、HttpServletResponse以提

供与Web服务器的交互功能(如Session的访问)。此参数类型的onSubmit方法

的调用优先级较高。也就是说,如果我们在子类中同时覆盖了这两个不同参数的

onSubmit方法,那么只有此版本的方法被执行,另一个将被忽略。

⑵ 将输入的请求数据对象强制转型为预定义的请求对象类型。

⑶ 返回处理结果

ModelAndView类包含了逻辑单元返回的结果数据集和表现层信息。ModelAndView

本身起到关系保存的作用。它将被传递给Dispatcher,由Dispatcher 根据其中

保存的结果数据集和表现层设定合成最后的界面。

这里我们用到了两种签名版本的ModelAndView构造方法:

Ø public ModelAndView(String viewname)

返回界面无需通过结果数据集进行填充。

Ø public ModelAndView(String viewname, Map model)

返回界面由指定的结果数据集加以填充。可以看到,结果数据集采用了Map接口

实现的数据类型。其中包含了返回结果中的各个数据单元。关于结果数据集在界

面中的填充操作,可参见下面关于返回界面的描述。

上面这两个版本的构造子中,通过viewname指定了表示层资源。

另外,我们也可以通过传递View对象指定表示层资源。

Ø public ModelAndView(View view)

Ø public ModelAndView(View view, Map model)

我们可以结合RedirectView完成转向功能,如:

return new ModelAndView(

new RedirectView(“/redirected.jsp”

));

当然,我们也可以在带有HttpServletRequest参数的onSubmit方法实现中,通

过HttpServletRequest/HttpServletResponse完成forward/redirect功

能,这两种途径可以达到同样的效果。

最后,来看返回界面:

错误返回界面loginfail.jsp只是个纯html文件(为了与View Resolver中设

定的后缀相匹配,因此以.jsp作为文件后缀),这里就不再浪费篇幅。

再看成功登录后的页面main.jsp:

界面显示效果如下:

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

<html>

<body>

<p>Login Success!!!</p>

<p>Current User:

<c:out value="${logininfo.username}"/><br>

</p>

<p>Your current messages:</p>

<c:forEach items="${messages}"

var="item"

begin="0"

end="9"

step="1"

varStatus="var">

<c:if test="${var.index % 2 == 0}">

*

</c:if>

${item}<br>

</c:forEach>

</body>

</html>





登录失败后的页面loginfail.jsp:

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

<html>

<body>

<p>Login Fail!!!</p><c:out value="${failmsg}" />

</body>

</html>

页面逻辑非常简单,首先显示当前登录用户的用户名。然后循环显示当前用户的通知消息

“messages”。如果当前循环索引为奇数,则在消息前追加一个“*”号(这个小特性在这里

似乎有些多余,但却为不熟悉JSTL 的读者提供了如何使用JSTL Core taglib 进行循环和

逻辑判断的样例)。


实际上这只是个普通JSTL/JSP页面,并没有任何特殊之处,如果说有些值得研究的技术,

也就是其中引用的JSTL Core Taglib

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

上面这句话申明了页面中所引用的taglib,指定其前缀为“c”,也就是说,在页面中,

所有以“c”为前缀,形同<c:xxxx>的节点都表明是此taglib的引用,在这里,也就是对JSTL

Core Lib的引用。

这里需要注意的是,笔者所采用的Web 容器为Tomcat 5(支持Servlet 2.4/JSP2.0

规范)以及Apache JSTL 2.0(http://jakarta.apache.org/taglibs/index.html)。

<c:out value="${logininfo.username}"/>

<c:out>将value 中的内容输出到当前位置,这里也就是把logininfo 对象的

username属性值输出到页面当前位置。

${……}是JSP2.0 中的Expression Language(EL)的语法。它定义了一个表达式,

其中的表达式可以是一个常量(如上),也可以是一个具体的表达语句(如forEach循环体中

的情况)。典型案例如下:

Ø ${logininfo.username}

这表明引用logininfo 对象的username 属性。我们可以通过“.”操作符引

用对象的属性,也可以用“[]”引用对象属性,如${logininfo[username]}

与${logininfo.username}达到了同样的效果。

“[]”引用方式的意义在于,如果属性名中出现了特殊字符,如“.”或者“-”,

此时就必须使用“[]”获取属性值以避免语法上的冲突(系统开发时应尽量避免

这一现象的出现)。

与之等同的JSP Script大致如下:

LoginInfo logininfo =

(LoginInfo)session.getAttribute(“logininfo”);

String username = logininfo.getUsername();

可以看到,EL大大节省了编码量。

这里引出的另外一个问题就是,EL 将从哪里找到logininfo 对象,对于

${logininfo.username}这样的表达式而言,首先会从当前页面中寻找之前是

否定义了变量logininfo,如果没有找到则依次到Request、Session、

Application 范围内寻找,直到找到为止。如果直到最后依然没有找到匹配的

变量,则返回null.

如果我们需要指定变量的寻找范围,可以在EL表达式中指定搜寻范围:

${pageScope.logininfo.username}

${requestScope.logininfo.username}

${sessionScope.logininfo.username}

${applicationScope.logininfo.username}

在Spring 中,所有逻辑处理单元返回的结果数据,都将作为Attribute 被放

置到HttpServletRequest 对象中返回(具体实现可参见Spring 源码中

org.springframework.web.servlet.view.InternalResourceView.

exposeModelAsRequestAttributes方法的实现代码),也就是说Spring

MVC 中,结果数据对象默认都是requestScope。因此,在Spring MVC 中,

以下寻址方法应慎用:

${sessionScope.logininfo.username}

${applicationScope.logininfo.username}

Ø ${1+2}

结果为表达式计算结果,即整数值3。

Ø ${i>1}

如果变量值i>1的话,将返回bool类型true。与上例比较,可以_____发现EL会自

动根据表达式计算结果返回不同的数据类型。

表达式的写法与java代码中的表达式编写方式大致相同。

<c:forEach items="${messages}"

var="item"

begin="0"

end="9"

step="1"

varStatus="var">

……

</c:forEach>

上面这段代码的意思是针对messages 对象进行循环,循环中的每个循环项的引用变量为

item,循环范围是从0到9,每次步长为1。而varStatus则定义了一个循环状态变量var,

循环状态变量中保存了循环进行时的状态信息,包括以下几个属性:

属性 类型 说明

index int 当前循环索引号

count int 成员总数

first boolean 当前成员是否首位成员

last boolean 当前成员是否末尾成员

再看:

<c:if test="${var.index % 2 == 0}">

*

</c:if>

这段代码演示了判定Tag <c:if>的使用方法。可以看到,其test属性指明了判定条件,

判定条件一般为一个EL表达式。

<c:if>并没有提供else子句,使用的时候可能有些不便,此时我们可以通过<c:choose>

tag来达到类似的目的:

<c:choose>

<c:when test="${var.index % 2 == 0}">

*

</c:when>

<c:otherwise>

!

</c:otherwise>

</c:choose>

类似Java 中的switch 语句,<c:choose>提供了复杂判定条件下的简化处理手法。其

中 <c:when>子句类似case子句,可以出现多次。上面的代码,在奇数行时输出“*”号,

而偶数行时输出“!”。

通过<c:choose>改造后的输出页面:

至此,一个典型的请求/响应过程结束。通过这个过程,我们也了解了Spring MVC 的核心实现机制。对其进行总结,得到以下UML序列图:

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yinianshen/archive/2008/11/23/3354226.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yinianshen/archive/2008/11/23/3354226.aspx
分享到:
评论

相关推荐

    Spring MVC入门(登录示例)

    **Spring MVC 入门教程——基于登录示例** Spring MVC 是 Spring 框架的一个模块,主要用于构建 Web 应用程序。它提供了模型-视图-控制器(MVC)架构,帮助开发者分离业务逻辑、数据处理和用户界面,使得代码更易于...

    精简源码-spring-mvc 入门级使用,亲测好用

    这个"精简源码-spring-mvc 入门级使用"的压缩包文件,旨在为初学者提供一个简单易懂的实践案例,帮助他们快速理解和上手 Spring MVC。 首先,我们从 "spring" 这个标签开始。Spring 是一个开源框架,它提供了一个...

    spring mvc入门书籍

    Spring MVC 是一款强大的Java web应用程序框架,用于构建高效、模块化的Web应用。它基于Spring框架,专注于处理HTTP请求和响应,...《Spring MVC入门》这本书将帮助你深入了解这一框架,并引导你一步步掌握其使用技巧。

    Spring MVC入门项目

    **Spring MVC 入门项目详解** Spring MVC 是 Java Web 开发中的一个核心框架,它为构建基于模型-视图-控制器(MVC)模式的Web应用程序提供了强大的支持。本项目是一个专门为初学者设计的入门教程,旨在帮助大家快速...

    intellij idea 2017 spring mvc 入门

    【描述】:“Java Spring MVC超简单,Spring MVC入门,第一个Java程序,IntelliJ IDEA入门” 这表明我们将从零开始,逐步学习如何在IntelliJ IDEA这个强大的Java集成开发环境中配置Spring MVC环境,创建并运行一个...

    Spring mvc 入门向导

    在这个Spring MVC入门向导中,我们将深入探讨如何配置开发环境、理解Spring MVC的架构以及构建Web Store项目。 首先,配置Spring开发环境至关重要。这包括安装Java Development Kit (JDK),设置环境变量以确保Java...

    spring mvc 入门介绍

    ### Spring MVC 入门知识点详解 #### 一、Spring MVC 概述 Spring MVC 是 Spring 框架的一部分,主要用于构建基于 Model-View-Controller (MVC) 设计模式的 Web 应用程序。它提供了丰富的功能来简化 Web 开发过程,...

    Spring MVC 入门教程

    ### Spring MVC 入门教程详解 #### 一、Spring MVC框架概述 Spring MVC是Spring框架的一个模块,专门用于构建Web应用程序。它遵循Model-View-Controller(MVC)设计模式,将业务逻辑、数据和表示层分离,提高代码...

    资料-10 Spring MVC入门程序.rar

    这个“资料-10 Spring MVC入门程序.rar”压缩包很可能是包含了一个简单的Spring MVC项目示例,帮助初学者理解并学习如何搭建和运行Spring MVC应用程序。 在Spring MVC中,核心概念包括DispatcherServlet、Model-...

    Spring MVC 入门实例

    首先, 我需要在你心里建立起 Spring MVC 的基本概念. 基于 Spring 的 Web 应用程序接收到 http://localhost:8080/hello.do(事实上请求路径是 /hello.do) 的请求后, Spring 将这个请求交给一个名为 helloController ...

    Spring MVC入门实例

    **Spring MVC 入门实例详解** Spring MVC 是一个基于 Java 的模型-视图-控制器(MVC)架构,是 Spring 框架的一部分,用于构建Web应用程序。它简化了开发流程,提供了强大的数据绑定、自动验证和异常处理等功能。本...

    Spring mvc入门Demo资料

    通过这个"Spring mvc入门Demo资料",新手可以学习如何创建一个简单的Spring MVC项目,理解控制器的编写、视图的展示以及如何处理HTTP请求。实际运行这个Demo,能帮助初学者更好地理解Spring MVC的工作原理,并为...

    spring mvc 入门Demo

    这个入门Demo是Spring MVC学习的起点,展示了如何搭建一个基础的Spring MVC应用并实现简单的请求处理。随着对框架的深入理解,可以学习更多高级特性,如模型绑定、数据验证、异常处理、RESTful API设计、视图技术...

    Spring MVC入门教程

    Spring MVC入门教程

    Spring MVC入门 XML版本+注释版本

    总结一下,Spring MVC入门涉及的关键概念有: 1. `DispatcherServlet`:作为请求分发器。 2. XML配置:定义组件,如视图解析器、处理器映射器和处理器适配器。 3. 注解配置:使用`@Controller`、`@RequestMapping`等...

    spring mvc 入门案例

    本入门案例将带你逐步了解如何使用 Spring MVC 创建一个简单的 Web 应用。 首先,我们需要了解 Spring MVC 的核心组件和工作流程: 1. **DispatcherServlet**:作为所有请求的前端控制器,它负责接收请求并分派到...

    spring mvc入门示例

    **Spring MVC 入门示例** Spring MVC 是一个基于 Java 的模型-视图-控制器(MVC)架构,用于构建动态 Web 应用程序。它提供了处理 HTTP 请求、数据绑定、异常处理等功能,使得开发者可以更专注于业务逻辑,而不是...

    spring mvc 的入门级资料

    Spring MVC 入门级资料 Spring MVC 是一个基于 Java 的 Web 框架,它提供了一种灵活、可扩展、Easy-to-use 的 Web 应用程序开发方式。Spring MVC 是 Spring 框架的一部分,提供了一个强大、灵活、可扩展的 MVC 框架...

Global site tag (gtag.js) - Google Analytics