您的位置:首页 > 编程语言 > Java开发

SpringMVC入门实例及详细讲解

2012-04-17 17:09 555 查看
SpringServletWebBeanMVC
Spring 框架提供了构建 Web
应用程序的全功能 MVC 模块。使用 Spring
可插入的 MVC 架构,可以选择是使用内置的 Spring Web
框架还是 Struts 这样的 Web
框架。通过策略接口,Spring
框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages(JSP)技术、Velocity、Tiles、iText
和 POI。Spring MVC
框架并不知道使用的视图,所以不会强迫您只使用 JSP
技术。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。

  Spring 的 Web MVC
框架是围绕 DispatcherServlet
设计的,它把请求分派给处理程序,同时带有可配置的处理程序映射、视图解析、本地语言、主题解析以及上载文件支持。默认的处理程序是非常简单的 Controller
接口,只有一个方法 ModelAndView handleRequest(request, response)。Spring
提供了一个控制器层次结构,可以派生子类。如果应用程序需要处理用户输入表单,那么可以继承 AbstractFormController。如果需要把多页输入处理到一个表单,那么可以继承 AbstractWizardFormController。
Spring MVC对于现在较成熟的Model-View-Control框架而言,其解决的主要问题无外乎下面几部分:

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

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

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

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

开发步骤:
首先新建web Project项目:MySpringMvc
1.加载项目所需要的jar包;

spring.jar -------------------------这个在spring2.5.6资源包的dist下面

spring-webmvc.jar---------------这个在spring2.5.6资源包的dist/module下面
2.配置web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
Xml代码


1.
<SPAN style="FONT-SIZE: large"><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
2.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3.
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
4. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 5.
<servlet>
6.
<servlet-name>dd</servlet-name>
7.
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
8.
<!-- <init-param>-->
9.
<!-- <param-name>contextConfigLocation</param-name>-->
10.
<!-- <param-value>/WEB-INF/applicationContext.xml</param-value>-->
11.
<!-- </init-param>-->
12.
</servlet>
13.
<!--
14.
applicationContext.xml文件代表示应用程序服务的配置和 bean 配置。如果想装入多个配置文件,可以在
15.
<param-value>标记中用逗号作分隔符。
16.
springmvc配置文件与spring配置的servlet名称有关[如本配置中是dd]

17.
通常springmvc配置文件名称结构为:[servlet-name]-servlet.xml,

18.
如果你没有指定init-param里面contextCofigLocation的值中对应的XML文件的话

19.
(也就是applicationContext全局配置文件没有配置在web.xml中的话),那么像本

20.
段代码对应在springmvc中的配置文件就应该是/WEB-INF/dipatcher-servlet.xml这样的文件,

21.
否则如果配置了applicaitonContext.xml这样的spring全局配置文件,如本配置那么就必须为/WEB-INF/dd-servlet.xml

22.
-->
23.
<servlet-mapping>
24.
<servlet-name>dd</servlet-name>
25.
<url-pattern>*.do</url-pattern>
26.
</servlet-mapping>
27.
</web-app></SPAN>

2.由于上面的初始化参数中没有指定名字的XML文件,因此在WEB-INF下面建立
dispatcher-servlet.xml
Xml代码


1.
<SPAN style="FONT-SIZE: medium"><SPAN style="FONT-SIZE: large"><?xml version="1.0" encoding="UTF-8"?>
2.
<!--看到下面的beans这个元素标签没有,必须有标签的声明-->
3.
<beans
4.
xmlns="http://www.springframework.org/schema/beans"
5.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6.
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 7.

8.
<!-- URL Mapping -->
9.
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
10.
<property name="mappings">
11.
<props>
12.
<prop key="/regAction.do">regAction</prop>
13.
</props>
14.
</property>
15.
</bean>
16.

17.
<!-- definition of View Resolver -->
18.
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
19.
<property name="viewClass">
20.
<value>org.springframework.web.servlet.view.JstlView</value>
21.
</property>
22.
<property name="prefix">
23.
<value>/view/</value>
24.
</property>
25.
<property name="suffix">
26.
<value>.jsp</value>
27.
</property>
28.
</bean>
29.
<!-- formController ,这个formController可以配置也可以不配置-->
30.
<bean id="formController"
31.
class="org.springframework.web.servlet.mvc.ParameterizableViewController">
32.
<property name="viewName">
33.
<value>form</value>
34.
</property>
35.
</bean>
36.

