Spring MVC vs Strut2 MVC

1 MVC概念
1.1 什么是MVC模式
MVC全称是Model View Controller,模型(Model) - 视图(View) - 控制器(Controller)。MVC起源于20世纪70年代后期,它开始是由Trygve Reenskaug为Smalltalk平台开发的框架,现成为了一种流行的模式。


Model(模型):模型是信息的载体,包括业务数据。
View(视图):视图是用户看到并与之交互的界面。
Controller(控制器):从视图中接收数据,调用业务逻辑处理数据,并将获取的数据对象返回到相应的视图中。




由图可见:
1)View依赖Model,但是Model不依赖View。
从模型中分离出表现,这样可以使开发人员更加专注,因为开发视图的人,更加关注如何布局,美观,界面操作友好性,而开发模型的人,才更关注业务逻辑,同数据库的交互等等,这样可以将两者开发人员分离开来,使开发人员更加专注于某一方面,做起来才更专业。毕竟人无完人,上帝给了你一个才能的同时也关闭了另一份才能,所以做人嘛,千万别拿自己的短处去PK别人的长处,想弥补自己的缺点去追赶别人,其实只要充分发挥自己的长处,将之发挥到极致,才能与众不同、出类拔萃。

另外使系统更加松耦合,可以使用同一套模型,切换不同的View去展示,比如PC端、手机端,另外可以在不修改另外两层的情况下替换Model,这个跟分层模式一样,同分层不同的是分层架构中不相邻的层不允许相互依赖和调用,而在MVC中View要依赖Model。

2)Contoller充当一个中转站。从View中接收参数,调用业务逻辑,生成Model,然后将Model和请求转发到相应的View中。

1.2 J2EE领域的MVC
Model:业务对象Bean。
View:通常由JSP、Servlet或者XSLT等实现。
Controller:通常是一个Controller Servlet,这个一般会借助于框架实现例如Spring mvc的Controller,Struts mvc的Action等。


2 Spring MVC 之helloworld
仍然是国际惯例,helloworld:
因为这个需要应用服务器,所以要遵循servlet规范目录,代码的目录如下图所示:




web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
   <display-name>spring mvc helloworld</display-name>
   <description>spring mvc helloworld</description>
<!--配置controller的控制器,可以用逗号分隔配置多个  -->
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/hello-servlet.xml</param-value>
   </context-param>
   <listener>
  <!--配置上下文载入器,用于载入contextConfigLocation配置的配置文件 -->    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
<!--配置DispatcherServlet,这是Spring mvc的核心,匹配的url由他处置 -->
   <servlet>
      <servlet-name>hello</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
  
   <servlet-mapping>
      <servlet-name>hello</servlet-name>
<!--*.htm均指向DispatcherServlet,当然可以配置成*.do,等,也可以配置多个-->
      <url-pattern>*.htm</url-pattern>
   </servlet-mapping>
</web-app>


控制器, HelloController:

public class HelloController implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("hello controller");
        return new ModelAndView("jsp/hello.jsp");
    }
}


配置控制器,hello-servlet.xml:
注意其中的bean配置的是name属性,而不是id,因为id不可以有"/"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
     <bean name="/hello.htm" class="org.frank1234.spring.mvc.HelloController">
   </bean>
</beans>



JSP页面,hello.jsp:
<html>
    <body>
        <h1>hello frank1234 ,begin spring mvc</h1>
    </body>
</html>

启动tomcat,浏览器中输入:
http://localhost:8088/hello/hello.htm ,输出如下图所示:



3 Spring MVC
3.1 请求的生命周期




结合helloworld程序解释步骤:
1)用户请求URL http://localhost:8088/hello/hello.htm,由于在web.xml配置了匹配规则,符合匹配规则,所以请求会交到DispatcherServlet中。
2)DispatcherServlet会根据默认的映射处理器BeanNameUrlHandlerMapping,根据hello-servlet中的配置信息找到HelloController。
3)DispatcherServlet将请求分发给HelloController.
4)HelloController返回一个ModelAndView对象,
5)由于helloworld程序没有使用视图解析器ViewResolver,所以就没有步骤5。
6)将请求导向"jsp/hello.jsp",显示页面。

3.2 控制器
1)简单控制器:
helloworld使用的就是简单控制器。
实现Controller接口或者继承AbstractController都属于简单控制器。
只是实现Controller接口要实现方法:
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
继承AbstractController要实现方法:
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)

2)命令控制器
使用命名控制器可以将请求的参数自动绑定到命令对象中,类似于struts的ActionForm,只是Spring的命令对象不需要继承Spring的类。
代码示例:
public class HelloCommandController extends AbstractCommandController {
    public HelloCommandController(){
       setCommandClass(HelloCommand.class);
    }
    public ModelAndView handle(HttpServletRequest request,HttpServletResponse response,Object command,BindException errors) throws Exception{
       HelloCommand helloCommand = (HelloCommand)command;
        //xxxx
        return new ModelAndView("jsp/hello.jsp");
    }
}



3)多动作控制器
上面这种一个url就得对应一个Controller,如果url很多的话,就会造成大量的Controller类,如果想某一类url都请求同一个Controller,然后每个url请求Controller中的某个方法的话,可以使用Spring的MultiActionController,这个类似于Struts的DispatchAction。
代码示例:
HelloMultiActionController类:
public class HelloMultiActionController extends MultiActionController {
    public ModelAndView sayHello(HttpServletRequest request,HttpServletResponse response){
        return null;
    }
    public ModelAndView sayGoodbye(HttpServletRequest request,HttpServletResponse response){
        return null;
    }
}


