Struts2 实战:从 登录Demo 看 Struts2 应用开发

摘要:
  作为 Struts2 的首篇文章,本文首先以 LoginDemo 为例介绍了构建一个简单的 Struts2 应用的一般步骤和流程,并结合 Struts2 框架的原理给出每个步骤的目的与内涵。紧接着以 MVC 为支撑、以该 Demo 为出发点概述了 Struts2 的运行机制,给出了 Struts2 应用的一次 “请求-响应” 的完整流程,揭示了 Struts2的 请求与视图相分离的本质。最后,针对该Demo所涉及到的知识点Namespace进行了深入探究,并总结出 Struts2 的请求路由规则。


一. 第一个Struts2应用的构建 — 登录Demo

创建一个 Struts2 应用一般需要以下几个步骤:

  (1) 下载、解压 struts-2.1.6-all.zip 并为 Web 应用添加 Struts2 支持。将目录 struts-2.1.6\apps\struts2-blank-2.1.6\WEB-INF\lib 下的 commons-fileupload.jar、commons-io.jar、freemarker.jar、commons-logging-1.1.jar、ognl.jar、struts2-core.jar 和 xwork-core.jar 七个jar包复制到Web应用的WEB-INF/lib路径下。如果需要在Web应用中使用 struts2 的更多特性,则需要将相应的jar文件复制到web应用的WEB-INF/lib路径下。


  (2) 编辑 Web 应用的web.xml配置文件,配置 Struts 2 的核心 Filter,该Filter被用来拦截用户请求。由于Web应用是基于请求/响应模式的,所以为了让 Struts2 框架介入 Web 应用中,需要在web.xml中配置该框架的核心filter。下面是Struts2 在web.xml文件中的配置片段:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name> 
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

   <!-- 定义Struts2的核心Filter -->
  <filter>
    <!-- 可任意命名,但必须与 filter-mapping 中的 filter-name 一致-->
    <filter-name>Struts2</filter-name> 
    <!--struts2-core-2.1.6.jar中 包org.apache.struts2.dispatcher.ng.filter下的一个类-->
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
  </filter>

  <!-- 使Struts2的 Filter 拦截所有请求 -->
  <filter-mapping>
    <filter-name>Struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

  (3) 定义处理用户请求的 Action 类,以便调用 Model 中的方法来处理请求。实际上,StrutsPrepareAndExecuteFilter 和 Action 共同构成了 Struts2 的控制器(Controller)。其中, StrutsPrepareAndExecuteFilter 为核心控制器,负责拦截、处理所有用户请求;Action 为业务控制器,负责调用 Model处理实际业务并返回处理结果。 Action 的实现手段通常有以下三种:

   ① 一个包含无参的execute()方法(返回类型为 String)的普通Java类;
   ② 实现 com.opensymphony.xwork2.Action 接口并重写execute()方法的Java类;
   ③ 继承 com.opensymphony.xwork2.ActionSupport 类并重写execute()方法的Java类。★★★ 推荐使用方式 ★★★
  
  在该登录Demo中,Action 的实现采用的是第三种方式,代码如下所示。关于 Action 更详细、全面的介绍见我的下一篇博文,此不赘述。

public class LoginAction extends ActionSupport{

    private static final long serialVersionUID = 1L;

    // 使用  Action 来封装 HTTP 请求参数
    private String username;
    private String password;


    // getter and setter
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }


    public void setPassword(String password) {
        this.password = password;
    }


    // 处理用户请求的逻辑
    @Override
    public String execute() throws Exception {
        if(username.equals("rico") && password.equals("root")){
            System.out.println("登录成功...");
            return SUCCESS;
        }else if(username.equals("") || password.equals("")){
            System.out.println("用户名或密码未填写...");
            return INPUT;
        }else {
            System.out.println("登录失败...");
            return ERROR;
        }
    }
}

  (4) 配置 Action,并编辑 struts.xml。配置 Action 实际上就是 使具体请求与具体的Action相关联,从而使得核心控制器(StrutsPrepareAndExecuteFilter) 可以根据该配置来创建合适的 Action实例,并调用对应的业务控制方法处理用户请求。在配置Action过程中,首先复制目录 struts-2.1.6\apps\struts2-blank-2.1.6\WEB-INF\src\java 下的 struts.xml 到 Web应用的src目录,然后编辑 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>
    <!--开发模式下,修改 struts.xml 后不需重启Tomcat便可立即生效  -->
    <constant name="struts.devMode" value="true" />
    <package name="default" namespace="/" extends="struts-default">
        <action name="login" class="com.tju.rico.action.LoginAction">
            <!-- ................................................. -->
            <!-- 配置 Action 处理结果与物理视图资源之间的对应关系... -->
            <!-- ................................................. -->
        </action>
    </package>
</struts>

  (5) 配置 Action 处理结果 物理视图资源 之间的对应关系。当 Action 处理用户请求后,通常会返回一个处理结果,即 逻辑视图名(Action 接口中的五个静态字段:success,error,input,login 和 none) ,而这个逻辑视图名必须与具体的物理视图资源关联才有价值。最终在 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>
    <!--开发模式下,修改 struts.xml 后不需重启Tomcat便可立即生效  -->
    <constant name="struts.devMode" value="true" />
    <package name="default" namespace="/" extends="struts-default">
        <action name="login" class="com.tju.rico.action.LoginAction">
            <result name="success">/welcome.jsp</result>
            <result name="error">/error.jsp</result>
            <result name="input">/login.jsp</result>
        </action>
    </package>
</struts>

  (6) 到此为止,第一个Struts2应用 — 登录Demo 便完成,其组织结构与运行结果如下图所示:

            Demo组织结构与运行结果.png-326.2kB


二. Struts2 应用的运行逻辑

1、Struts2 应用的运行逻辑

  上面所述的 Struts2 应用的构建流程是以“请求-响应”为主线的,下面给出 Struts2 应用的一次 “请求-响应” 的完整流程,如下图所示:

            

  可以从上面图示看出,Struts2 的核心在于 将用户请求与响应视图相分离。也就是说,用户的所有请求都只向控制器发送,由控制器调用模型组件、视图组件向用户展现响应。特别需要注意以下几点:

  • 在 Struts2 应用中,StrutsPrepareAndExecuteFilter 和 Action 一起充当 Controller,并由其调用 Model、View 响应用户请求;

  • 在 Struts2 应用中,StrutsPrepareAndExecuteFilter 通过反射生成 Action 实例并通过该实例调用相应的方法(一般是 execute() 方法)处理用户请求;

  • 业务控制器Action 并不与物理视图相关联,也就是说,业务处理结果(数据)与显示逻辑相分离。特别地,业务处理结果与怎样的视图关联依然由 StrutsPrepareAndExecuteFilter 决定(通过在 struts.xml 中配置)。


2、Struts2 应用的运行逻辑实例

  我们反过头结合 登录Demo来看 Struts2 的运行逻辑,如下图所示:

(1) 用户在客户端(浏览器)键入请求地址,例如:http://servername/WebAppname/login
(2) 客户端将上述请求进一步封装成HTTP请求,并发送给服务器(Tomcat);
(3) 服务器找到对应已部署的Web应用,并参考其 web.xml;
(4) 请求被 Struts2 Filter 过滤,参考 struts.xml 进行对请求响应;
(5) 匹配 Namespace 与 请求URL,从而确定对应的 Package,并在该Package内进一步匹配 Action;
(6) 成功匹配 Action 后,通过Action实例调用其 execute() 方法处理用户请求,并返回逻辑视图名;
(7) 根据逻辑视图名匹配物理视图资源,并forward到该视图;
(7) 服务器生成响应并将对应视图通过客户端(浏览器)展现给用户。

            Struts2运行逻辑实例.png-23.2kB


