<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
    "http://struts.apache.org/dtds/struts-6.0.dtd">
<struts>
    <!-- 开发模式 -->
    <constant name="struts.devMode" value="true" />
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <constant name="struts.action.extension" value="action,," />
    
    <package name="default" namespace="/" extends="struts-default">
        
        <!-- ========== 自定义拦截器配置 ========== -->
        <interceptors>
            <interceptor name="logging" class="com.example.struts2.interceptor.LoggingInterceptor"/>
            <interceptor name="timing" class="com.example.struts2.interceptor.TimingInterceptor"/>
            <interceptor name="rateLimit" class="com.example.struts2.interceptor.RateLimitInterceptor"/>
            <interceptor name="validation" class="com.example.struts2.interceptor.ValidationInterceptor"/>
            <interceptor name="monitor" class="com.example.struts2.interceptor.MonitorInterceptor"/>
            
            <interceptor-stack name="customStack">
                <interceptor-ref name="logging"/>
                <interceptor-ref name="timing"/>
                <interceptor-ref name="monitor"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
            
            <interceptor-stack name="apiStack">
                <interceptor-ref name="logging"/>
                <interceptor-ref name="rateLimit">
                    <param name="maxRequestsPerMinute">100</param>
                </interceptor-ref>
                <interceptor-ref name="validation"/>
                <interceptor-ref name="timing"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>
        
        <!-- 默认拦截器栈 -->
        <default-interceptor-ref name="customStack"/>
        
        <!-- 默认 Action -->
        <default-action-ref name="index" />
        
        <!-- 全局结果 -->
        <global-results>
            <result name="rateLimitExceeded">/error-rate-limit.jsp</result>
            <result name="invalidInput">/error-invalid-input.jsp</result>
        </global-results>
        
        <!-- ========== Actions ========== -->
        <action name="index">
            <result>/index.jsp</result>
        </action>
        
        <action name="hello" class="com.example.struts2.HelloAction">
            <result>/hello.jsp</result>
        </action>
        
        <action name="learn" class="com.example.struts2.LearnAction">
            <result>/learn.jsp</result>
        </action>
        
        <action name="interceptor" class="com.example.struts2.InterceptorDemoAction">
            <result>/interceptor-demo.jsp</result>
        </action>

        <action name="ognl" class="com.example.struts2.OgnlLabAction">
            <result>/ognl-lab.jsp</result>
        </action>

        <action name="ognl_bind" class="com.example.struts2.OgnlLabAction" method="bind">
            <result>/ognl-lab.jsp</result>
        </action>

        <action name="validation" class="com.example.struts2.ValidationLabAction">
            <result>/validation-lab.jsp</result>
        </action>

        <action name="validation_submit" class="com.example.struts2.ValidationLabAction" method="submit">
            <param name="actionName">submit</param>
            <result>/validation-lab.jsp</result>
            <result name="input">/validation-lab.jsp</result>
        </action>
        
        <action name="interceptor_api" class="com.example.struts2.InterceptorDemoAction">
            <interceptor-ref name="apiStack"/>
            <result>/interceptor-demo.jsp</result>
        </action>
        
        <action name="calc" class="com.example.struts2.CalculatorAction">
            <result>/calculator.jsp</result>
            <result name="input">/calculator.jsp</result>
        </action>
        
        <action name="calc_execute" class="com.example.struts2.CalculatorAction" method="calculate">
            <result>/calculator.jsp</result>
            <result name="input">/calculator.jsp</result>
        </action>
        
        <action name="user" class="com.example.struts2.UserFormAction" method="list">
            <result>/user-list.jsp</result>
        </action>
        
        <action name="user_add" class="com.example.struts2.UserFormAction" method="add">
            <param name="actionName">user_add</param>
            <result type="redirectAction">user</result>
            <result name="input">/user-form.jsp</result>
        </action>
        
        <action name="user_edit" class="com.example.struts2.UserFormAction" method="edit">
            <result>/user-form.jsp</result>
        </action>
        
        <action name="user_update" class="com.example.struts2.UserFormAction" method="update">
            <param name="actionName">user_update</param>
            <result type="redirectAction">user</result>
            <result name="input">/user-form.jsp</result>
        </action>
        
        <action name="user_delete" class="com.example.struts2.UserFormAction" method="delete">
            <result type="redirectAction">user</result>
        </action>
        
        <!-- AJAX演示 -->
        <action name="ajax" class="com.example.struts2.AjaxDemoAction">
            <result>/ajax-demo.jsp</result>
        </action>
        
        <action name="ajax_checkUsername" class="com.example.struts2.AjaxDemoAction" method="checkUsername">
            <result type="json"/>
        </action>
        
        <action name="ajax_getStats" class="com.example.struts2.AjaxDemoAction" method="getStats">
            <result type="json"/>
        </action>
        
        <action name="ajax_saveUser" class="com.example.struts2.AjaxDemoAction" method="saveUser">
            <result type="json"/>
        </action>
        
        <action name="ajax_getRealtimeData" class="com.example.struts2.AjaxDemoAction" method="getRealtimeData">
            <result type="json"/>
        </action>
        
        <!-- 文件上传 -->
        <action name="upload" class="com.example.struts2.FileUploadAction">
            <result>/file-upload.jsp</result>
        </action>
        
        <action name="uploadSingle" class="com.example.struts2.FileUploadAction" method="uploadSingle">
            <result>/file-upload.jsp</result>
            <result name="input">/file-upload.jsp</result>
        </action>
        
        <action name="uploadMultiple" class="com.example.struts2.FileUploadAction" method="uploadMultiple">
            <result>/file-upload.jsp</result>
            <result name="input">/file-upload.jsp</result>
        </action>
        
        <!-- 类加载可视化 -->
        <action name="classloader" class="com.example.struts2.ClassLoaderAction">
            <result>/classloader-visual.jsp</result>
        </action>
        
        <action name="classloader_getHierarchy" class="com.example.struts2.ClassLoaderAction" method="getClassLoaderHierarchy">
            <result type="json"/>
        </action>
        
        <action name="classloader_getLoadedClasses" class="com.example.struts2.ClassLoaderAction" method="getLoadedClasses">
            <result type="json"/>
        </action>
        
        <action name="classloader_simulate" class="com.example.struts2.ClassLoaderAction" method="simulateClassLoading">
            <result type="json"/>
        </action>
        
        <action name="classloader_getStrutsClasses" class="com.example.struts2.ClassLoaderAction" method="getStrutsClassesInfo">
            <result type="json"/>
        </action>
        
        <!-- Action生命周期可视化 -->
        <action name="lifecycle" class="com.example.struts2.ActionLifecycleAction">
            <result>/lifecycle-visual.jsp</result>
        </action>
        
        <action name="lifecycle_getLifecycle" class="com.example.struts2.ActionLifecycleAction" method="getLifecycle">
            <result type="json"/>
        </action>
        
        <action name="lifecycle_getInterceptorChain" class="com.example.struts2.ActionLifecycleAction" method="getInterceptorChain">
            <result type="json"/>
        </action>
        
        <action name="lifecycle_simulate" class="com.example.struts2.ActionLifecycleAction" method="simulateRequest">
            <result type="json"/>
        </action>
        
        <action name="lifecycle_getValueStack" class="com.example.struts2.ActionLifecycleAction" method="getValueStack">
            <result type="json"/>
        </action>
        
    </package>
</struts>