hello-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

   <bean id="paramResolver"
        class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
      <property name="paramName">
         <value>method</value>
      </property>
   </bean>
   <bean name="/hello.htm"
      class="org.frank1234.spring.mvc.HelloMultiActionController">
      <property name="methodNameResolver">
         <ref bean="paramResolver" />
      </property>
     
   </bean>
</beans>



这样如果http://localhost:8088/hello/hello.htm?method=sayHello
就会请求到HelloMultiActionController中的sayHello()方法。
另外,hello-servlet.xml还可以这么配置:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

   <bean id="paramResolver"
        class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
      <property name="paramName">
         <value>method</value>
      </property>
   </bean>
   <bean name="/hello.htm"
      class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
      <property name="methodNameResolver">
         <ref bean="paramResolver" />
      </property>
      <property name="delegate">
         <ref bean="login_delegate" />
      </property>
   </bean>
   <bean id="login_delegate"
      class="org.frank1234.spring.mvc.HelloMultiActionController" />
</beans>


这样类HelloMultiActionController,就不用继承MultiActionController了,直接写成如下就可以了:
public class HelloMultiActionController  {
    public ModelAndView sayHello(HttpServletRequest request,HttpServletResponse response){
        return null;
    }
    public ModelAndView sayGoodbye(HttpServletRequest request,HttpServletResponse response){
        return null;
    }
}

4)FormController
我觉得校验用js处理更合适,这样可以减轻服务器端的压力。
4 Struts2 MVC之 helloworld
代码目录结构如下:



struts2依赖的jar包列表:





web.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>Struts 2 demo</display-name>
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

如果filter-class配置成:org.apache.struts2.dispatcher.FilterDispatcher
会显示这个FilterDispatcher已过期。

struts.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <!-- 定义成true可以看到日志输出,生产环境下要关闭-->
    <constant name="struts.devMode" value="true" />
    <package name="helloworld" extends="struts-default">
        <action name="hello"
                class="org.frank1234.struts2.helloworld.HelloWorldAction"
                method="go">
            <result name="success">/jsp/helloworld.jsp</result>
        </action>
    </package>
</struts>

其中的method="go"可以随便命名,只要和HelloWorldAction中的方法名对应就OK了。

HelloWorldAction类:
public class HelloWorldAction {
    private String name;

    public String go() throws Exception {
        System.out.println("helloworldaction");
        setName("frank1234");
        return "success";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


连HttpServletRequest对象和HttpServletResponse对象都不需要啦,爽歪歪啊。

helloworld.jsp:
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>Hello World struts2</title>
</head>
<body>
<h1> Hello World, <s:property value="name"/></h1>
</body>
</html>

启动tomcat,浏览器中输入:
http://localhost:8088/hello/hello.action
不加.action效果一样。




5 Spring MVC vs Struts MVC
Struts1和Struts2有较大的不同,本文说的主要是Struts2的MVC,Struts2是从Webwork发展而来的。Struts1太老了,搞技术的应该喜新厌旧,关注新技术。

1)从web.xml配置可以看出Spring基于Servlet,Struts2基于Filter机制。
2)用Spring mvc的话,使用Spring的IoC和AOP会更容易些。
3)Struts2省去了HttpServletRequest和HttpServletResponse对象,并且不依赖任何Struts2的类,这样更容易测试,更符合可测试性和松耦合这两个核心价值观。
4)Struts2提供的前台taglib更多一些,不过笔者更倾向于使用JSTL。
5)Spring的Controller是单例的,Struts2每次都产生新的实例,这样需要注意Spring的实例变量的线程安全性。
6)总体感受,都很优秀,由于了解的不深入,感觉struts2更简练一些。偶觉得团队用哪个用的熟就可以选择哪个,因为对于开发来说,难的是业务逻辑。






《Spring in action》
《企业应用架构模式》
http://baike.baidu.com/link?url=1KYanQ3dwZX0yOu-5_GVGn9pCjMWGgEBQ9Zg3PiB_yNL3xgKXpzduLJNYEoPHxQE0InNip03woCdOBrtRmRUDDyKRWn9_y7JaaNX-Y8pSJm6_cKGaz7ierPjejZ6jDMOHQ_6P5JleQpJ9V8tBeYKSVRgtRCQPAwcshn17PORY3SIdqmubW8FNCawXdRi2rZfBPY1lF15_6Q-V8UGXDxtm_
http://xp9802.iteye.com/blog/1214256
http://zh.wikipedia.org/zh/MVC
http://www.ruanyifeng.com/blog/2007/11/mvc.html
http://blog.csdn.net/wanghuan203/article/details/8623048
http://developer.51cto.com/art/200906/130473.htm
http://blog.csdn.net/qiulongtianshi/article/details/7776694
http://wuquanyin1011.iteye.com/blog/693364
http://blog.csdn.net/gstormspire/article/details/8239182
http://www.yiibai.com/struts_2/struts_examples.html

猜你喜欢

转载自frank1234.iteye.com/blog/2172294
今日推荐