Struts2框架的基本使用(二)

     上一篇 Struts2框架的基本使用 我们限于篇幅,最后简单介绍了Action的配置问题,本篇接着介绍有关框架的一些其他基本用法,主要内容如下:

  • Action的基本配置
  • result的基本配置
  • Struts的异常处理机制
  • Convention插件于“约定”的支持

一、Action的基本配置      上篇文章我们简单的看了Struts.xml中的package包元素的一些属性的使用情况,接下来我们看看Action的元素的一些属性及其使用情况。依然是上篇的Struts.xml文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <package name="walker" extends="struts-default">
        <action name="login" class="MyPackage.LoginAction">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
    </package>
</struts>

我们这里的action元素就对应于一个xxxAction,它的name属性指定了他所处理的URL,也就是我们请求/login的时候核心拦截器会匹配到此Action。class属性指定了该Action对应的物理路径。此外action元素还可以有method属性,该属性的默认值是execute,也就是当核心拦截器匹配到一个xxxAction的时候,会默认调用它的execute方法,当然我们也是可以使用method属性来显式指定某个方法作为默认方法调用。

<struts>
    <package name="walker" extends="struts-default">
        <action name="login" class="MyPackage.LoginAction" method="myMehod">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
    </package>
</struts>
public class LoginAction extends ActionSupport {
    private String username;
    private String password;
    public String getUsername(){
        return this.username;
    }
    public void setUsername(String s){
        this.username = s;
    }
    public String getPassword(){
        return this.password;
    }
    public void setPassword(String s){
        this.password = s;
    }
    public String execute() throws Exception{
        if(getUsername().equals("walker")&&getPassword().equals("yam")){
            ActionContext ac = ActionContext.getContext();
            ac.put("login","hello 123");
            return SUCCESS;
        }
        return ERROR;
    }

    public String myMehod(){
        ActionContext ac = ActionContext.getContext();
        ac.put("login","hello walker");
        return SUCCESS;
    }
}

我们在Struts.xml中指定了默认调用的方法是myMethod,从结果图中我们可以看出来,框架执行了我们的myMethod方法而不是默认的execute方法。

     在配置action元素的时候,Struts框架允许我们在name属性字段使用通配符。即使用 * 代表一个或多个字符,然后我们可以在class属性或者子元素中使用{n}来获取 * 所代表的内容。例如:

<struts>
    <package name="walker" extends="struts-default">
        <action name="*" class="MyPackage.LoginAction" method="{1}">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
    </package>
</struts>

当我们请求login这个URL时候,核心拦截器获取到这个URL,然后在struts.xml中查找,哪个Action能匹配这个URL呢?当它看到一个action的name值为 * 的时候,就决定用此action来响应此次请求,此时 * 的值为login,{1}表示name中的第一个 * 的值,此处自然也是login,于是显式调用LoginAction中的login方法。这就是统配符的简单使用情况,其实子元素result中也是可以通过{n}来获取 * 的值的,具体的等到介绍result的时候在详解。

下面说一下,有关使用通配符而产生的匹配顺序问题。

<struts>
    <package name="walker" extends="struts-default">
        <action name="loginABC" class="MyPackage.LoginAction" method="login">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
        <action name="*ABC" class="MyPackage.LoginAction" method="{1}">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
        <action name="*" class="MyPackage.LoginAction" method="{1}">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
    </package>
</struts>

试想一下,如果我们请求 loginABC,框架会调用哪个action来响应呢?这三者都能匹配当前请求的URL。在Struts框架中loginABC原URL优先级最高,后面两种优先级相同,具体选择按照先后顺序。在此例中优先级为:

loginABC > *ABC > *

最后一个有关Action配置的是,为Action配置默认值,也就是在URL无法匹配到具体的某个Action的时候,默认的Action会去响应此URL。

<struts>
    <package name="walker" extends="struts-default">
        //为默认Action指定name
        <default-action-ref name="err" />
        //为默认Action指定class和处理结果
        <action name="err" class="MyPackage.DefaultAction">
            <result name="error">/error.jsp</result>
        </action>

        <action name="login" class="MyPackage.LoginAction" method="login">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
    </package>
</struts>
public class DefaultAction extends ActionSupport {

    public String execute() throws Exception{
        return ERROR;
    }
}

这样一旦用户输入了不合法的URL,我们一律跳转到错误页面。这一点在安全性方面还是很重要的。

二、配置处理结果      之前我们一直都在介绍有关Action的一些配置操作,但是始终没有说明Action返回的一个字符串是如何对应于物理视图资源的。其实从Action返回的字符串要想能够被核心拦截器识别是对应于哪个物理视图,是需要在Struts.xml中进行配置的。本小节就来学习下对处理结果的配置。

/*这是之前的Struts.xml配置文件*/
<struts>
    <package name="walker" extends="struts-default">
        <action name="login" class="MyPackage.LoginAction" method="login">
            <result name="error">/error.jsp</result>
            <result name="success">/index.jsp</result>
        </action>
    </package>
</struts>

我么可以看出来,配置逻辑视图和物理视图之间的映射是使用 result 元素来实现的。配置result元素时候通常是需要指定两个属性:

  • name:对应于Action返回的字符串的值
  • type:指定结果类型,默认值是dispatcher,可以省略

对于上面的两个属性,name属性中指定了一个字符串,如果该Action返回的是对应的字符串,那么核心拦截器就会知道该视图的物理位置。至于type属性,我们打开sturts-default.xml文件:

<result-types>
      <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
      //默认类型
       <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
            
       <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
            
      <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
            
       <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>

       <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
            
       <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
            
       <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" />
</result-types>

以上是Struts框架为我们提供的默认的type类型,至于这些type具有什么作用,马上介绍。此处我们还应该知道,如果想要自定义一个结果类型的话,首先需要手写一个继承自com.opensymphony.xwork2.Result,然后在struts.xml文件中使用上述的元素配置定义。最后我们就可以在result元素中使用了。

     首先我们我们看第一个type类型:plainText,它没什么实际的意义,主要用于显示视图的源代码。例如:

<struts>
    <package name="walker" extends="struts-default">
        <action name="login" class="MyPackage.LoginAction" method="login">
            <result name="error">/error.jsp</result>
            //此处指定了type类型为plainText
            <result name="success" type="plainText">/index.jsp</result>
        </action>
    </package>
</struts>

可以看到,返回的是index的源代码。从此例我们可以看出,type的作用类似于告诉核心拦截器,对于刚刚拿到的物理视图,该以怎样的形式响应用户,默认的是dispather,就是转发的意思,也就是forward请求该页面,而对于我们刚刚指定的typeplainText,就是响应用户以源代码。虽然例子没什么实际价值,但是我们从中推测出type究竟在对应物理视图的过程中扮演了怎样的角色。

     第二个type类型是:redirect。它和dispather很是类似,只不过dispather是同一次请求的转发操作,而redirect则是重新的一次request,会丢失上次请求中的所有参数值。由于和dispather很是类似,此处不再赘述。

第三个type类型是:redirectAction。它和redirect又很相似,只不过redirect一般用于请求具体的资源,而redirectAction主要用于请求Action,形成Action处理链。

<struts>
    <package name="walker" extends="struts-default">
        <default-action-ref name="err"/>
        <action name="err" class="MyPackage.DefaultAction">
            <result name="error">/error.jsp</result>
        </action>

        <action name="login" class="MyPackage.LoginAction" method="login">
            <result name="error">/error.jsp</result>
            <result name="success" type="redirectAction">err</result>
        </action>
    </package>
</struts>

如上述代码所示,我们loginAction处理完成之后,通过result元素的type属性指定了下一个action为err。对于同package下的Action可以使用相对路劲,如果非相同的package,则需要使用Parma元素添加命名空间。