三. NameSpace: 命名空间与请求路由规则

  Struts2 之所以提供命名空间的功能,主要是为了处理在同一个WebApp中包含同名的 Action 的情形。其以命名空间的方式来管理 Action,使得同一个命名空间里不能有同名的 Action, 而不同的命名空间里可以有同名的 Action。但是 Struts2 不支持为单独的 Action 设置命名空间,而是通过为Package指定namespace属性来为Package下面的所有Action指定共同的命名空间,从而解决Action命名冲突问题。实际上,我们在 Struts2 中所提到的 Package 与 Java 中的 package 作用类似。我们可以将每个Action划分到一个Package中,例如,每个命名空间下都可以有一个名为 ”help” 的 Action,并且有着各自不同的实现。此外,如果在Package中没有指定namespace属性,则该包下的所有Action处于默认的命名空间下,即等价于namespace的属性值为空字符串(“”)的情形。Struts2还支持根命名空间(“/”)。有几点需要注意:

  • Namespace为空就意味着只要在该默认命名空间下找到可以匹配的 Action,该请求就一定会被响应(具体响应结果取决于匹配精度,精度越高,越优先被用来响应请求), 而不管是否能够找到与请求URL相匹配(无论精确匹配还是模糊匹配)的 Package;
  • 除Namespace的属性值为空(“”)的情形外, Namespace 必须以 “/” 开头
  • Namespace 与 Package 一般以 模块名 命名。

1) 请求路由规则

  在匹配一个Action时,遵循如下规则 (以”http://server/WebAppName/path1/path2/path3/test“为例 ):

  • ① 寻找Namespace为”/path1/path2/path3”的Package。如果存在这个Package,则在这个Package中 寻找名字为test的Action,若找到,则执行;否则 (不存在该Package 或者 这个 Package 中不存在该Action),转步骤2;

  • ② 寻找Namespace为”/path1/path2”的Package。如果存在这个Package,则在这个Package中 寻找名字为test的Action,若找到,则执行;否则 (不存在该Package 或者 这个 Package 中不存在该Action),转步骤3;

  • ③ 寻找Namespace为”/path1”的Package。如果存在这个Package,则在这个Package中 寻找名字为test的Action,若找到,则执行;否则 (不存在该Package 或者 这个 Package 中不存在该Action),就去缺省 Namespace 或者 Namespace为空字符串的Package下面去找名为test的Action,如果还是找不到,则页面提示找不到 Action。
      
    特别地,
      (1). 若存在根命名空间,当一个request直接请求 ContextPath (即:”http://server/WebAppName/“) 下面的资源时,Struts2会首先到根命名空间下去寻找匹配的Action,若找到则执行,否则,报错;

      (2). 若不存在根命名空间,假如直接请求 “http://server/WebAppName/“, 则Struts2会直接从web.xml找到相应的welcome-file并返回。


2) 请求路由规则小结

  总的来说,请求路由规则为 精度越高越优先 (精度相同时,看先后顺序),可总结为如下两条:

  • FilterDispatcher在请求路由时,将请求URL按上述规则与Namespace进行逐个匹配。一旦匹配成功,要么正常响应(找到特定Action),要么报404(未找到特定Action)。至此,本次请求路由结束;

  • 当一个request直接请求ContextPath (“http://server/WebAppName/“) 下面的资源时,若存在根命名空间,则参照第一条;若不存在根命名空间,则Struts2会直接从web.xml找到相应的welcome-file并返回。至此,本次请求路由结束;


四. 小结

  作为 Struts2 入门文章,本文首先以HelloWorld为例介绍了创建一个简单的 Struts2 应用的一般步骤和流程,紧接着以该 HelloWorld Web应用为出发点简述了 Struts2 的运行机制,揭示了 Struts2 的核心:将请求与视图相分离。最后,针对该Web应用所涉及到的知识点Namespace进行了深入探究,并总结出Struts2的请求路由规则。

  更复杂、全面的 Struts2 应用实例和关于Action的详细解读见我的下一篇博客。


引用

《轻量级 Java EE 企业应用实战(第四版)》
struts 2读书笔记—–struts2的开发流程
Struts2学习(一):创建一个Struts2应用

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值