struts2.1.6教程二、struts.xml配置及例程

 

1.配置文件的优先级

在struts2中一些配置(比如常量)可以同时在struts-default.xml(只读性),strtus-plguin.xml(只读性),struts.xml,struts.properties和web.xml文件中配置,它们的优先级逐步升高,即是说后面的配置会覆盖掉前面相同的配置。

 

2.配置形式

下面以对struts.i18n.encoding=UTF-8的配置为例进行说明:

在struts.xml配置形式如下:

 

   <constant name="struts.i18n.encoding" value="gbk"></constant>

在struts.properties的配置形式如下:

struts.i18n.encoding=UTF-8

在web.xml中配置如下:

<filter>

<filter-name>struts2</filter-name>
<filter-class>    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    </filter-class>
    <init-param>
       <param-name>struts.i18n.encoding</param-name>
       <param-value>UTF-8</param-value>
    </init-param>
</filter>

说明:官方声称配置了此常量可以解决中文乱码问题,但实事上并不能达到目的,在前面的三个项目中,如果我们在表单中输入中文,其结果是会出现乱码。解决此问题参看[一.7的注意]。这是struts2.1.6中的一bug,它的下一版2.1.8已解决此问题。

 

3.package配置相关

属性名

是否必须

说明

Name

Package的唯一标识,不允许同名

Extends

指定要继承的包

Namespace

指定名称空间

Abstract

声明包为抽象否

 

 

说明:在上面的配置文件中所用到的Test1Action和Test2Action这两个Action都只是继承了com.opensymphony.xwork2.ActionSupport类,而ActionSupport默认返回的就是“success”,所以当点击上面的链接分别转到了forward目录下的test1.jsp和test2.jsp。下面重点来看这个package元素的namespace属性及action的name属性,它们共同定义了action所映射到的实质文件。上图展示了链接地址和action的对应关系,所以当我们要想访问一个action所关联到的jsp文件时,应该用namespace+action的name 关于它的内容测试可以参考struts2package项目。

 

补充:通常情况下,action元素的name是属性值是不能出现“/”的,所以希望通过action中name属性来实现多级映射,需要在sturts.xml中增加如下属性:  

<constant name="struts.enable.SlashesInActionNames" value="true"/> 

这样配置后就可以再action的name元素中使用“/”了。比如:

<package name="tt3" extends="struts-default">
        <action name="test3/test3" class="com.asm.Test3Action">
            <result name="success">/forward/test3.jsp</result>
        </action>
</package>

然后输入<a href="<%=path%>/test3/test3.action">test3</a><br>链接地址就可以访问了

 

强调namespace默认值“”,即不配置namespace属性。它的意思是:如果action不能进行完整路径匹配,则会来此namespace下进行匹配,比如:.../test/test/test.action,如果参照namespace及action的name不能找到也之完全对应的action,它会再到依次追溯到上级目录中查找,即是说它会以…/test/test.action这样的路径来对应namespace和action的name进行查找。如果返回到最终的目录仍找不到,它就会到namespace="/"对应的包下查找名为test的action,如果仍找不到,它就会去默认的namespace下查找名为test的action,如果找到则执行此action。另外,namespace也可以配置成namespace="/"。它代表配置为项目的根。 总结action的名称探索顺序:完全对应、逐步追溯到上级目录查找、"/"下查找、默认namespace下查找。

 

为什么要提出namespace,主要是避免多人共同开发项目出现名字冲突。如果不使用namespace,多个人所写的action中可能出现重名的现象,这样当项目合并时就会出现冲突。而有了namespace可以在项目开发时由项目经理给每一个人分不同的namespace,这样每个开发人员只需要保证自己所写的action不同名即可。

 

namespace引发的链接问题:当我们为action配置了namespace时,访问此action的形式总会是如下形式:.../webappname/xxx/yyy/ActionName.action 而当此action成功执行跳转到某个jsp页面时,如想在此jsp页面写链接,一定要写绝对路径,因为相对路径是相对.../webappname/xxx/yyy/,而如果以后我们修改了action的namespace时,相对路径又要变,所以链接不能写成相对路径。 以下介绍

1.绝对路径的写法:通常用myeclipse开发时建立一个jsp文件,默认总会有如下内容:

<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>


我们写绝对路径可以参此内容。还可以参<head>下的<base href="<%=basePath%>"> 来完成绝对路径的书写。

 

4.分工合作include:指定多个配置文件

比如让jack来单独开发一个action,在jack.xml中的配置文件为:

<struts>
    <package name="jack" namespace="/jack" extends="struts-default">
        <action name="test4" class="com.asm.Test4Action">
            <result name="success">/forward/test4.jsp</result>
        </action>
    </package>    
</struts>

然后在struts.xml文件中增加如下内容:<include file="jack.xml"></include> 它实质就是把jack.xml中的<package>及其内容写进struts.xml中的<struts>根元素下。

 

链接:<a href="<%=path %>/jack/test4.action">test4</a> 这样便可以访问到了forward目录下的test4.jsp了。

 

 

5.tomcat认证访问

接上例:namespce的作用除了在前面提到的避免协同开发名字冲突外,还为认证提供一个条件。比如jack开发的东西所关联到的页面需要权限才能被访问。由于多为tomcat中的内容,下面只列出步骤。
步骤一,tomcat的conf目录下tomcat-users.xml内容如下:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="manager"/>
  <role rolename="admin"/>
  <user username="jack" password="jack" roles="admin,manager"/>
  <user username="tom" password="tom" roles="manager"/>
</tomcat-users>
步骤二,在web.xml中增加如下内容:
<security-constraint>
        <web-resource-collection>
            <web-resource-name>jack</web-resource-name>
            <url-pattern>/jack/*</url-pattern>
            <http-method>POST</http-method>
            <http-method>GET</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>
    <security-role>
        <role-name>admin</role-name>
    </security-role>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>input authentication message</realm-name>
    </login-config>

这样配置完成后,当我们访问.../jack中的任何内容都会要求输入密码认证信息,认证时输入tomcat-users.xml配置的admin权限的用户名和密码即可访问(这里就只有jack用户名可以访问)

 

6.初识拦截器

拦截器能在action被调用之前和被调用之后执行一些“代码”。Struts2框架的大部分核心功能都是通过拦截器来实现的,如防止重复提交、类型转换、对象封装、校验、文件上传、页面预装载等等,都是在拦截器的帮助下实现的。每一个拦截器都是独立装载的(pluggable),我们可以根据实际的需要为每一个action配置它所需要的拦截器。

myStruts2项目下,重新对配置文件作如下修改:

<package name="myFirst" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor" />
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"
/>
</interceptors> <action name="login" class="com.asm.LoginAction">
<interceptor-ref name="timer"></interceptor-ref> <interceptor-ref name="params"></interceptor-ref>
<result name="loginSuccess">/success.jsp</result> <result name="loginFailure">/failure.jsp</result> </action> </package>

首先在package中定义了两个拦截器,然后在login action中引用了这两个拦截器,需要说明的是这里使用的拦截器都是系统自带的拦截器。其实在extends所继承的struts-default中就包含了很多拦截器,也包括我们这里所用的拦截器,但如果在此action中不使用params拦截器,将会报空指针错,因为params拦截器的作用是传递表单参数,如果不使用此拦截器就不能在action中得到表单参数,所以引用时会报空指针错。虽然extends继承的strust-default自带有params拦截器,但是当我们自己引用了拦截器时,继承struts-default将不会再为我们分配默认的拦截器(有点类似构造器),但是我们仍然可以通过<interceptor-ref name="defaultStack"/>来继续使用struts-defalut的拦截器。补充:由于上面的package继承于struts-default,而我们这里所用到的timer和params都是在struts-defalut中定义过,所以即使我们在<interceptors>中没有定义过这两个拦截器,也可以直接在action中引用。

 

使用<interceptor-stack>组合多个拦截器:比如我们想把上面的params和timer这两个拦截器组合:

    <interceptor-stack name="timer_param">
                <interceptor-ref name="timer" />
                <interceptor-ref name="params" />
    </interceptor-stack>

然后再在action引用<interceptor-ref name="timer_param"/>”,效果和分别引用两个是一样的。其实我们使用strtus-default中的<interceptor-ref name="defaultStack"/>也是使用interceptor-stack方式。

 

7.Action中的method属性

在struts1.x中我们知道通过继承DispatchAction可以实现把多个Action进行统一操作,在struts2中实现action的统一操作也很简单。我们以crud操作为例,把crud集中到一个Action中。
步骤一、建立CRUDAction,内容如下:

package com.asm;
import com.opensymphony.xwork2.ActionSupport;
public class CRUDAction extends ActionSupport {
    public String add() {
        return "success";
    }
    public String del() {
        return "success";
    }
    public String update() {
        return "success";
    }
    public String query() {
        return "success";
    }
}

步骤二、配置此Action,为了清晰明了,专为此Action,建立一个配置文件crud.xml,主要内容如下:

<struts>
    <package name="crud" extends="struts-default" namespace="/crud">
        <action name="add" class="com.asm.CRUDAction" method="add">
            <result name="success">/crud/addSuccess.jsp</result>
        </action>
        <action name="del" class="com.asm.CRUDAction" method="del">
            <result name="success">/crud/delSuccess.jsp</result>
        </action>
        <action name="update" class="com.asm.CRUDAction" method="update">
            <result name="success">/crud/updateSuccess.jsp</result>
        </action>
        <action name="query" class="com.asm.CRUDAction" method="query">
            <result name="success">/crud/querySuccess.jsp</result>
        </action>
    </package>
</struts>

分析:上面的method方法的值来源于CRUDAction中方法的名字,这样当我们访问上面的每一个Action时,它实质是和method指定的方法关联上。

步骤三、把crud.xml配置文件并入struts.xml中,只需增加如下代码:

<include file="crud.xml"></include>

步骤四、编写相应的jsp页面,在此略去crud文件夹下的四个跳转jsp页面(addSuccess.jsp等),重点是crud.jsp页面。内容如下:

<html>
<%
    String path=request.getContextPath();
%>
    <body>
        <a href="<%=path %>/crud/add.action">添加数据</a><br>
        <a href="<%=path %>/crud/del.action">删除数据</a><br>
        <a href="<%=path %>/crud/query.action">查询数据</a><br>
        <a href="<%=path %>/crud/update.action">修改数据</a><br>
    </body>
</html>

 

补充扩展,动态调用DMI不使用method实现统一.我们在crud.xml中增加如下内容:

<action name="op" class="com.asm.CRUDAction">
            <result name="success">/crud/op.jsp</result>
</action>

然后再在crud.jsp中定义如下链接:

<a href="<%=path %>/crud/op!add.action">添加数据</a><br>
<a href="<%=path %>/crud/op!del.action">删除数据</a><br>
<a href="<%=path %>/crud/op!query.action">查询数据</a><br>
<a href="<%=path %>/crud/op!update.action">修改数据</a><br>

注意查看上面的链接地址,它们都是针对op action,然后再加地上“!+CRUDAction中相应的方法名”,最后再写上.action即可以访问到统一页面op.jsp。这样做虽然能减少页面,但是由于它们实质用到的是同一个Action,所以这就意味着我们要使用的拦截器相同,相同的跳转result。实际中这种方式很少使用,在此略作了解。如果不想使用动态方法调用,我们可以通过常量来关闭,即在struts.xml中增加如下配置:

<constant name="struts.enable.DynamicMethodInvocation" value="false"/>

 

扩展2:在CRUDAction中使用do。举例:我们在CRUDAction中增加一个新的方法,内容如下:

    public String doMain(){
       return "success";
    }

然后再在在crud.xml中增加如下内容:

<action name="main" class="com.asm.CRUDAction" method="main">
           <result name="success">/crud/main.jsp</result>
</action>

注意:配置中method属性值是doMain中去掉do后M小写。然后再在crud.jsp中增加如下链接:

<a href="<%=path %>/crud/main.action">main页面</a><br>

随后便可以访问到.../crud/main.jsp页面了。

 

8.使用ForwardAction实现页面屏蔽。

我们在jsp页面之间写链接总会是.../xxx.jsp,而如果我们想屏蔽掉具体的jsp,只需要所jsp页面配置成一个ForwardAction即可实现。示例如下:在根目录下有一个index.jsp主页,我们strtus.xml中作如下配置:

<package name="def" extends="struts-default">        
        <action name="forward">
            <result >/index.jsp</result>
        </action>
</package>

说明:如果没有未action指定class,默认就是ActionSupport类,如果没有为action指定method属性,则默认执行execute方法,如果没有指定result的name属性,默认值为success。知道了这些再结合ActionSupport的源码就不难理解实现转发的原理了。

 

随后再在前面第7点扩展中用到的op.jsp中增加如下代码:

<a href="<%=request.getContextPath()%>/forward.action">forward</a>

最后再测试访问op.jsp,在op.jsp中页面中直接点链接便可以跳到index.jsp,观察地址栏发现此时跳到index页面是进行的服务器跳转,如果我们在上面的配置中的result增加type属性变成

<result type="redirect">/index.jsp</result>

,实现的跳转就是客户端跳转。

补充:像这种forward形式的action实质是执行的ActionSupport 这个Action。因此配置它的result可以参看此类的api文档,比如它常用的result name有:success、login、input等。

 

9.使用default-Action配置统一访问

default-action-ref,当访问没有找到对应的action时,默认就会调用default-action-ref指定的action.同样在上面的package中增加如下内容

<default-action-ref name="error"></default-action-ref>
        <action name="error">
            <result>/other/error.jsp</result>
        </action>

上面一段内容就是说当我们访问的action不能被找到时便指向名为error的action中去,接着我们在下面配置了这个error Action。但是要注意,一个package内只配置一个<default-action-ref>,如果配置多个,就无法预测结果了. 此时我们只要输入.../myStruts2/luanFangWen.action这样的形式,它就会去访问这个默认的<default-action-ref>,通常我们会为它配置一个错误页面,以提示用户访问的页面不存在。

 

在web开发中,我们还可以把这个默认的action访问配置成主页,这样当用户访问一些不存在的action时,总会跳到主页上去。

通过此配置,只要是访问一个不存在的action便会转向到.../other目录下的error.jsp页面。但是如果访问是其它的不存在资源则仍是报tomcat所标识的404错误,我们可以在web.xml中作如下配置:

<error-page>
        <error-code>404</error-code>
        <location>/other/404error.jsp</location>
</error-page>

这样配置后,访问错误页面将跳到.../other/404error.jsp页面中去。

补充说明:如果我们用ie访问时,如果选中了[工具][IE选项][高级][浏览][显示友好的http错误信息],则配置的错误页面将失效,因为找不到资源时会报HTTP404错误,而ie截取到此错误进行了它自身的友好处理,所以我们设置<error-page>就失效。

 

 

10.使用通配符

建立struts2wildcard项目,此实例基本仿照前面前面第7点的实例改写而成。为了使用通配符,只需要改写配置文件即可。此实例未使用通配时的配置文件如下:

<action name="addUser" class="com.asm.UserAction" method="addUser">
            <result name="success">/user/addUser.jsp</result>
</action>
<action name="delUser" class="com.asm.UserAction" method="delUser">
            <result name="success">/user/delUser.jsp</result>
</action>
<action name="queryUser" class="com.asm.UserAction" method="queryUser">
            <result name="success">/user/queryUser.jsp</result>
</action>
<action name="updateUser" class="com.asm.UserAction" method="updateUser">
            <result name="success">/user/updateUser.jsp</result>
</action>

我们注释掉上面的配置,使用通配符只需如下内容即可达到相同的效果:

<action name="*User" class="com.asm.UserAction" method="{1}User">
            <result name="success">/user/{1}User.jsp</result>
</action>

原理:当有.../addUser.action请求时,如果不能在当前应用中找到完全相同的addUser名字的Action时,通配符配置这时就起作用了,按通配原则,它便和上面的name="*User"相配成功,这里不难明了*此时代指的内容是add,再来看method恰恰是引用第一个*的内容,所以它的method此时的完整名为addUser,它刚好和com.asmUserAction中的addUser方法相对,所以它会去addUser方法,再来看下面的result配置所指代的页面,它也用到了{1},所以它的完整页面是/addUser.jsp。其实如果我们有良好的编程命名习惯,所有的Action我们都只需要进行一次配置。

 

举例:规定所有的Action类都用XXXAction来命名,类中所有的CRUD方法都用add/del/update/query。Jsp页面也用add/del/update/query_XXX.jsp这样的形式。即配置文件可以写成如下形式:

<action name="*_*" class="com.asm.{2}Action" method="{1}">
            <result name="success">.../{1}_{2}.jsp</result>
</action>

Name中第一个*代表CRUD操作的名字,第二个*代表类的名字。所以访问链接地址举例如下:

.../del_User.action将访问到User类的del方法,成功后跳到del_User.jsp页面。补充说明{0}是代表name中所有的*组合。

 

11.使用0配置:ZERO Annotation

 

12.Result配置详解

说明:在前面的许多案例中我们所用到的Action基本都继承自ActionSupport这个类,而在这个类中我们定义了五个字段:SUCCESS,NONE,ERROR,INPUT,LOGING。我们可以直接返回这些字段值,这些字段值实质是被定义成:String SUCCESS=”success”这样的形式,所以我们只要在Result元素中用它们的小写即可。
<result>标准完整形式如下:

<result name="success" type="dispatcher">
        <param name="location">/default.jsp</param>
</result>

如果我们都采用默认的形式,最终可以简写成:<result>/default.jsp</result>

探讨type类型

Type类型值

作用说明

对应类

chain

用来处理Action链

com.opensymphony.xwork2.ActionChainResult

dispatcher

用来转向页面,通常处理JSP

org.apache.struts2.dispatcher.ServletDispatcherResult

redirect

重定向到一个URL

org.apache.struts2.dispatcher.ServletRedirectResult

redirectAction

重定向到一个Action

org.apache.struts2.dispatcher.ServletActionRedirectResult

plainText

示源文件内容,如文件源码

org.apache.struts2.dispatcher.PlainTextResult

freemarker

处理FreeMarker模板

org.apache.struts2.views.freemarker.FreemarkerResult

httpheader

控制特殊http行为的结果类型

org.apache.struts2.dispatcher.HttpHeaderResult

stream

 

向浏览器发送InputSream对象,通常用来处理文件下载,还可用于返回AJAX数据。

 

org.apache.struts2.dispatcher.StreamResult

 

velocity

处理Velocity模板

org.apache.struts2.dispatcher.VelocityResult

xslt   

  处理XML/XLST模板

 org.apache.struts2.views.xslt.XSLTResult

 

以上对type类型作简要的说明,下面来看实例:当一个Action处理后要返回的Result是另一个Action时,作如何配置,关键就是配置type类型。下面建立struts2result项目说明
步骤一:建立两个Action:TestAction、Test2Action
步骤二:web.xml配置省略。struts.xml主要配置内容如下:

<struts>
    <package name="resultTest" extends="struts-default">
        <action name="test" class="com.asm.TestAction">
            <result name="success" type="chain">
                <param name="actionName">test2</param>
            </result>
        </action>

        <action name="test2" class="com.asm.Test2Action">
            <result name="success">/test2Suc.jsp</result>
        </action>    
    </package>
</struts>

说明:在名为“test”的action中,我们配置result元素的type类型值为chain,意为将继续把Action传递到下一个名为test2的Action中去,在test2.action中会把页面转向到test2Suc.jsp中去。

在type类型为chain时,它的param有4个值可配,除了这里用到的name=”actionName”外(必须配置,否则报错),还有name=namespace|method|skipActions。其中namespace指定要转向到action的名字空间,由于此处是转到Action位于同一个namespace下,而namesapace的默认值the current namespace,所以可以省略不写(需要说明的是如果要跳到别的名称空间的action中去,除了使用namespace指定外,还可以用:/要跳去action所在名称空间的值/要跳去的action的name值)。Method用于指定转向到一个目标action所调用的方法,默认是调用下一个action的execute方法,所以此处仍可以省略。SkipActions是一个可选的属性,一般不用。具体可以参看chain所对应类的api帮助

 

在本实例中,我们还在TestAction中设定一个username字段,并在execute方法执行为它赋了值,并在test2Suc.jsp中引用了此值。其实这种做法在web开发中还是很有用处,比如可以代替隐藏域需要注意的是之所以在action的传递中能把设定的这个值保存下去主要是因为转向都是服务器跳转。如果我们跳转时采取了客户端跳转,比如在test2 action的result中指定type类型为redirect,要想传递参数可以在result指向的jsp页面中附加参数即可,我们可以在test2 action的result中写成:

<result name="success" type="redirect">
/test2Suc.jsp?username=${username}
</result>  

 

随后在test2Suc.jsp页面中引用时会出现三个问题:

1.EL表达式引用失效,(EL表达式应该使用${param.username}形式)。我们也可以使用<%=request.getParameter("username")%>获取参数值。 

2.由于在前面的TestAction中设定的值为中文,而附加到这里的uri请求的参数后面时会出现乱码问题。(可以使用URI编码再解码解决此问题)

3.值栈取值失效:因为每一次request共享同一个值栈,所以服务器端的forward跳转也是能共享同一值栈得。但是着当test action执行后把请求交由test2 action时,test2 action采取的是redirect重定向到test2Suc.jsp页面,这时其实就是重发的一次request,所以在test action保存的值栈内容全部失效。这也就是为什么我们要附加参数的原因。而参数是保存在actionContext中,所以采用了#的方式来取出值。图示说明:

步骤三,编写链接页面index.jsp。发布测试:

 

全局result

如果我们所有的action均有可能跳到相同的页面,则不防使用全局result。为了方便引用我们专门建立一个package来存放公共的result。在会用到个全局的跳转时,只需要把继承自这个公共的package即可。

建立公共包,代码如下:

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

由于它下面没的action配置,所以我们可以像默认的struts-default包一样,声明abstract=true,这样声明表示此packgage下不会有action,它一般是用来让别的package继承。随后再在要用到全局result中引用这个公共的package。代码如下:

<package name="testGlobal" extends="pubResult" >
    <action name="error" class="com.asm.ErrorAction"></action>
    <action name="error2" class="com.asm.Error2Action"></action>
</package>

这样操作相当于把全局的result加到了此package下的所有action中去。

 

动态Result:了解

步骤一:建立DynaAction,主要代码如下:

package com.asm;
public class DynaAction extends ActionSupport {
    private String username;
    private String nextAction;

    public String execute() throws Exception {
        if (username.equals("admin")) {
            nextAction = "admin";
        } else if (username.equals("user")) {
            nextAction = "user";
        } else {
            nextAction = ERROR;
        }
        return SUCCESS;
    }
    ...省略get/set方法    
}

步骤二、建立jsp页面dyna.jsp,主要是为了向DynaAction中传递username参数。

步骤三、相关配置如下:

<package name="dynaTest" extends="pubResult">
        <action name="dyna" class="com.asm.DynaAction">
            <result name="success" type="chain">${nextAction}</result>
        </action>

        <action name="admin" >
            <result>/admin.jsp</result>
        </action>

        <action name="user">
            <result>/user.jsp</result>
        </action>
</package>

分析:当dyna.jsp把参数传递到DynaAction中去时,如果传递的值为admin,我们便设定了nextAction的值admin,在配置文件中我们通过${nextAction}(用在struts配置文件中的ognl,其实nextAction的值是存在值栈中,我们通过${}这样的形式取出。在此只作了解)来获取值便为admin,随后再继续把请求传递到下一个Action中去(此时也即admin.action),为了方便我们设定了两个ForwardAction:admin.action和user.action。这样便可以跳到指定的jsp页面。 原理:dyna.action执行后会继续把请求传递给下一个Action,而下一个Action的到底是哪一个Action,是通过DynaAction中动态指定的,比如这里是根据传递的username的值指定。

 

 

13.异常处理

步骤一、建立struts2exception项目下,在该项目下建立登录页面login.jsp。主要代码如下:

<form action="<%=request.getContextPath() %>/login.action">
        username:<input type="username" name="username"><br>
        <input type="submit" value="login">
</form>    

步骤二、建立LoginAction,代码如下:

package com.asm;
public class LoginAction extends ActionSupport {
    private String username;
    public String execute() throws Exception {
        if (username.equals("exception")) {
            throw new ClassNotFoundException("类未被找到");
        } else if (username.equals("global")) {
            throw new Exception("全局异常");
        } else {
            return SUCCESS;
        }
    }
    ...省力get/set方法
}

步骤三、struts.xml配置文件如下:

<struts>
    <package name="ex" extends="def">
        <action name="login" class="com.asm.LoginAction">
            <exception-mapping result="myException"
                exception="java.lang.ClassNotFoundException">
            </exception-mapping>
            <result name="myException">/exception.jsp</result>
            <result name="success">/main.jsp</result>
        </action>
    </package>

    <package name="def" extends="struts-default" abstract="true">
        <global-results>
            <result name="myGlobal">/globalException.jsp</result>
        </global-results>

        <global-exception-mappings>
            <exception-mapping result="myGlobal"
                exception="java.lang.Exception">
            </exception-mapping>
        </global-exception-mappings>
    </package>
</struts>

分析

1.异常处理机制较为简单,所以在此只略作说明。当登录时输入“exception”时,在LoginAction中会抛出会一个ClassNotFoundException异常,此异常我们采取的局部异常处理的方式,如果登录时输入“globla”,则会抛出Exception异常,此异常我们采取的是全局异常的处理方式,

2.在ex包中我们继承了全局异常所在的包。提示:<exception-mapping>中的result属性的值来源于<result>元素中的name属性的值。从实例可以看出,我们一般把这种全局性的异常放在一个抽象包中供其实包继承。

 

小结Action

在struts2中一个普通的java类只要有public String execute()这样的方法都可以配置成一个Action,另外我们可以实现Action接口来使java类成为一个Action,但通常的做法是继承ActionSupport类,这也是以后的项目中惯用的方法,也是推荐的首选方法。 与struts1.x不同的是:在struts2中每一个Action被请求访问时都会new出这个Action对象,所以Action本身不存在线程安全的问题。

 

项目代码:http://pan.baidu.com/s/1pJkfxnt

 

转载于:https://www.cnblogs.com/crazylqy/p/4425587.html

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值