`
kkkhhhli
  • 浏览: 11601 次
  • 性别: Icon_minigender_1
  • 来自: 南京
最近访客 更多访客>>
社区版块
存档分类
最新评论

struts1.x、struts2.x和springmvc浅析

    博客分类:
  • java
阅读更多
入住javaeye也要1年半了,第一次给自己的blog丰富点. 从当前javaEE项目来说,有关view层的框架做个小总结.
一: struts1.x
A配置:
1 导入struts1.x的jar包到web-inf/lib下面
2 在web-inf目录下新建struts-config.xml文件,配置struts相关内容
3 web.xml配置加入:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
- <init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
- <init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
- <init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
- <servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
配置随容器启动的servlet,并初始化struts的配置文件.设置由struts处理的请求标识
4 编写action控制类,继承Action[复杂情况继承DispactureAction],同时在struts-config.xml中配置这个控制类action.例如:
<action path="/stock" parameter="method" name="stocklogForm"   type="com.xuanmu.struts.action.stock.StockAction" scope="request">
<forward name="LIST" path="/productsList.jsp" />
</action>
当截取到请求为stock时就由StockAaction处理.[继承DispactureAction的话分发到parameter值对应的方法中去], 该方法返回由字符串封装[LIST]的ActionForward对象,然后再struts-config.xml中的匹配 ,决定返回呈现的页面

B流程:
1预备工作:服务器启动,Web应用启动时就会加载web.xml初始化actionServlet和记载struts配置文件(struts-config.xml),读配置信息到内存中,供以后action调用
2(由请求定位action控制类)
用户通过客户端向服务器发出一个请求,http://localhost:8080/struts_login/login.do
我们已经在web.xml配置了所有符合某特定格式的请求都将由struts指定的Servlet来处理。比如:只要是以.do结尾的请求(*.do)都由 org.apache.struts.action.ActionServlet来对其进行处理.ActionServlet会拿到用户的请求,并且去分析这个URL,它会截下 /login. 截下来之后,它是为了去struts-config.xml这个配置文件里面找<action>标签path属性的值等于所截部分的那个 Action.
3(页面数据注入)
找到对应的action之后,ActionServlet会把表单提交的数据给存放(生成对应调用 set/get方法)到struts-config中相应的action标签的name属性值指定的actionform类中(若有, [actionform的子类,并且在form-bean标签中配置了,若要进行数据验证可以在actionform中覆盖validate方法,推荐使用js,减轻服务器负担]).同时把actionform和当前HttpServletrequest 对象注入到代调用的action方法中.
4(调用action的处理方法)
[默认是execute方法可以通过dispactureAction分发请求给自定义的方法]可以在方法中取得请求附属的数据(若需要),编写业务逻辑代码处理请求.
5(返回到view层的页面)
Action的业务逻辑方法会返回一个ActionForward对象 ,ActionForward对象根据此action配置的<forward>匹配name进而调转到对应path的jsp页面上.
C特性分析:
1 线程模式:单例模式,每个action只维护一个实例服务于对应的请求,效率较好,但多线程环境下需要考虑数据同步等安全问题
2 JSTL标签和struts标签处理页面展示,页面相对整洁

二:struts2.x
A配置:
1 导入struts2.x的相关jar包到WEB-INF/lib下
2 在项目的src目录下新建struts.properties或struts.xml
struts.properties和struts.xml具有相同的配置作用,配置项目相关
3 web.xml加入:
<!-- 延长action中属性的生命周期,以便在 jsp页面中进行访问,让actionContextcleanup过滤器来清除属性,不让action自己清除。-->
<filter>
<filter-name>ActionContextCleanUp</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class>
</filter>

<!-- 若有其他相关的filter 需要加在这个地方-->

<!--配置struts2过滤器-->
<filter>
<filter-name>webwork</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
</filter>

<filter-mapping>
<filter-name>ActionContextCleanUp</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>webwork</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

4 编写action请求处理类.可以继承struts2的 ActionSupport也可以不继承,(不过一般为了方便获取 request,response以及session 最好自己编写一个类继承ActionSupport,并在类中获取request等,让请求处理类继承这个类),然后根据页面和struts.xml配置决定请求的处理方法.
例1:
------页面
#  <s:form action="login.action" method="post">
#         <s:textfield key="username" name="user.username"/>
#         <s:password key="password" name="user.password" />
#         <s:submit key="submit" />
#   </s:form>
------struts.xml
#     <action name="login" class="cc.dynasoft.action.LoginAction">
#             <result name="success">/welcome.jspresult>
#             <result name="error">/login.jspresult>
#     </action>
这时请求会交由LoginAction的默认方法execute来处理,在LoginAaction中有user对象及其set方法,页面属性会自动注入到此user对象中,返回字符串[success],匹配struts.xml此action内的result值确定调转的展示页面
例2:
-----页面
<s:form action="submit.action">
<s:textfield name="msg"label="输入内容"/> 
<s:submit name="save"value="保存"align="left"method="save"/>
<s:submit name="print"value="打印"align="left"method="print"/> 
</s:form>
-----struts.xml:
<action name="submit" class="action.MoreSubmitAction">
<result name="save">/result.jsp</result>
<result name="print">/result.jsp</result>
</action>
由页面submit的method方法来指定对应的处理方法,方法返回字符串.继而确定调转展示页面

例3:
-----设置自定义的url后缀,有struts2处理例如struts.action.extension=php.默认为action,即处理所有*.action的请求
-----页面
<form  method="post" action="Kinder_add.php"
<input type="text" name="kinder.name">
<input  type="text"name="kinder.zip">
<input type="submit" value="提交">
</form>
-----strust.xml
- <action name="*_*" method="{2}" class="ostar.lg.action.{1}Action">
<result name="success">/default.jsp</result>
</action>
这样的意思是:所有由'_'间隔的请求都会有'_'前面的字符串同名的action类处理,并交给这个类的和'_'后面字符串同名的方法处理[简化了配置],方法返回字符串继而确定调转展示的页面.(*_*只是一种自定义格式,可任意配置)
B 流程:
1、客户端初始化一个对服务器的请求(tomcat);
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于 Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin);
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个 Action;
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;
5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类;
6、ActionProxy创建一个ActionInvocation的实例。
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。
C特性分析:
1 线程模式,每一次请求都会产生一个新的实例处理请求. 多线程环境没有数据同步问题.
2 引入数据的依赖注入
[页面表单数据到action的注入,实例对象的注入,都是通过set注入,需要提供set方法]
3 基于AOP的拦截器,可以在每次请求前后灵活控制
4 配置文件支持表达式,基于约定优于配置的话可简化配置文件
4 内置以插件形式支持ajax如dojo,支持多种模板展示jsp、freemarker,Velocity等

三 springMvc:
A(2.5版+spring注解)配置:
1 复制spring相关jar包到web-inf/lib里面
2 web.xml新增如下:
<!--   Spring 容器启动监听器 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<!--   Spring MVC 的 Servlet ,它将加载 WEB-INF/annomvc-servlet.xml 的配置文件,以启动 Spring MVC 模块
-->
- <servlet>
<servlet-name>annomvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
- <servlet-mapping>
<servlet-name>annomvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
[这里spring回根据servlet-name的值(annomvc)去加载(annomvc).servlet.xml]

注解1:
在web-inf/新建annomvc-servlet.xml里面新增如下:

<!--:对 web 包中的所有类进行扫描,以完成 Bean 创建和自动依赖注入的功能 -->
<context:component-scan base-package="com.controller" />
这样就会自动扫描controller包下面的所有类

<!--:对模型视图名称的解析,即在模型视图名称添加前后缀  -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/test/" p:suffix=".jsp" />

3 这样你在com.controller下面新建一类Test类
@Controller
@RequestMapping("/test.do")
public class Test{
@RequestMapping(params="method=show")
public String show(User user,ModelMap model){
System.out.println(“calling...”);

}
}
这样当页面有请求,例如action="test.do?method=show"时就会调用Test类中的show方法. 是不是简化了很多..

注意:需要使用spring注解时还需要在配置文件中加上相应的xml的schema验证

B流程:
spring mvc请所有的请求都提交给在web.xml中配置的DispatcherServlet,由它查询一个或多个HandlerMapping,找到处理请求的Controller,并且将请求提交给这个类。
Controller进行业务逻辑处理后,会返回一个ModelAndView
Dispathcher查询一个或多个 ViewResolver视图解析器,找到ModelAndView对象指定的视图对象 ,视图对象负责渲染返回给客户端。
C 特性:
1 线程模式:单例模式,效率较好.
2 基于方法级别的拦截,而不是基于类。更细粒度的灵活控制
3 通过注解简化了很多配置,但同时在代码中增加了和业务不相干的代码.
[并不是所有项目都适合通过注解,虽然可以简化繁琐的配置,但是对于项目经常需要改动时,有可能需要更改代码并重新编译后才能使之生效,而配置文件的更改可以自动服务器发现,及时更新]

总结:
这里可看出这几个框架大致有哪些异同,可以根据项目来适当选择.个人感觉springmvc 这的不错,struts2 回归从单例模式回归.每次都是新的实例.+ 项目拦截器存在过多等问题,感觉效率不是很好. springmvc 则提供的最简化的请求处理映射,能极大提高项目效率.
【曾看到过一个做测试的哥们说,做并发压力测试,struts2每秒到达300左右,springmvc到达了2000/s.】

总之.根据项目而选择所需要架构.
下次有机会把我springmvc(注解) + spring +hibernate小demo分享下,希望有经验的拍砖并指点下. over。
=========================
struts2 与 Spring MVC比较
struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入
struts2实际上是通过setter getter方法与request打交道的
struts2中,一个Action对象对应一个request上下文

spring3 mvc不同,spring3mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去
在spring3mvc中,一个方法对应一个request上下文

好了 我们来整理一下
struts2是类级别的拦截, 一个类对应一个request上下文,
springmvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应
所以说从架构本身上 spring3 mvc就容易实现restful url
而struts2的架构实现起来要费劲
因为struts2 action的一个方法可以对应一个url
而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了

===================================
spring3mvc的方法之间基本上独立的,独享request response数据
请求数据通过参数获取,处理结果通过ModelMap交回给框架
方法之间不共享变量

而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的
这不会影响程序运行,却给我们编码 读程序时带来麻烦
==============
spring mvc 和 struts2.0哪个好点
自己用了一下,struts1.X和版本和spring 2.0 MVC的实现方式关不多,如果用myeclise开发,strut的效率高许多,而spring得自己手写不少的配置. 如果以struts2.0 和spring 对比,其实很多也差不多,如标签实现,strut2.0的标签,虽然灵活,但jstl实现起来,差不多. 但spring mvc拦截器,功能太弱. 到底用哪个好点,不过spring mvc的IOC方式,倒是不错,这点是我最喜欢的.但没有才插件来支持,每行代码都得手写,myeclipse工具也发挥不了多少的作用. 请问各位,到底哪一个比较好一点.
MVC最复杂的是表单处理,这一块Struts做得较好,而Spring灵活性确实折服人,所以提出如下建议: 中小型项目用纯Spring就足已; 大型项目用Struts+Spring。
Struts2集成第三方很好用  比如Ajax的JSON、统计报表、统计图表等等  而且用了模型驱动(set、get)之后  和前台的交互变的很简单  相比struts1没得说 用Spring进行整合  可以成为开发利器
对于你要使用Struts2.0,Spring  MVC或者是Struts1.X还应该看你 的实际需求,你需要什么就要学什么,每种框架都有它的好处, 要看你的熟练程度,Struts1.x是学习框架的基础,Spring MVC 只是比Struts1.x多一点而已,而Struts2是Webwork和Struts的结合, 比起Struts1.x和Spring MVC优势更多一些。
==============
spring mvc配置问题
在配置文件applicationContext.xml中定义了
<bean   id="baseTransactionProxy"   class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"   abstract="true">
<property   name="transactionManager"   ref="transactionManager"/>
<property   name="transactionAttributes">
<props>
<prop   key="insert*">PROPAGATION_REQUIRED</prop>
<prop   key="update*">PROPAGATION_REQUIRED</prop>
<prop   key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean   id="manager"   parent="baseTransactionProxy">
<property   name="target">
<bean   class="slim.business.BookTransactionImpl">
<property   name="bookDao"   ref="bookDao"/>
<property   name="userDao"   ref="userDao"/>
<property   name="classDao"   ref="classDao"/>
<property   name="transactionDao"   ref="transactionDao"/>
</bean>
</property>
</bean>
,而mvc的配置文件中定义了
<bean   id="login_action"   class="slim.web.controller.LoginFormController">
<property   name="commandClass">
<value>slim.web.form.LoginForm</value>
</property>
<property   name="bt"   ref="manager"/>
<property   name="successView"   value="index"/>
</bean>
会出现无法初始化manager的问题,我想这可能是配置文件初始化的问题,请高手说明一下原因,谢谢

ps:出错信息
Can't   resolve   reference   to   bean   'manager'   while   setting   property   'bt';   nested   exception   is   org.springframework.beans.factory.NoSuchBeanDefinitionException:   No   bean   named   'testspring'   is   defined
org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference
(BeanDefinitionValueResolver.java:180) 
===============
Spring MVC框架的高级配置
本文将为您提供关于Spring MVC框架的配置技巧,以帮助治理基于Spring的web应用程序的多个实例。本配置治理主题常被学术界所忽略,但是,这对于现实的Web开发尤为重要。本主题并不直接关联任何具体的技术,因此,我们将从最基本的概念开始对这个问题进行说明。下面,我们将根据Spring MVC框架,为基于本技术开发的项目提供一系列的解决方案。

Spring配置

人们经常会在一台以上的主机上配置一种Web应用程序。例如,在生产中,一个网站可能只有一个实例。除了此实例外,开发人员可以在用于开发的机器上配置其他的(开发)实例。也可以在公司(机构)内部的本地开发服务器上维护其他应用程序装置,这将让您受益匪浅。该实例的目的是使Web设计者可以获得有质量保证的材料,并为需要为应用程序提供文件资料的人提供准入。

大家都知道,即使是最简单的场景,也需要安装、配置和维护三个实例。而对于位于不同地理位置的团队来说,要从事这样的项目便更加困难。对于任何不是非凡简单的Web应用程序项目,都需要多名开发人员来安装项目装置和本地设置以及运行单元测试的装置等。

很多组织都将自己开发的产品作为Web应用程序。我们可以在很多产品中发现这种情况,例如电子商务系统、内容治理系统(CMS),以及博客发布平台等。这类产品可在多个服务器中进行部署。对于成功的多用途Web应用程序来说,他们的开发人员必须要保证他们的应用程序便于安装,并且能够与其他Web应用程序完美集成。经过上述讨论之后,我们应该明了,作为本文主题的应用程序配置是通用Web应用程序项目开发人员所需要解决的重要问题之一。

诸如CVS或Subversion之类的版本控制系统是开发组织使用的一种标准工具。这种工具代表了一些组织的中心源代码版本库,它们被用于保持源代码的有序。用户可以跟踪应用程序源代码的变化,显示不同版本的区别,并可以确定项目分支。而且,它们使得在应用程序部署中进行部分更新成为可能。

很明显,版本控制系统软件是跟踪源代码所必需的,它对于解决应用程序配置问题有非常大的帮助。在本文中,我们将不会把重点放在版本控制系统上,因为这方面已经有很多相关的材料了。在此,我们将关注版本控制问题中的一个小话题:如何使Web应用程序的配置更加便捷(尤其是使用Spring MVC框架编写的Web应用程序)。

问题是:我们在此讨论的是一种什么样的配置?任何Web应用程序都需要一些资源,这些资源通常都是其所运行的服务器所特有的,例如数据库URL、发送电子邮件的SMTP服务器,以及包含专用软件文件的文件夹等。这样的设置应该集中,从而使应用程序配置更加简单。

但是,这只是这个问题最简单的一种版本。有时候,在应用程序开发中需要更加复杂的配置。这意味着,必须将各次部署中的不同Bean连接起来,而这会使问题更加复杂。

这些应用程序配置问题的解决方案有诸多优势,包括:简化应用程序的安装和配置过程,使源代码版本控制更加简便,减少源代码版本库中的冲突现象。下面,我们将通过示例具体讨论这个话题。

问题

我们首先来演示一下上文所提到的最简单的版本。在这一场景中,我们希望在应用程序部署中改变的是简单的配置参数,例如链接、密码等。假如您曾经使用Spring MVC框架开发过Web应用程序,那么您应该知道这里将用到的两个配置文件:

/WEB-INF/applicationContext.XML,它让您可以配置Bean,或者显示应用程序上下文。通过这个文件,您可以定义自己的业务逻辑Bean、资源以及其他可以与Web端口相关联的所有Bean。

/WEB-INF/[servlet-name]-servlet.xml,它被用于配置Web层、视图解析器、控制器、校验器以及其他所有MVC框架中必需的Bean。[servlet-name]指的是在web.xml部署描述符中定义的Spring dispatcher servlet的名称。

那么问题在哪儿呢?问题就出在applicationContext.xml中将包括一些特定于主机的Bean定义。其中,最明显的一个示例就是包含了JDBC连接信息的bean,但是任何一种稍微复杂些的应用程序都有十几个类似的Bean。看一下下面的示例:
〈bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"〉
〈property name="driverClassName"〉
〈value〉org.postgresql.Driver〈/value〉
〈/property〉
〈property name="url"〉
〈value〉jdbc:postgresql://localhost/test〈/value〉
〈/property〉
〈property name="username"〉
〈value〉postgres〈/value〉
〈/property〉
〈property name="passWord"〉
〈value〉〈/value〉
〈/property〉
〈/bean〉


这个解决方案的问题在于对applicationContext.xml文件的维护。对于初学者来说,设想一下,项目放在源代码版本控制系统中,例如 CVS。下面,假设您希望在网站中添加新的功能,那么就需要在应用程序上下文定义中添加额外的Bean定义。问题是如何在生产服务器上体现这些改变。

通常情况下,应用程序的本地实例不会与活动站点使用同样的数据库,因此applicationContext.xml文件将包括让您能够访问本地数据库的设置。当您想提交在源代码版本库中的改变时,就需要注重这些特定于主机属性的同步性。版本库中的文件最终可能使用本地设置中的配置。假如想在生产服务器上更新配置,就必须手动同步这些属性的值。这是非常枯燥的任务,而且还非常轻易出错。

对于应用程序的每个实例来说,这个问题更加重要。假如有三位开发人员正在使用代码段基址,而且他们使用的是本地的数据库。当您提交更改的时候,他们每个人在本地服务器上更新源代码的时候都必须非常谨慎。他们会手动同步这些更改,然后提交他们的工作。这样一来,版本控制系统对于这些配置文件来说已经毫无用处。假如曾经使用过Spring MVC,那么您应该知道applicationContext.xml是应用程序中的要害组件,因为是它将所有的东西粘合在一起。所以,我们需要一种机制来帮助使应用程序中各项保持有序,这点非常重要。

正如前面所提到的,这是您可能碰到的较简单的配置问题。更难的问题出现在当需要在不同服务器中进行不同的Bean连接的时候。这类问题常会出现在日常软件开发任务中。例如,假如您的产品有一个客户身份验证模块,可以对来自关系数据库或 LDAP服务器中的用户进行身份验证。自然,这一身份验证模块可以使用抽象了特定版本库的Bean进行配置。假如您想改变不同应用程序部署中验证用户的方式,就需要在applicationContext.xml文件中进行不同的Bean连接。这种配置问题常见于在部署中有可配置特性的所有应用程序。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics