SSH框架(三) 常用WEB框架Struts1、Struts2和Spring MVC三者的区别

二: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加入:

<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等 

三 Spring MVC

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 通过注解简化了很多配置,但同时在代码中增加了和业务不相干的代码. 

[并不是所有项目都适合通过注解,虽然可以简化繁琐的配置,但是对于项目经常需要改动时,有可能需要更改代码并重新编译后才能使之生效,而配置文件的更改可以自动服务器发现,及时更新] 


我们用struts2时采用的传统的配置文件的方式,并没有使用传说中的0配置。spring3 mvc可以认为已经100%零配置了(除了配置spring mvc-servlet.xml外)。

Spring MVC和Struts2的区别:

1. 机制:spring mvc的入口是servlet,而struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这样就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。

2. 性能:spring会稍微比struts快。spring mvc是基于方法的设计而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细,但要小心把握像在servlet控制数据一样。spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通过setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。

3. 参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。

4. 设计思想上:struts更加符合oop的编程思想, spring就比较谨慎,在servlet上扩展。

5. intercepter的实现机制:struts有以自己的interceptor机制,spring mvc用的是独立的AOP方式。这样导致struts的配置文件量还是比spring mvc大,虽然struts的配置能继承,所以我觉得论使用上来讲,spring mvc使用更加简洁,开发效率Spring MVC确实比struts2高spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring3 mvc就容易实现restful urlstruts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。

6. 另外,spring3 mvc的验证也是一个亮点,支持JSR303,处理ajax的请求更是方便,只需一个注解@ResponseBody ,然后直接返回响应文本即可。送上一段代码(这个功能没有用过,暂且收藏了):

@RequestMapping(value="/whitelists")  
public String index(ModelMap map) {  
    Account account = accountManager.getByDigitId(SecurityContextHolder.get().getDigitId());  
    List<Group> groupList = groupManager.findAllGroup(account.getId());  
    map.put("account", account);  
    map.put("groupList", groupList);  
    return "/group/group-index";  
}  
// @ResponseBody ajax响应,处理Ajax请求也很方便  
@RequestMapping(value="/whitelist/{whiteListId}/del")  
@ResponseBody  
public String delete(@PathVariable Integer whiteListId) {  
    whiteListManager.deleteWhiteList(whiteListId);  
    return "success";  
}

小结:

Struts1.X和Spring MVC的实现方式差不多,如果myeclipse开发,Struts1.X效率快很多,而Spring MVC需要手写很多的配置文件。

Struts2.X和Spring MVC的很多地方相似,如标签实现,Struts2.X的标签虽然灵活,但jstl实现起来,差不多。

但是Spring MVC拦截器,功能太弱,到底哪个好点,不过spring mvc的IOC方式是一个挺好的功能。

MVC最复杂的是表单处理,这一块Struts做的比较好,而Spring灵活性确实非常棒。

Struts1.x是学习框架的基础,Spring MVC 只是比Struts1.x多一点而已,而Struts2是Webwork和Struts的结合, 比起Struts1.x和Spring MVC优势更多一些。












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值