37.
<!-- Action Definition -->
38.
<bean id="regAction" class="org.lee.springmvc.demo.RegAction">
39.
<!--在MySpringMvc这个项目中就没有配置这个commandClass,
40.
因为它提前调用了setCommandClass(LoginForm.class)这个方法;这样跟下面效果一样
41.
不过还是建议配成下面这样的更好
42.
-->
43.
<property name="commandClass">
44.
<value>org.lee.springmvc.demo.RegInfo</value>
45.
</property>
46.
<property name="error_view">
47.
<value>error</value>
48.
</property>
49.
<property name="success_view">
50.
<value>success</value>
51.
</property>
52.
<property name="commandName">
53.
<value>myCommand</value>
54.
</property>
55.
</bean>
56.
</beans></SPAN></SPAN>

3.建立JSP文件
form.jsp
Html代码


1.
<SPAN style="FONT-SIZE: medium"><SPAN style="FONT-SIZE: large"><%@page contentType="text/html"%>
2.
<%@page pageEncoding="UTF-8"%>
3.
<%@taglib prefix="spring"
4.
uri="http://www.springframework.org/tags"%>
5.

6.
<%@taglib prefix="c"
7.
uri="http://java.sun.com/jsp/jstl/core"%>
8.
<html>
9.
<head>
10.
<meta http-equiv="Content-Type"

11.
content="text/html; charset=UTF-8">
12.
<title>Login Form</title>
13.
</head>
14.
<body>
15.
<h1>登入表单</h1>
16.
<spring:bind path="command.*">

17.
<font color="red">
18.
<b>${status.errorMessage}</b>
19.
</font><br>
20.
</spring:bind>
21.

22.
请输入使用者名称与密码:<p>
23.
<form name="loginform" action="login.do" method="post">

24.

25.
<spring:bind path="command.userName">

26.
名称 <input type="text" name="${status.expression}" value="${status.value}"/>
27.
<font color="red"><c:out value="${status.errorMessage}" /></font><br/>
28.

29.
</spring:bind>
30.

31.
<spring:bind path="command.password">

32.
密码 <input type="password" name="${status.expression}" value="${status.value}"/>
33.
<font color="red"><c:out value="${status.errorMessage}" /></font><br/>
34.
</spring:bind>
35.

36.
<input type="submit" value="确定"/>

37.
</form>
38.
注意:输入错误会再回到这个页面中。
39.
</body>
40.
</html></SPAN></SPAN>

4.建立jsp文件

success.jsp
Html代码


1.
<SPAN style="FONT-SIZE: medium"><SPAN style="FONT-SIZE: large"><%@page contentType="text/html"%>
2.
<%@page pageEncoding="GBK"%>
3.

4.
<html>
5.
<head>
6.
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
7.
<title>登入成功</title>
8.
</head>
9.
<body>
10.
<H1>哈啰! ${welcomeuser}!!</H1>

11.
这是您的神秘礼物!^o^<a href="login.do">退出登录</a>
12.
</body>
13.
</html></SPAN></SPAN>

5.建立一个java bean LoginForm.java
Java代码


1.
<SPAN style="FONT-SIZE: medium"><SPAN style="FONT-SIZE: large">package zz.it.beans;

2.

3.
public class LoginForm {
4.
private String userName;
5.
private String password;
6.

7.
public String getPassword() {
8.
return password;
9.
}
10.

11.
public void setPassword(String password) {
12.
this.password = password;
13.
}
14.

15.
public String getUserName() {
16.
return userName;
17.
}
18.

19.
public void setUserName(String userName) {
20.
this.userName = userName;
21.
}
22.

23.

24.
}
25.
</SPAN></SPAN>

6.建立controller LoginController.java
Java代码


1.
<SPAN style="FONT-SIZE: medium"><SPAN style="FONT-SIZE: large">package zz.it.controller;

2.

3.

4.
import org.springframework.validation.BindException;
5.
import org.springframework.web.servlet.ModelAndView;
6.
import org.springframework.web.servlet.mvc.SimpleFormController;
7.

8.
import zz.it.beans.LoginForm;
9.

10.
public class LoginController extends SimpleFormController {

11.
/**

12.
* 构造方法
13.
*/
14.
public LoginController() {
15.
// TODO Auto-generated constructor stub
16.
//setCommandClass(LoginForm.class);
17.
//这句话要是不写的话,那么在dd-servlet.xml中的loginController里面配置上如下:
18.
// <property name="commandClass">

19.
//<value>zz.it.beans.LoginForm</value>
20.
//</property>

21.
//这样效果也是一样的

22.
}
23.

24.
public ModelAndView onSubmit(Object cmd, BindException errors) {
25.
LoginForm loginForm = (LoginForm) cmd;
26.
if (loginForm.getUserName().equals("test")
27.
&& loginForm.getPassword().equals("test")) {
28.
return new ModelAndView(getSuccessView(), "welcomeuser", loginForm

29.
.getUserName());
30.
} else {
31.
errors.reject("ccc", "用户名或密码有误!");
32.
errors.rejectValue("userName", "nameErr", null, "用户名错误");

33.
errors.rejectValue("password", "passErr", null, "密码错误");

34.
return new ModelAndView(getFormView(), errors.getModel());

35.
}
36.
}
37.
}
38.
</SPAN></SPAN>