<struts>
    <package name="walker" extends="struts-default" namespace="/aaa">
        <default-action-ref name="err"/>
        <action name="err" class="MyPackage.DefaultAction">
            <result name="error">/error.jsp</result>
        </action>
    </package>

    <package name="walker2" extends="struts-default">
        <action name="login" class="MyPackage.LoginAction" method="login">
            <result name="error">/error.jsp</result>
            <result name="success" type="redirectAction">
                <param name="actionName">err</param>
                <param name="namespace">/aaa</param>
            </result>
        </action>
    </package>

</struts>

代码比较简单,这里就不在赘述了。

最后介绍一点有关result配置的内容,我们可以使用全局结果来使得某些结果可以被所有的Action使用。我们看个例子:

<struts>
    <package name="walker2" extends="struts-default">
        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>

        <action name="login" class="MyPackage.LoginAction">
            <result name="success" type="redirectAction">
                <param name="actionName">err</param>
                <param name="namespace">/aaa</param>
            </result>
        </action>
    </package>

</struts>

我们在login这个Action中并没有配置error对应的result元素,但是使用global-results元素配置了一个全局的结果,也就是如果某个Action返回error,但是在自己的result子元素中没有找到该结果对应的物理视图,就会跑到全局下搜索,如果找到立即使用。此例中我们故意输错密码,看到的结果如下:

虽然我们没有配置error结果对应的物理视图,但是通过查找全局的结果,框架还是找到error.jsp并forward结果返回。需要注意的是,局部结果的优先级是高于全局的,也就是如果某个Action返回的结果可以在自己的result元素中找到,就不会搜索全局下的结果。因为是全局的,使用的时候还是慎重。

篇幅限制,未完待续。。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

C/C++ volatile

volatile是“易变的”、“不稳定”的意思。volatile是C的一个较为少用的关键字,它用来解决变量在“共享”环境下容易出现读取错误的问题。

933
来自专栏技术小讲堂

使用Unity创建依赖注入依赖注入生命周期:注册、解析、销毁   注册解析销毁

这篇文章翻译自《Dependency Injection With Unity》第三章。文中提到的类似“前几节”的内容您不必在意,相信您可以看懂的。 P.S:如...

3496
来自专栏大内老A

[WCF权限控制]WCF自定义授权体系详解[原理篇]

到目前为止,我么介绍的授权策略都是围绕着安全主体进行的,基本上都是基于角色的授权。虽然角色是定义权限最为常用的形式,但是它解决不了授权的所有问题。基于角色的授权...

1879
来自专栏java 成神之路

NIO 之 Buffer 图解

3888
来自专栏大内老A

通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[中]:管道如何处理请求

从上面的内容我们知道ASP.NET Core请求处理管道由一个服务器和一组中间件构成,所以从总体设计来讲是非常简单的。但是就具体的实现来说,由于其中涉及很多对象...

2739
来自专栏java一日一条

Java异常有多慢?

实际上,真正要讨论的问题并不是,“相对‘那些不会发生错误的代码’来说,‘那些以异常形式上报的错误’会有多慢?”,因为你可能也认同“已接受的回答”。相反,真正的问...

612
来自专栏别先生

Spring之配置文件bean作用域的详细介绍

Spring的配置文件applicationContext.xml中bean作用域的详细介绍: 1:对象的创建:单例和多例         scope="sin...

1787
来自专栏Java帮帮-微信公众号-技术文章全总结

hibernate延迟加载详解

hibernate延迟加载详解 Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载。hiber...

2973
来自专栏与神兽党一起成长

使用FTP连接池封装工具类

早前的思路是将FTP连接的管理(对象池功能)与FTP工具类(上传下载方法)在一个工程中实现,在工具类中调用是模板类提供的模板方法, 由模板方法与对象池打交道——...

922
来自专栏coder修行路

python中重要的模块--asyncio

一直对asyncio这个库比较感兴趣,毕竟这是官网也非常推荐的一个实现高并发的一个模块,python也是在python 3.4中引入了协程的概念。也通过这次整理...

4007

扫码关注云+社区