<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>拦截器演示 - Struts2</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 900px; margin: 50px auto; padding: 20px; }
        h1 { color: #e74c3c; }
        h2 { color: #3498db; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
        .card { background: #f9f9f9; padding: 20px; margin: 15px 0; border-radius: 8px; }
        .card h3 { margin-top: 0; color: #2c3e50; }
        code { background: #eee; padding: 2px 6px; border-radius: 3px; }
        pre { background: #2c3e50; color: #ecf0f1; padding: 15px; border-radius: 5px; overflow-x: auto; }
        table { width: 100%; border-collapse: collapse; margin: 10px 0; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background: #3498db; color: white; }
        .time { color: #27ae60; font-weight: bold; }
        .api-link { display: inline-block; background: #9b59b6; color: white; padding: 10px 20px; 
                    text-decoration: none; border-radius: 5px; margin: 5px; }
        .lab { background:#fff7e6; border-left:4px solid #fa8c16; padding:15px; border-radius:8px; margin:20px 0; }
    </style>
</head>
<body>
    <h1>🛡️ Struts2 拦截器演示</h1>

    <div class="lab">
        <strong>实验观察点：</strong>
        <ul>
            <li>连续刷新页面，观察 Action 调用次数如何累积</li>
            <li>切换到“API 限流栈”，理解为什么拦截器顺序会影响结果</li>
            <li>注意执行时间显示，这就是拦截器注入到 request 的数据</li>
        </ul>
    </div>
    
    <div class="card">
        <h3>📊 执行统计</h3>
        <p>本次请求执行时间: <span class="time"><s:property value="executionTime / 1000000.0"/> ms</span></p>
        
        <h4>Action 调用统计:</h4>
        <table>
            <tr><th>Action</th><th>调用次数</th></tr>
            <s:iterator value="interceptorStats" var="entry">
                <tr>
                    <td><s:property value="#entry.key"/></td>
                    <td><s:property value="#entry.value"/></td>
                </tr>
            </s:iterator>
        </table>
    </div>
    
    <div class="card">
        <h3>🔗 拦截器链演示</h3>
        <p>当前使用: <code>customStack</code> (日志 + 计时 + 监控 + 默认栈)</p>
        <a class="api-link" href="interceptor_api">切换到 API 限流栈</a>
        <a class="api-link" href="interceptor">恢复默认栈</a>
        <p>API 栈包含: 日志 + 限流 + 验证 + 计时 + 默认栈</p>
        <table>
            <tr><th>拦截器</th><th>作用</th><th>你应该观察什么</th></tr>
            <tr><td>LoggingInterceptor</td><td>记录请求进入/退出</td><td>看日志顺序，理解责任链</td></tr>
            <tr><td>TimingInterceptor</td><td>统计执行耗时</td><td>看 executionTime 如何注入 request</td></tr>
            <tr><td>MonitorInterceptor</td><td>累积 Action 调用统计</td><td>连续刷新看调用数增长</td></tr>
            <tr><td>RateLimitInterceptor</td><td>限制频率</td><td>API 栈里观察限流触发</td></tr>
            <tr><td>ValidationInterceptor</td><td>校验输入</td><td>思考错误应该在哪一层拦截</td></tr>
        </table>
    </div>
    
    <div class="card">
        <h3>🧪 快速实验建议</h3>
        <ul>
            <li>先刷新当前页两次，看调用统计是否增加</li>
            <li>再切到 <code>interceptor_api</code>，对比多了哪些拦截器</li>
            <li>观察“先进入后退出”的洋葱模型</li>
            <li>思考：如果你要加鉴权，应放在哪个拦截器位置最合理？</li>
        </ul>
    </div>

    <div class="card">
        <h3>📚 拦截器执行顺序</h3>
        <pre>
请求 → LoggingInterceptor → TimingInterceptor → MonitorInterceptor → Action
响应 ← LoggingInterceptor ← TimingInterceptor ← MonitorInterceptor ← Result
        </pre>
        <p><strong>注意:</strong> 拦截器像洋葱一样，先进入的后退出</p>
    </div>
    
    <div class="card">
        <h3>💡 拦截器核心概念</h3>
        <ul>
            <li><strong>Interceptor 接口:</strong> init() → intercept() → destroy()</li>
            <li><strong>intercept() 方法:</strong> 调用 invocation.invoke() 继续链</li>
            <li><strong>拦截器栈:</strong> 多个拦截器按顺序组成链</li>
            <li><strong>责任链模式:</strong> 每个拦截器决定是否继续</li>
        </ul>
    </div>
    
    <p><a href="learn">← 返回学习中心</a></p>
</body>
</html>