7.最后,整合部署,访问http://localhost:1234/MySpringMvc/login.do
效果图
初始登录界面

登录成功页面

登录失败页面

我估计初学者,最关心的大都有这两个问题
1.这个controller是怎样像struts那样进行封装数据的
2.<spring:bind>为什么这么用,为什么取值只能是command.xxx

1.controller是怎样进行数据封装的
要说这个问题,我不得不说SimpleFormController了
SimpleFormController是AbstractFormController的具体实现,允许你在配置文件里通过successView和formView属性来配置成功视图(表单成功提交后要转向的页面)和表单视图(显示表单的页面);如果提交不合法(有三种可能:1.validator出错。2.bind错误,也就是说从请求中提取参数封装到command的过程中出现了类型转化错误,比如将一个含字母字符串转换为Integer。3.onBindAndValidate()方法出错),则会重新返回到表单视图;如果提交合法,onSubmit()方法的默认实现会转向成功页面,当然你可以覆写该方法在转向之前填充一些你想返回的信息。
SimpleFormController的工作流与AbstractFormController差不多,唯一的不同是你不必自己去实现showForm()和processFormSubmission()。showForm()这个方法已经被类SimpleFormController实现了并被限定为final,你不可以在继承SimpleFormController的子类里覆写这个类。processFormSubmission()这个方法尽管可以去覆写但由于它几乎可以满足所有的要求,因此一般也不会有人去重写它。

它的处理流程是这样的:
  

get请求来到时,这样处理:
  

1) 请求传递给一个controller对象
  

2) 调用formBackingObject()方法,创建一个command对象的实例。  

3) 调用initBinder(),注册需要的类型转换器
  

4) 调用showForm()方法,返回准备呈现给用户的视图 ,如果“bindOnNewForm”属性设为true,则ServletRequestDataBinder会将初始请求参数填入一个新的表单对象,并且执行onBindOnNewForm()方法。

5) 调用referenceData()方法,准备给用户显示相关的数据。如用户登录需要选择的年度信息  

6) 返回formView指定的视图
post请求来到时,这样处理:
  

1) 如果sessionForm属性没有设定,则调用formBackingObject()方法,创建一个command对象的实例。否则从session中取得表单对象  

2) 将请求传来的参数写入command对象,看它的源代码,会发现它是这样来做的:
ServletRequestDataBinder binder = createBinder(request, command);

binder.bind(request);
3)执行onBind()方法,在绑定数据之后,验证数据之前对表单数据进行一些自制的修改动作。
  

4) 如果设置为要求验证(validateOnBinding属性被设定),则调用validator类进行数据验证  

5) 调用onBindAndValidate()方法,该方法允许自定义数据绑定和校验处理  

6)执行processFormSubmission()检验 Errors对象中含不含错误,如果含有错误则执行showForm()返回到填写表单页面;否则执行onSubmit()方法,进行提交表单,然后转向成功页面。
2.<spring:kind>的用法
在Spring框架体系下,可以说规约最少,最不受限制的就是表现层技术了。不像Struts,改定了好多的标签,而且有些功能还和标签绑定了。Sping也定义了一些标签,但这些标签只是给使用者提供了一些方便,并不会提供额外的功能或效果。

Sping Tag比较少,不超过十个,这里只介绍最常用的一个<sping:bind>,也叫作Spring绑定
<sping:bind>的path属性制定了与表单中的那个属性绑定,这样,${status.expression}就代表了那个属性的名称,${status.expression}代表那个属性的值。如果path属性为“XXX.*”则与那个表单的所有属性绑定。
上面的例子表单有两个属性username和password。实际上绑定方式有两种,第一种就像我的上一篇http://javacrazyer.iteye.com/blog/790834文章讲的的那样,第二种如下:
......

<spring:bind path="loginForm">

用户名:<INPUT name="userName" type="text" value="${command.userName}"/><br>

密码:<INPUT name="password" type="password" value="${command.password}"/>

</spring:bind>
这样尽管也行,但在错误信息处理上,针对用户名和密码的报错信息不会像原来那样显示出来了

所以验证我下面要说的话:
使用<sping:bind>标签,在初次进入表单页面时并不会有什么作用,而是当表单提交后,如果有BindException错误时再返回这个页面时,可以把先前的输入显示在input里。

