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

SpringMVC应用程序架构----高级特性

2010-10-24 23:38 337 查看
Web 应用与MVC

目前比较好的MVC,老牌的有Struts、Webwork。新兴的MVC 框架有Spring MVC、Tapestry、JSF等。这些大多是著名团队的作品,另外还有一些边缘团队的作品,也相当出色,如Dinamica、VRaptor等。

这些框架都提供了较好的层次分隔能力。在实现良好的MVC 分隔的基础上,通过提供一些现成的辅助类库,同时也促进了生产效率的提高。

如何选择一个合适的框架?什么是考量一个框架设计是否优秀的标准?很难定夺的问题。旁观各大论坛中铺天盖地的论战,往往在这一点上更加迷茫。

从实际Web产品研发的角度而言(而非纯粹设计上,扩展性上,以及支持特性上的比较),目前Struts 也许是第一选择。作为一个老牌MVC Framework,Struts 拥有成熟的设计,同时,也拥有最丰富的信息资源和开发群体。换句实在点的话,产品基于Struts 构建,如果公司发生人事变动,那么,找个熟悉Struts的替代程序员成本最低。

从较偏向设计的角度出发,WebWork2 的设计理念更加先进,其代码与Servlet API 相分离,这使得单元测试更加便利,同时系统从BS结构转向CS接口也较为简单。另外,对于基于模板的表现层技术(Velocity、Freemarker和XSLT)的支持,也为程序员提供了除JSP之外的更多的选择(Struts也支持基于模板的表现层技术,只是实际中不太常用)。而对于Spring而言,首先,它提供了一个相当灵活和可扩展的MVC实现,与WebWork2相比,它在依赖注入方面、AOP 等方面更加优秀,但在MVC 框架与底层构架的分离上又与Webworks 存在着一定差距(Spring 的MVC 与Servlet API 相耦合,难于脱离Servlet容器独立运行,在这点的扩展性上,比Webwork2稍逊一筹)。

我们还要注意到,Spring对于Web应用开发的支持,并非只限于框架中的MVC部分。即使不使用其中的MVC实现,我们也可以从其他组件,如事务控制、ORM模板中得益。同时,Spring也为其他框架提供了良好的支持,如我们很容易就可以将Struts 与Spring 甚至WebWork与Spring 搭配使用(与WebWork 的搭配可能有些尴尬,因为两者相互覆盖的内容较多,如WebWork中的依赖注入机制、AOP机制等与Spring中的实现相重叠)。因此,对于Spring在Web应用中的作用,应该从一个更全面的角度出发。

第一个SpringMVC实例:

下面的实例,实现了一个常见的用户登录逻辑,即用户通过用户名和密码登录,系统对用户名和密码进行检测,如果正确,则在页面上显示几条通知信息。如果登录失败,则返回失败界面。

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

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

首先来看登录界面:

对应的index.html:

[b]<form action="login.do" method="post">


<table>

<tr>

<td>[/b]用户名:</td>

[b]<td><input
type="text" name="username" /></td>


</tr>

<tr>

<td>[/b]密码:</td>

[b]<td><input
type="password" name="password"></td>


</tr>

<tr>

<td
colspan="2" align="right"><input
type="submit" value="
[/b]提交"
/></td>


[b]</tr>


</table>

</form>[/b]

MVC
关键流程的第一步,即收集页面输入参数,并转换为请求数据对象。这个静态页面提供了一个基本的输入界面,下面这些输入的数据将被发送至何处,将如何被转换为请求数据对象?

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

当用户输入用户名密码提交之后,此请求被递交给Web 服务器处理,上面我们设定form提交目标为"/login.do",那么Web服务器将如何处理这个请求?

显然,标准Http
协议中,并没有以.do
为后缀的服务资源,这是我们自己定义的一种请求匹配模式。此模式在web.xml中设定:

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

[b]<web-app version="2.4"


xmlns="[/b]http://java.sun.com/xml/ns/j2ee"

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

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

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

[b] <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>

Config.xml[/b]配置文件:

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


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

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

<beans>

[b]<bean
id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">


<property name="viewClass">

<value>org.springframework.web.servlet.view.JstlView</value>

</property>

</bean>

<bean
id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">


<property name="mappings">

<props>

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

</props>

</property>

</bean>

<bean
id="LoginAction" class="com.hit.action.LoginAction">


<property
name="commandClass">


<value>com.hit.action.LoginInfo</value>

</property>

<property name="fail_view">

<value>/WEB-INF/loginFail.jsp</value>

</property>

<property
name="success_view">


<value>/WEB-INF/loginSuccess.jsp</value>

</property>

</bean>

</beans>[/b]

View
Resolver的viewClass参数

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

org.springframework.web.servlet.view.JstlView

其余可选的viewClass还有:

Ø org.springframework.web.servlet.view.freemarker.FreeMarkerView(用于基于FreeMarker模板的表现层实现)

Ø org.springframework.web.servlet.view.velocity.VelocityView(用于基于velocity模板的表现层实现)等。

“urlMapping”关系映射

可以看到,这里我们将“/login.do”请求映射到处理单元LoginAction。<props>节点下可以有多个映射关系存在,目前我们只定义了一个。

LoginAction定义

这里定义了逻辑处理单元LoginAction
的具体实现,这里,LoginAction
的实现类为com.hit.action.LoginAction。

LoginAction的请求数据对象

commandClass 参数源于LoginAction
的基类BaseCommandController,BaseCommandControlle
包含了请求数据封装和验证方法(
BaseCommandController.bindAndValidate ),它将根据传入的HttpServletRequest构造请求数据对象。

这里我们指定commandClass
为com.hit.action.LoginInfo,这是一个非常简单的Java
Bean,它封装了登录请求所需的数据内容:

package com.hit.action;

public
class LoginInfo {


[b] 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;

}[/b]

}

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

之后,对Http
请求中的参数进行遍历,并查找LoginInfo
对象中是否存在与之同名的属性,如果找到,则将此参数值复制到LoginInfo对象的同名属性中.请求数据转换完成之后,我们得到了一个封装了所有请求参数的Java 对象,并将此对象作为输入参数传递给LoginAction。

返回视图定义

对于这里的LoginAction
而言,有两种返回结果,即登录失败时返回错误界面,登录成功时进入系统主界面。对应我们配置了fail_view、success_view两个自定义参数。之后,Resolver 会将LoginAction的返回数据与视图相融合,返回最终的显示界面。

LoginAction.java:

[b]public class LoginAction extends SimpleFormController {


private String success_view;

private String fail_view;[/b]

public
String getFail_view() {


[b] return fail_view;


}[/b]

public
void setFail_view(String fail_view) {


[b] this.fail_view = fail_view;


}[/b]

public
String getSuccess_view() {


[b] retiurn success_view;


}[/b]

public
void setSuccess_viiew(String success_view) {


[b] this.success_view = success_view;


}[/b]

@Override

[b] protected ModelAndView onSubmit(HttpServletRequest
request,


HttpServletResponse response,

Object obj,

BindException ex) throws Exception {

request.setAttribute("message",
"success");


return new
ModelAndView(this.getSuccess_view());


}[/b]

}

其中:

⑴ onSubmit方法

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

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

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

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

用传入。

onSubmit方法包含了两个或者四个参数:Object obj和BindException ex。

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

数据对象的引用。

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

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

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

理异常情况(如显示对应的错误提示)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: