社会主义接班人 阅读(90) 评论(0)

昨天在eclipse上搭建了Struts2框架,只是引入包,新建了一个Struts.xml,在Struts.xml、web.xml中做了一些配置就能运行hello.jsp,感觉也好神奇,而且Struts2是MVC框架,Model、Controller、View在哪里,也没像.Net的MVC那样一目了然,好奇它的工作原理,今天在公司研究了一天.

一、创建项目

这里在昨天搭建框架时的项目MyStruts2的基础上进行修改。

1.在src下创建com.test.cyw的包,然后创建一个TestAction的类,用来创建Action,Struts2中的action都是继承自com.opensymphony.xwork2.ActionSupport。实现execute()方法。请注意execute()的返回值是"testcyw".

package com.cyw.test;
import com.opensymphony.xwork2.*;

public class TestAction extends ActionSupport {

    private static final long serialVersionUID = 1L;

    @Override
    public String execute() throws Exception {
        
        return "testcyw";   
    }
}

2.在配置文件Struts.xml中增加配置,请注意下面的截图的action的name属性和result的name属性。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
    <package name="default" extends="struts-default">
            <default-action-ref name="hello" />
            <action name="hello">
                <result>/WEB-INF/hello.jsp</result>
            </action>
            <action name="test" class="com.cyw.test.TestAction">
                <result name="testcyw">/WEB-INF/test.jsp</result>
            </action>
    </package>
</struts>

3.创建一个test.jsp页面,在body体中输入下面的代码<h2>Hello,Test Action!</h2>

4.在浏览器输入http://localhost:8088/MyStruts2/test,浏览器会响应如下,请留意输入的url的test,以及配置文件的action、result的name属性,和execute()方法的返回值。

execute()返回的是对应的result的name属性,用户输入浏览器的是action的name属性。

 

二、工作流程

1.当在浏览器输入http://localhost:8088/MyStruts2/test时,发起请求,Tomcat截获请求之后会将请求封装成HttpServletRequest对象

2.由于在web.xml中配置了一个过滤器,会执行org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter来进行过滤,其实在它之前还有两层过滤:ActionContextCleanUp的可选过滤器、其他过滤器(SiteMesh等),在Struts2.1以前调用FilterDispatcher,Struts2.1以后调用StrutsPrepareAndExecuteFilter。

   <filter>
        <filter-name>struts-prepare</filter-name>
        <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts-prepare</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

3.在StrutsPrepareAndExecuteFilter中会通过ActionMapper来决定这个请是否需要调用某个Action,这里通过name="test"能找到对应的Action:TestAction。

4.如果ActionMapper决定需要调用某个Action,StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy

5.ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类,找到了com.cyw.test.TestAction

6 ActionProxy创建一个ActionInvocation的实例。

7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。

8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果.返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper.这里TestAction执行execute()方法返回了一个字符串:"testcyw",通过这个找到该action下result的name="testcyw"的result,然后找到对应的jsp:test.jsp页面输出。

三、MVC框架

既然说Struts2是MVC框架,那它体现在哪里?MVC分别对应的是什么呢?

在上面的演示demo中,基本能体现出控制器和View,StrutsPrepareAndExecuteFilter算是中央处理器,来调配所有的Action(Controller),Action返回响应的jsp页面,这里没体现出Model,其实我们可以在action中定义实体然后再jsp中获取实体的属性,而且在struts2中获取更加方便。