说到错误信息处理,我又要许多要说了,来看看我前一篇文章http://javacrazyer.iteye.com/blog/790834中controller中的
errors.reject("ccc", "用户名或密码有误!");

return new ModelAndView(getFormView(), errors.getModel());
它调用了BindException的reject方法,这样,再调用BindException的getModel()方法,就把错误连同表单等信息一并返回到表单页面用以显示。
reject方法的第一个参数是错误码,如果设定了国际化资源,则显示资源文件中该错误码对应的错误条目,如果没有设定了国际化资源,则显示reject方法的第二个参数。
reject方法的不足之处是在表现层不能区分错误消息属于那个字段,即不能说明是username不对呢还是password不对。解决这种情况可以使用rejectValue方法,这也是更一般使用的方法。rejectValue方法定义如下:
rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage)

第一个参数指定表单的域,即username或password,这样就可以分辨到底是那块出了问题;第二个参数和reject方法的第一个参数一样,制定错误码;第三个参选数制定了资源文件中的占位符;第四个参数和和reject方法的第二个参数一样。rejectValue方法还有一个简化的定义
rejectValue(String field, String errorCode, String defaultMessage)

上面是在Controller里使用的方法,使用上述方法后,若果出现BindException错误,返回表单页面时就会显示错误信息,那么如何在页面里显示错误信息呢?
上面/WEB-INF/jsp/login.jsp里由于在controller里使用的是reject方法,所以只能那么显示,如果我们使用rejectValue方法,例如改动LoginController:
errors.rejectValue("userName", "nameErr", null, "用户名错误");

errors.rejectValue("password", "passErr", null, "密码错误");
这样,就可以把页面改为如之前最后的形式
<spring:bind path="command.userName">

名称 <input type="text" name="${status.expression}" value="${status.value}"/>

<font color="red"><c:out value="${status.errorMessage}" /></font><br/>

</spring:bind>

<spring:bind path="command.password">

密码 <input type="password" name="${status.expression}" value="${status.value}"/>

<font color="red"><c:out value="${status.errorMessage}" /></font><br/>

</spring:bind>
这样错误的消息就绑定到相应的字段了。当然也可以不制定某个字段,一股脑都输出
到此,大家还是没看到我是怎样讲解command这个值的,至于为什么非要是command而不是其他值

这是因为setCommandClass这个方法是AbstractController中的一个方法,而这个

方法使用到的一个默认值public static final java.lang.String DEFAULT_COMMAND_NAME = "command";public static final java.lang.String DEFAULT_COMMAND_NAME = "command";

看到了没有,就是叫做command,所以在标签中就敢大胆的用啦

3.最后还有几个小问题
(1)一个常见的错误:

不通过controller直接访问含有spring:bind标签的JSP页面会出现下面的错误:

javax.servlet.ServletException: Neither Errors instance nor plain target object for bean name 'person' available as request attribute

解决办法:

http://spring.jactiongroup.net/viewtopic.php?p=5482
(2)星号(*)的意思

global and all field errors,

## use wildcard (*) in place of the property name

<spring:bind path="company.*">

<c:forEach items="${status.errorMessages}" var="error">

c:out value="${error}"/><br/>

</c:forEach>

</spring:bind>
(3)command的意思

3-1 commandClass

相当于struts中的ActionForm,用来封装V中的数据,方便在C中使用。
3-2 commandName

用来指定JSP中的数据需要绑定到哪个对象。默认为command

比如下面的配置中,commandName就是command

<spring:bind path='command.email'>

<td><input type='text' name='${status.expression}'

value='${status.value}' size='30'

maxlength='100'></td></tr>

</spring:bind>

因为是缺省值,所以它就不需要再在Controller中显示声明
如果在Controller中设置了setCommandName("me");则上面的配置文件需要改为:

<spring:bind path='me.email'>

<td><input type='text' name='${status.expression}'

value='${status.value}' size='30'

maxlength='100'></td></tr>

</spring:bind>

简单吧。

(4)一个要注意的问题(原文链接)

一个普通的<spring.bind>的使用类似于:
<spring:bind path="user.age">

<input type="text" name="age" value="${status.value}">

<font color="red">${status.errorMessage}</font>

</spring:bind>
需要注意的是:<input>的name属性值必须与<spring:bind>的path属性的匹配,否则就绑定不了!
例如下面的代码就绑定不了
<spring:bind path="user.age">

<input type="text" name="theAge" value="${status.value}">

<font color="red">${status.errorMessage}</font>

</spring:bind>
为了避免手误,强烈推荐下列方法来绑定:
<spring:bind path="user.age">

<input type="text" name="${status.expression}" value="${status.value}">

<font color="red">${status.errorMessage}</font>

</spring:bind>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: