Struts2框架使用及分析

原文鏈接:http://blog.csdn.net/qq_22329521/article/details/74547658

第一步導(dǎo)包瞧省,不多說了
第二步配置struts2文件
<?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:將Action配置封裝绒净,就是可以在Package中配置很多action
            name:給包起名字潘飘,起到標(biāo)識(shí)作用,隨便起娘荡,不能其包名重復(fù)
            namespace屬性:給action的訪問路徑定義一個(gè)命名空間
            extends屬性:繼承一個(gè)指定包(struts-default在struts2-core jar包下有struts-default.xml中有package struts-default)
            abstract屬性:包是否為抽象的橘沥;標(biāo)識(shí)性屬性。標(biāo)識(shí)該包不能獨(dú)立運(yùn)行苹丸。專門被繼承
    -->
    <package name="hello" namespace="/hello" extends="struts-default">
        <!-- action 元素:配置action類
                     name屬性:決定了返回Action訪問資源名
                     class屬性:action的完整類名
                     method屬性:指定調(diào)用action中的那個(gè)方法來處理請(qǐng)求-->
        <action name="HelloAction" class="com.fmt.struct.HelloAction" method="hello">
            <!--result 元素:結(jié)果配置
                     name:標(biāo)識(shí)結(jié)果處理的名稱:與action的返回值對(duì)應(yīng)
                     type屬性:指定調(diào)用那個(gè)result類來處理結(jié)果默認(rèn)使用轉(zhuǎn)發(fā)(在繼承的struts-default包中有result的配置已經(jīng)設(shè)置好了)(type提供重定向,轉(zhuǎn)發(fā)苇经,重定向action赘理,轉(zhuǎn)發(fā)action)
                     標(biāo)簽體:填寫頁面的相對(duì)路徑-->
            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
    </package>
</struts>

web.xml中配置struts2核心過濾器

<!-- struts2 核心過濾器-->
    <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>
public class HelloAction {

    public String hello(){
        System.out.println("hello");
        return "success";
    }
}

訪問http://localhost:8080/structs2/hello/HelloAction,就訪問成功了

默認(rèn)配置

如果 一些必要參數(shù)沒寫扇单,默認(rèn)加載的是struts-default下的配置com.opensymphony.xwork2.ActionSupport 這個(gè)類

<struts>
        <package name="default" namespace="/default" extends="struts-default" >
            <!-- 找不到包下的action,會(huì)使用Demo2Action作為默認(rèn)action處理請(qǐng)求 -->
            <default-action-ref name="Demo2Action"></default-action-ref>
            <!-- method屬性:execute  -->
            <!-- result的name屬性:success  -->
            <!-- result的type屬性:dispatcher 轉(zhuǎn)發(fā)  -->
            <!-- class屬性:com.opensymphony.xwork2.ActionSupport -->
            <action name="Demo2Action"   >
                <result  >/hello.jsp</result>
            </action>
        </package>
</struts>

struts常量配置

struts的基本常量是在struts2-corejar中的org.apache.struts2中的default.properties中有基本的常量

外部修改常量的三種方式

  1. 在之前struts.xml的<struts>標(biāo)簽下填寫
<!--i18:國際化商模,解決post提交亂碼-->
    <constant name="struts.i18n.encoding" value="UTF-8"></constant>
    <!--指定訪問action時(shí)的后綴名
    如果value改為do:http://....../HelloAction.do
    -->
    <constant name="struts.action.extension" value="action,,"></constant>
    <!--是否是開發(fā)模式(更多的好處可以在default.properties文件下看)
               1,可以熱加載配置(不需要重啟服務(wù))
               2.提供了更多的錯(cuò)誤信息,方便開發(fā)時(shí)的調(diào)試
    -->
    <constant name="struts.devMode" value="true"></constant>
  1. 在src目錄下創(chuàng)建strtus.properties蜘澜,然后填寫鍵值對(duì)如
struts.i18n.encoding=UTF-8
  1. 在web.xml中填寫
    <context-param>
        <param-name>struts.i18n.encoding</param-name>
        <param-value>UTF-8</param-value>
    </context-param>

加載的順序是依次加載的

如果要引入其他配置

在當(dāng)前struct標(biāo)簽下加入
<include file="com/fmt/struct/struts.xml"/>

動(dòng)態(tài)訪問一個(gè)類

public class Demo1Action {
    public String add(){
        System.out.println("add");
        return "success";
    }
    public String delete(){
        System.out.println("delete");
        return "success";
    }
    public String change(){
        System.out.println("change");
        return "success";
    }
    public String find(){
        System.out.println("find");
        return "success";
    }
}

根據(jù)url訪問的話配置

配置一
<package name="dynamic" namespace="/dynamic" extends="struts-default">

       
        <action name="Demo1Action_add" class="com.fmt.b_dynamic.Demo1Action"
                method="add">

            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
         <action name="Demo1Action_delete" class="com.fmt.b_dynamic.Demo1Action"
                method="delete">

            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
        ....
    </package>

//上訴的配置顯然比較累贅

配置二
    <!--配置動(dòng)態(tài)方法調(diào)用常量
        默認(rèn)是關(guān)閉的施流,需要重啟
    -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
    <package name="dynamic" namespace="/dynamic" extends="struts-default">
        <action name="Demo1Action" class="com.fmt.b_dynamic.Demo1Action"
                >

            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
    </package>
訪問的url 為http://......//Demo1Action!delete
 http://......//Demo1Action!add
 ...

//上面注意點(diǎn)是帶!感嘆號(hào)的 這種也是不怎么用的的,搜索引擎在搜索的時(shí)候可能因?yàn)槟氵@路徑的特點(diǎn)鄙信,不會(huì)收錄下啦

配置3:通配符
 <package name="dynamic" namespace="/dynamic" extends="struts-default">

        <!--動(dòng)態(tài)調(diào)用方式瞪醋,使用通配符的樣子-->
        <action name="Demo1Action_*" class="com.fmt.b_dynamic.Demo1Action"
                method="{1}">

            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
    </package>
為http://......//Demo1Action_delete  http://......//Demo1Action_add

ServetApi

獲取request 這些的方式
public class DemoAction extends ActionSupport {


    @Override
    public String execute() throws Exception {

        //session域
        Map<String, Object> session = ActionContext.getContext().getSession();
        session.put("name","session");
        //application
        Map<String, Object> application = ActionContext.getContext().getApplication();
        application.put("name","application");
        /**
         *  //request域(struct2并不推薦使用原生的request域中)
            Map<String, Object>  request = (Map<String, Object>) ActionContext.getContext().get("request");
         */
        //直接使用,推薦
        ActionContext.getContext().put("name","request域");

        return super.execute();
    }

    public String execute1() throws Exception {

        //原生的request(這些內(nèi)部實(shí)際還是從ActionContext中獲取)
        javax.servlet.http.HttpServletRequest request = ServletActionContext.getRequest();

        //原生的Response
        HttpServletResponse response = ServletActionContext.getResponse();

        //原生的ServletContext
        ServletContext servletContext = ServletActionContext.getServletContext();

        //獲取session對(duì)象
        HttpSession session = request.getSession();
        return super.execute();
    }
}

如果不希望每個(gè)方法都手動(dòng)調(diào)用獲取request可以采用下面方式

public class DemoAction extends ActionSupport implements ServletRequestAware{

    HttpServletRequest request;
    @Override
    public String execute() throws Exception {

    }

    @Override
    public void setServletRequest(HttpServletRequest httpServletRequest) {
         this.request=httpServletRequest;
    }
}
直接實(shí)現(xiàn)接口接可以了

原因在于 我們配置了的action 繼承與struts-default
然后在struts-default


這里寫圖片描述

其中interceptor-stack是個(gè)攔截棧装诡,我們查看servletConfig 所對(duì)應(yīng)的對(duì)象他的class是 org.apache.struts2.interceptor.ServletConfigInterceptor

public String intercept(ActionInvocation invocation) throws Exception {
        Object action = invocation.getAction();
        ActionContext context = invocation.getInvocationContext();
        HttpServletRequest request;
        //這里就是攔截器做的操作银受,如果我們當(dāng)前這個(gè)action實(shí)現(xiàn)了這個(gè)接口,默認(rèn)調(diào)用
        if(action instanceof ServletRequestAware) {
            request = (HttpServletRequest)context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
            ((ServletRequestAware)action).setServletRequest(request);
        }

        if(action instanceof ServletResponseAware) {
            HttpServletResponse response = (HttpServletResponse)context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
            ((ServletResponseAware)action).setServletResponse(response);
        }   
          .....   

獲取參數(shù)

  1. 通過成員變量獲取
    //http://localhost:8080/structs2/api/xxxx?name=tom
public class DemoAction extends ActionSupport{
 @Override
    public String execute() throws Exception {
        System.out.println(name);
        return super.execute();
    }
    public String name;
    public String getName(){
        return name;
    }
    public void setName(String name) {
        this.name = name;
    } 
    //每次訪問一個(gè)action的時(shí)候會(huì)new一個(gè)action對(duì)象出來
    public DemoAction() {
    System.out.println("init");
    }
}
  
  1. 封裝一個(gè)對(duì)象來獲取
//http://localhost:8080/structs2/xxx?mUser.name=tom&mUser.age=123
public class User {
    public String name;
    public int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class DemoAction extends ActionSupport{
public User mUser
 @Override
    public String execute() throws Exception {
        System.out.println(mUser.toString());
        return super.execute();
    }
        public User getmUser() {
        return mUser;
    }

   public void setmUser(User mUser) {
        this.mUser = mUser;
    }
}

但是帶mUser.這種參數(shù)提交方式很奇怪 慎王。

  1. 模型驅(qū)動(dòng)
//http://localhost:8080/structs2/api/xxx?name=tom&age=123
public class DemoAction extends ActionSupport implements ModelDriven<User>{
  public User mUser=new User();
  public String execute() throws Exception {
        System.out.println(mUser.toString());
        return super.execute();
    }
  @Override
    public User getModel() {
        return mUser;
    }
   
}

OGNL語法

OGNL是Object-Graph Navigation Language的縮寫蚓土,全稱為對(duì)象圖導(dǎo)航語言宏侍,是一種功能強(qiáng)大的表達(dá)式語言赖淤,它通過簡單一致的語法,可以任意存取對(duì)象的屬性或者調(diào)用對(duì)象的方法谅河,能夠遍歷整個(gè)對(duì)象的結(jié)構(gòu)圖咱旱,實(shí)現(xiàn)對(duì)象屬性類型的轉(zhuǎn)換等功能确丢。

OGNL表達(dá)式的計(jì)算是圍繞OGNL上下文進(jìn)行的。

  @Test
    public void fun1() throws OgnlException {
        User rootUser=new User("root",12);

        HashMap<String, User> context = new HashMap<>();

        context.put("user1",new User("root1",13));

        context.put("user2",new User("root2",14));
        OgnlContext ognlContext = new OgnlContext();

        ognlContext.setRoot(rootUser);
        ognlContext.setValues(context);

        //取出root中user對(duì)象的name屬性
        String name= (String) Ognl.getValue("name",context,ognlContext.getRoot());
        Integer age= (Integer) Ognl.getValue("age",context,ognlContext.getRoot());
       System.out.println(name+"age="+age);

       //#是從context中取值user1位鍵
        String name1= (String) Ognl.getValue("#user1.name",context,ognlContext.getRoot());
        Integer age1= (Integer) Ognl.getValue("#user1.age",context,ognlContext.getRoot());
        System.out.println(name1+"age="+age1);


        //修改Root中的值
        String name2= (String) Ognl.getValue("name='jack'",context,ognlContext.getRoot());
        Integer age2= (Integer) Ognl.getValue("age",context,ognlContext.getRoot());
        System.out.println(name2+"age="+age2);

        //修改Root中的值
        String name3= (String) Ognl.getValue("#user1.name='tom'",context,ognlContext.getRoot());
        Integer age3= (Integer) Ognl.getValue("#user1.age",context,ognlContext.getRoot());
        System.out.println(name3+"age="+age3);



        //調(diào)用root中的對(duì)象方法
        Ognl.getValue("setName('lilei')",context,ognlContext.getRoot());
        String name4= (String) Ognl.getValue("getName()",context,ognlContext.getRoot());
        System.out.println(name4);


        //調(diào)用map中的對(duì)象方法
        String name5= (String) Ognl.getValue("#user1.setName('11'),#user1.getName()",context,ognlContext.getRoot());
        System.out.println(name5);


        //調(diào)用靜態(tài)方法
        String name6=(String)Ognl.getValue("@com.fmt.Utils@echo('hello world')",context,ognlContext.getRoot());
        System.out.println(name6);

        //調(diào)用靜態(tài)方法
        Double pi=(Double)Ognl.getValue("@@PI",context,ognlContext.getRoot());
        System.out.println(pi);

        //創(chuàng)建對(duì)象
        Integer size= (Integer) Ognl.getValue("{'1','2','3','4'}.size()",context,ognlContext.getRoot());
        System.out.println(size);
        Character number= (Character) Ognl.getValue("{'1','2','3','4'}[2]",context,ognlContext.getRoot());
        System.out.println(number);
        Character number1= (Character) Ognl.getValue("{'1','2','3','4'}.get(2)",context,ognlContext.getRoot());
        System.out.println(number1);

        //創(chuàng)建map
        Integer map_size= (Integer) Ognl.getValue("#{'name':'tom','age':18}.size()",context,ognlContext.getRoot());
        System.out.println(map_size);
    }

ValueStack

ValueStack是一個(gè)接口吐限,在struts2中使用OGNL(Object-Graph Navigation Language)表達(dá)式實(shí)際上是使用,實(shí)現(xiàn)了ValueStack接口的類OgnlValueStack.它是ValueStack的默認(rèn)實(shí)現(xiàn)類.

public interface ValueStack {
    ....

    Map<String, Object> getContext();
    ...
    CompoundRoot getRoot();
    ...
}

public class CompoundRoot extends ArrayList {
    public CompoundRoot() {
    }

    public CompoundRoot(List list) {
        super(list);
    }

    public CompoundRoot cutStack(int index) {
        return new CompoundRoot(this.subList(index, this.size()));
    }

    public Object peek() {
        return this.get(0);
    }

    public Object pop() {
        return this.remove(0);
    }

    public void push(Object o) {
        this.add(0, o);
    }
}
  1. ValueStack貫穿整個(gè)action的生命周期鲜侥,每一個(gè)action實(shí)例都擁有一個(gè)ValueStack對(duì)象,其中保存了當(dāng)前action對(duì)象和其他相關(guān)對(duì)象.
  2. struts2把ValueStack對(duì)象保存在名為:struts.valueStack的request域中.即ValueStack作用域?yàn)閞equest.當(dāng)action創(chuàng)建的時(shí)候诸典,ValueStack就創(chuàng)建了描函,action被銷毀的時(shí)候,ValueStack就銷毀了
  3. ValueStack中的數(shù)據(jù)分兩部分存放:root(棧結(jié)構(gòu)狐粱,CompoundRoot)和context(map形式,OgnlContext)

分析流程

enter image description here

首先是web.xml 中配置了攔截器舀寓,攔截了請(qǐng)求到StrutsPrepareAndExecuteFilter

    <!-- struts2 核心過濾器-->
    <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>
//StrutsPrepareAndExecuteFilter
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;

        try {
            if(this.excludedPatterns != null && this.prepare.isUrlExcluded(request, this.excludedPatterns)) {
                chain.doFilter(request, response);
            } else {
                //設(shè)置編碼和國際化
                this.prepare.setEncodingAndLocale(request, response);
                //創(chuàng)建actionContext上下文(ActionContext,其實(shí)通過ThreadlLocal線程內(nèi)部維護(hù)所以不會(huì)出現(xiàn)不同action,共享的問題)
                this.prepare.createActionContext(request, response);
                this.prepare.assignDispatcherToThread();
                        //這是request的包裝類StrutsRequestWrapper肌蜻,重寫了getAttribute的方法(先從request取互墓,如果沒有再次value stack的棧取,最后從actioncntext冉选)
                request = this.prepare.wrapRequest(request);
                                //創(chuàng)建ActionMaping對(duì)象(是當(dāng)前請(qǐng)求信息映射為一個(gè)對(duì)象)(ActionMaping的創(chuàng)建是通過ActionMapper的getMapping方法篡撵,而ActionMapper的默認(rèn)實(shí)現(xiàn)是DefaultActionMapper可以從這個(gè)類的getMaping方法中查看,答題是解析url構(gòu)建mappig對(duì)象) 
                ActionMapping mapping = this.prepare.findActionMapping(request, response, true);
                //如果解析出來是null 則不會(huì)調(diào)用action豆挽,直接放行
                if(mapping == null) {
                    boolean handled = this.execute.executeStaticResourceRequest(request, response);
                    if(!handled) {
                        chain.doFilter(request, response);
                    }
                } else {
                           //執(zhí)行action
                    this.execute.executeAction(request, response, mapping);
                }
            }
        } finally {
            this.prepare.cleanupRequest(request);
        }

    }

  public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
        Integer counter = Integer.valueOf(1);
        Integer oldCounter = (Integer)request.getAttribute("__cleanup_recursion_counter");
        if(oldCounter != null) {
            counter = Integer.valueOf(oldCounter.intValue() + 1);
        }
         //從本地的ThreadLocal中獲取
        ActionContext oldContext = ActionContext.getContext();
        ActionContext ctx;
        if(oldContext != null) {
            ctx = new ActionContext(new HashMap(oldContext.getContextMap()));
        } else {
           // 創(chuàng)建了ValueStack 
            ValueStack stack = ((ValueStackFactory)this.dispatcher.getContainer().getInstance(ValueStackFactory.class)).createValueStack();
                     //ValueStack 中context放置了一地參數(shù) 進(jìn)入createContextMap內(nèi)部一對(duì)map育谬,有application,params帮哈,session等
            stack.getContext().putAll(this.dispatcher.createContextMap(request, response, (ActionMapping)null));
            //返回ActionContext實(shí)際還是ValuesStack中的context的
            ctx = new ActionContext(stack.getContext());
        }

        request.setAttribute("__cleanup_recursion_counter", counter);
        ActionContext.setContext(ctx);
        return ctx;
    }
//執(zhí)行 this.execute.executeAction(request, response, mapping); 最終進(jìn)入
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
        Map<String, Object> extraContext = this.createContextMap(request, response, mapping);
        ValueStack stack = (ValueStack)request.getAttribute("struts.valueStack");
        boolean nullStack = stack == null;
        if(nullStack) {
            ActionContext ctx = ActionContext.getContext();
            if(ctx != null) {
                stack = ctx.getValueStack();
            }
        }

        if(stack != null) {
            extraContext.put("com.opensymphony.xwork2.util.ValueStack.ValueStack", this.valueStackFactory.createValueStack(stack));
        }

        String timerKey = "Handling request from Dispatcher";

        try {
            UtilTimerStack.push(timerKey);
            String namespace = mapping.getNamespace();
            String name = mapping.getName();
            String method = mapping.getMethod();
//此次根據(jù)actinMapping的action信息構(gòu)建action的代理  
            ActionProxy proxy = ((ActionProxyFactory)this.getContainer().getInstance(ActionProxyFactory.class)).createActionProxy(namespace, name, method, extraContext, true, false);
            request.setAttribute("struts.valueStack", proxy.getInvocation().getStack());
            if(mapping.getResult() != null) {
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            } else {
                //代理執(zhí)行(ActionProxy實(shí)現(xiàn)類StrutsActionProxy)
                proxy.execute();
            }

            if(!nullStack) {
                request.setAttribute("struts.valueStack", stack);
            }
        } catch (ConfigurationException var17) {
            this.logConfigurationException(request, var17);
            this.sendError(request, response, 404, var17);
        } catch (Exception var18) {
            if(!this.handleException && !this.devMode) {
                throw new ServletException(var18);
            }

            this.sendError(request, response, 500, var18);
        } finally {
            UtilTimerStack.pop(timerKey);
        }

    }
  //StrutsActionProxy
   public String execute() throws Exception {
        ActionContext previous = ActionContext.getContext();
        ActionContext.setContext(this.invocation.getInvocationContext());

        String var2;
        try { 
        //當(dāng)前的invocation 實(shí)現(xiàn)類為DefaultActionInvocation
            var2 = this.invocation.invoke();
        } finally {
            if(this.cleanupContext) {
                ActionContext.setContext(previous);
            }

        }

        return var2;
    }
 //DefaultActionInvocation
     public String invoke() throws Exception {
        String profileKey = "invoke: ";

        String var21;
        try {
            UtilTimerStack.push(profileKey);
            if(this.executed) {
                throw new IllegalStateException("Action has already executed");
            }
             //攔截器組這里使用if 和 interceptor.getInterceptor().intercept(this);是遞歸的操作
            if(this.interceptors.hasNext()) {
                                 //依次獲取攔截器 然后執(zhí)行攔截器的intercept方法 然后我們看下struts-default.xml文件中的      <interceptor-stack name="defaultStack"> 下的攔截器
                InterceptorMapping interceptor = (InterceptorMapping)this.interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);

                try {
                    this.resultCode = interceptor.getInterceptor().intercept(this);
                } finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                   //之前的攔截器完成斑司,進(jìn)入我們的action
                this.resultCode = this.invokeActionOnly();
            }

           //同上根據(jù)返回走返回的一對(duì)攔截器
            if(!this.executed) {
                if(this.preResultListeners != null) {
                    Iterator i$ = this.preResultListeners.iterator();
                    
                    while(i$.hasNext()) {
                        Object preResultListener = (PreResultListener)i$.next();
                        PreResultListener listener = (PreResultListener)preResultListener;
                        String _profileKey = "preResultListener: ";

                        try {
                            UtilTimerStack.push(_profileKey);
                            listener.beforeResult(this, this.resultCode);
                        } finally {
                            UtilTimerStack.pop(_profileKey);
                        }
                    }
                }

                if(this.proxy.getExecuteResult()) {
                    this.executeResult();
                }

                this.executed = true;
            }

            var21 = this.resultCode;
        } finally {
            UtilTimerStack.pop(profileKey);
        }

        return var21;
    }

 protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
        String methodName = this.proxy.getMethod();
        。但汞。宿刮。
        //ognl表達(dá)式直接掉方法
        methodResult = this.ognlUtil.getValue(methodName + "()", this.getStack().getContext(), action);
        。私蕾。僵缺。
     String var22 = this.saveResult(actionConfig, methodResult);
     return var22;
    }
已exception 是    defaultStack攔截器組下第一個(gè)攔截器 對(duì)應(yīng)的class是com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor

    public String intercept(ActionInvocation invocation) throws Exception {
        String result;
        try {
        //這里的invocation.invoke();就是上面過來的this,形成遞歸
            result = invocation.invoke();
        } catch (Exception var7) {
            if(this.isLogEnabled()) {
                this.handleLogging(var7);
            }

....

攔截器使用

//使用攔截器的方式  實(shí)現(xiàn)Interceptor踩叭,繼承AbstractInterceptor 以及繼承MethodFilterInterceptor磕潮,三種這邊直接使用第三種
public class MyIntercept3  extends MethodFilterInterceptor{
    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        System.out.println("處理前");
        //放行
        actionInvocation.invoke();
        System.out.println("處理后");
        // return 的意義在于如果你不放行直接返回給result如果放行成功,這個(gè)return就沒有意義
        return "success";
    }
}

xml中配置

  <package name="hello" namespace="/hello" extends="struts-default">
            <interceptors>
                <!--注冊(cè)攔截器-->
                <interceptor name="MyInter3" class="com.fmt.intercept.MyIntercept3"></interceptor>
                <!--注冊(cè)攔截棧-->
                <interceptor-stack name="mystack" >
                    <!-- 自定義攔截器-->
                    <interceptor-ref name="MyInter3">
                          <!--指定那些方法不攔截-->
                    <param name="excludeMethods">add,delete</param>
                    <!--指定那些方法 攔截-->
                    <param name="includeMethods">change</param>
                    </interceptor-ref>
                    <!--引用默認(rèn)的20個(gè)攔截器-->
                    <interceptor-ref name="defaultStack"></interceptor-ref>
                </interceptor-stack>
            </interceptors>
       
            <default-interceptor-ref name="mystack">

            </default-interceptor-ref>
                <action name="HelloAction" class="com.fmt.struct.HelloAction" method="hello">
                    <interceptor-ref name="mystack"></interceptor-ref>
                <result name="success">/showjs.jsp</result>
        </action>
    </package>

參考文章
http://blog.csdn.net/tjcyjd/article/details/6850203
http://501565246-qq-com.iteye.com/blog/1748513

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末容贝,一起剝皮案震驚了整個(gè)濱河市自脯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斤富,老刑警劉巖膏潮,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異满力,居然都是意外死亡焕参,警方通過查閱死者的電腦和手機(jī)轻纪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叠纷,“玉大人刻帚,你說我怎么就攤上這事∩” “怎么了崇众?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長航厚。 經(jīng)常有香客問我校摩,道長,這世上最難降的妖魔是什么阶淘? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任衙吩,我火速辦了婚禮,結(jié)果婚禮上溪窒,老公的妹妹穿的比我還像新娘坤塞。我一直安慰自己,他們只是感情好澈蚌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布摹芙。 她就那樣靜靜地躺著,像睡著了一般宛瞄。 火紅的嫁衣襯著肌膚如雪浮禾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天份汗,我揣著相機(jī)與錄音盈电,去河邊找鬼。 笑死杯活,一個(gè)胖子當(dāng)著我的面吹牛匆帚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播旁钧,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吸重,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了歪今?” 一聲冷哼從身側(cè)響起嚎幸,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寄猩,沒想到半個(gè)月后嫉晶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年车遂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了封断。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斯辰。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舶担,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出彬呻,到底是詐尸還是另有隱情衣陶,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布闸氮,位于F島的核電站剪况,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蒲跨。R本人自食惡果不足惜译断,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望或悲。 院中可真熱鬧孙咪,春花似錦、人聲如沸巡语。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽男公。三九已至荤堪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間枢赔,已是汗流浹背澄阳。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踏拜,地道東北人寇荧。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像执隧,于是被迫代替她去往敵國和親揩抡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 概述 什么是Struts2的框架Struts2是Struts1的下一代產(chǎn)品镀琉,是在 struts1和WebWork的...
    inke閱讀 2,256評(píng)論 0 50
  • 1.什么是框架 什么是框架,框架從何而來,為什么使用框架? 1).框架(framework)——半成品: 1.是一...
    賈里閱讀 2,892評(píng)論 0 0
  • action中如何接受頁面?zhèn)鬟^來的參數(shù) 第一種情況:(同名參數(shù)) 例如:通過頁面要把id=1 name=tom a...
    清楓_小天閱讀 2,960評(píng)論 1 22
  • 1峦嗤、struts2工作流程 Struts 2框架本身大致可以分為3個(gè)部分: 核心控制器FilterDispatch...
    重山楊閱讀 1,520評(píng)論 0 38
  • 有沒有那么一首歌烁设,深深的藏在你的心里。可能很久不會(huì)去聽它装黑,但是只要前奏一想起副瀑,你就會(huì)深深的陷入回憶。 看慣了身邊各...
    周詩汶閱讀 511評(píng)論 11 2