Update: struts config, new actions and views
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
103
target/struts2-scaffold-1.0.0/WEB-INF/classes/struts.xml
Normal file
103
target/struts2-scaffold-1.0.0/WEB-INF/classes/struts.xml
Normal file
@@ -0,0 +1,103 @@
|
||||
<?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="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>
|
||||
</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">
|
||||
<result type="redirectAction">user</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">
|
||||
<result type="redirectAction">user</result>
|
||||
</action>
|
||||
|
||||
<action name="user_delete" class="com.example.struts2.UserFormAction" method="delete">
|
||||
<result type="redirectAction">user</result>
|
||||
</action>
|
||||
|
||||
</package>
|
||||
</struts>
|
||||
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/caffeine-2.9.3.jar
Normal file
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/caffeine-2.9.3.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/commons-io-2.15.1.jar
Normal file
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/commons-io-2.15.1.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/freemarker-2.3.32.jar
Normal file
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/freemarker-2.3.32.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/log4j-api-2.23.1.jar
Normal file
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/log4j-api-2.23.1.jar
Normal file
Binary file not shown.
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/ognl-3.3.4.jar
Normal file
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/ognl-3.3.4.jar
Normal file
Binary file not shown.
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/struts2-core-6.4.0.jar
Normal file
BIN
target/struts2-scaffold-1.0.0/WEB-INF/lib/struts2-core-6.4.0.jar
Normal file
Binary file not shown.
26
target/struts2-scaffold-1.0.0/WEB-INF/web.xml
Normal file
26
target/struts2-scaffold-1.0.0/WEB-INF/web.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
|
||||
version="4.0">
|
||||
|
||||
<display-name>Struts2 Scaffold</display-name>
|
||||
|
||||
<!-- Struts2 核心过滤器 -->
|
||||
<filter>
|
||||
<filter-name>struts2</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>struts2</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- 欢迎页 -->
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
</web-app>
|
||||
85
target/struts2-scaffold-1.0.0/calculator.jsp
Normal file
85
target/struts2-scaffold-1.0.0/calculator.jsp
Normal file
@@ -0,0 +1,85 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>计算器 - Struts2 表单示例</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
|
||||
h1 { color: #e74c3c; }
|
||||
.form-group { margin: 15px 0; }
|
||||
label { display: inline-block; width: 100px; }
|
||||
input, select { padding: 8px; font-size: 14px; }
|
||||
button { background: #3498db; color: white; padding: 10px 20px; border: none; cursor: pointer; }
|
||||
button:hover { background: #2980b9; }
|
||||
.result { background: #2ecc71; color: white; padding: 15px; margin: 20px 0; border-radius: 5px; }
|
||||
.error { color: #e74c3c; font-size: 12px; }
|
||||
.tip { background: #f9f9f9; padding: 15px; border-left: 4px solid #3498db; margin: 20px 0; }
|
||||
.quickbar { background:#fff7e6; padding:12px; border-left:4px solid #fa8c16; margin:20px 0; border-radius:6px; }
|
||||
.quickbar button { margin-right:8px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔢 计算器 - Struts2 表单示例</h1>
|
||||
|
||||
<s:if test="result != null">
|
||||
<div class="result">
|
||||
计算结果: <s:property value="num1"/>
|
||||
<s:property value="operator"/>
|
||||
<s:property value="num2"/>
|
||||
= <s:property value="result"/>
|
||||
</div>
|
||||
</s:if>
|
||||
|
||||
<div class="quickbar">
|
||||
<strong>快速实验:</strong>
|
||||
<button type="button" onclick="fillExample(12, '+', 8)">填入正确示例</button>
|
||||
<button type="button" onclick="fillExample(12, '/', 0)">填入除零错误</button>
|
||||
<button type="button" onclick="fillExample('', '*', '')">填入校验错误</button>
|
||||
</div>
|
||||
|
||||
<s:form action="calc_execute" method="post">
|
||||
<div class="form-group">
|
||||
<label>数字 1:</label>
|
||||
<s:textfield name="num1" placeholder="输入第一个数字"/>
|
||||
<s:fielderror fieldName="num1" cssClass="error"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>运算符:</label>
|
||||
<s:select name="operator" list="{'+', '-', '*', '/'}" headerKey="" headerValue="选择运算符"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>数字 2:</label>
|
||||
<s:textfield name="num2" placeholder="输入第二个数字"/>
|
||||
<s:fielderror fieldName="num2" cssClass="error"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit">计算</button>
|
||||
</div>
|
||||
</s:form>
|
||||
|
||||
<div class="tip">
|
||||
<strong>学习点:</strong>
|
||||
<ul>
|
||||
<li><code>name</code> 属性对应 Action 的 setter 方法</li>
|
||||
<li><code><s:fielderror></code> 显示验证错误</li>
|
||||
<li><code>validate()</code> 方法进行数据验证</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p><a href="learn">← 返回学习中心</a></p>
|
||||
|
||||
<script>
|
||||
function fillExample(n1, op, n2) {
|
||||
const fields = document.querySelectorAll('input[type="text"]');
|
||||
const select = document.querySelector('select');
|
||||
if (fields[0]) fields[0].value = n1;
|
||||
if (select) select.value = op;
|
||||
if (fields[1]) fields[1].value = n2;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
21
target/struts2-scaffold-1.0.0/error-invalid-input.jsp
Normal file
21
target/struts2-scaffold-1.0.0/error-invalid-input.jsp
Normal file
@@ -0,0 +1,21 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>参数无效</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 600px; margin: 100px auto; padding: 20px; text-align: center; }
|
||||
h1 { color: #e74c3c; }
|
||||
.error-box { background: #fdeaea; border: 1px solid #e74c3c; padding: 30px; border-radius: 10px; }
|
||||
.info { color: #7f8c8d; margin-top: 20px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="error-box">
|
||||
<h1>🚫 检测到无效参数</h1>
|
||||
<p>您的请求包含可疑内容,已被拦截。</p>
|
||||
<p class="info">此页面由 ValidationInterceptor 拦截器生成</p>
|
||||
</div>
|
||||
<p><a href="learn">← 返回学习中心</a></p>
|
||||
</body>
|
||||
</html>
|
||||
21
target/struts2-scaffold-1.0.0/error-rate-limit.jsp
Normal file
21
target/struts2-scaffold-1.0.0/error-rate-limit.jsp
Normal file
@@ -0,0 +1,21 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>请求过于频繁</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 600px; margin: 100px auto; padding: 20px; text-align: center; }
|
||||
h1 { color: #e74c3c; }
|
||||
.error-box { background: #fdeaea; border: 1px solid #e74c3c; padding: 30px; border-radius: 10px; }
|
||||
.info { color: #7f8c8d; margin-top: 20px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="error-box">
|
||||
<h1>⚠️ 请求过于频繁</h1>
|
||||
<p>您的请求次数超过限制,请稍后再试。</p>
|
||||
<p class="info">此页面由 RateLimitInterceptor 拦截器生成</p>
|
||||
</div>
|
||||
<p><a href="learn">← 返回学习中心</a></p>
|
||||
</body>
|
||||
</html>
|
||||
8
target/struts2-scaffold-1.0.0/hello.jsp
Normal file
8
target/struts2-scaffold-1.0.0/hello.jsp
Normal file
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Struts2 Scaffold</title></head>
|
||||
<body>
|
||||
<h1>${message}</h1>
|
||||
<p>Struts2 脚手架部署中...</p>
|
||||
</body>
|
||||
</html>
|
||||
33
target/struts2-scaffold-1.0.0/index.jsp
Normal file
33
target/struts2-scaffold-1.0.0/index.jsp
Normal file
@@ -0,0 +1,33 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Struts2 Scaffold</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; text-align: center; }
|
||||
h1 { color: #e74c3c; font-size: 2.5em; }
|
||||
.links { margin: 30px 0; }
|
||||
.links a { display: inline-block; background: #3498db; color: white; padding: 15px 30px; margin: 10px; text-decoration: none; border-radius: 5px; }
|
||||
.links a:hover { background: #2980b9; }
|
||||
.links a.learn { background: #2ecc71; }
|
||||
.links a.learn:hover { background: #27ae60; }
|
||||
.info { color: #7f8c8d; margin-top: 40px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🚀 Struts2 Scaffold</h1>
|
||||
<p>Struts2 学习脚手架已启动!</p>
|
||||
|
||||
<div class="links">
|
||||
<a href="learn" class="learn">📚 学习中心</a>
|
||||
</div>
|
||||
|
||||
<div class="links">
|
||||
<a href="hello">Hello 示例</a>
|
||||
<a href="calc">计算器</a>
|
||||
<a href="user">用户管理</a>
|
||||
</div>
|
||||
|
||||
<p class="info">Powered by Struts2 + Jetty</p>
|
||||
</body>
|
||||
</html>
|
||||
80
target/struts2-scaffold-1.0.0/interceptor-demo.jsp
Normal file
80
target/struts2-scaffold-1.0.0/interceptor-demo.jsp
Normal file
@@ -0,0 +1,80 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<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>
|
||||
<p>API 栈包含: 日志 + 限流 + 验证 + 计时 + 默认栈</p>
|
||||
</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>
|
||||
112
target/struts2-scaffold-1.0.0/learn.jsp
Normal file
112
target/struts2-scaffold-1.0.0/learn.jsp
Normal file
@@ -0,0 +1,112 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<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: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0; }
|
||||
.card h3 { margin-top: 0; }
|
||||
ul { line-height: 2; }
|
||||
a { color: #3498db; text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
.btn { display: inline-block; background: #3498db; color: white; padding: 10px 20px;
|
||||
border-radius: 5px; margin: 5px; }
|
||||
.btn:hover { text-decoration: none; background: #2980b9; }
|
||||
.btn-green { background: #27ae60; }
|
||||
.btn-purple { background: #9b59b6; }
|
||||
code { background: #eee; padding: 2px 6px; border-radius: 3px; }
|
||||
.lab { background:#fff7e6; border-left:4px solid #fa8c16; padding:15px; border-radius:8px; margin:20px 0; }
|
||||
.quick-tools { display:flex; gap:10px; flex-wrap:wrap; margin-top:10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🎓 Struts2 学习中心</h1>
|
||||
|
||||
<div class="lab">
|
||||
<strong>🧪 学习任务卡</strong>
|
||||
<ul>
|
||||
<li>先点“拦截器演示”,观察执行统计和链路顺序</li>
|
||||
<li>再点“计算器”,故意输入非法值体验 Struts2 验证</li>
|
||||
<li>最后点“用户管理”,理解 Action + JSP + 表单提交流程</li>
|
||||
</ul>
|
||||
<div class="quick-tools">
|
||||
<a class="btn btn-purple" href="interceptor">直接去拦截器实验</a>
|
||||
<a class="btn" href="calc">直接去计算器实验</a>
|
||||
<a class="btn btn-green" href="user">直接去用户管理实验</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>🛡️ 拦截器 (核心特性)</h3>
|
||||
<p>拦截器是 Struts2 最强大的特性之一,基于责任链模式实现 AOP。</p>
|
||||
<div>
|
||||
<a class="btn btn-purple" href="interceptor">拦截器演示</a>
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="interceptor">LoggingInterceptor</a> - 日志记录</li>
|
||||
<li><a href="interceptor">TimingInterceptor</a> - 性能计时</li>
|
||||
<li><a href="interceptor">RateLimitInterceptor</a> - IP 限流</li>
|
||||
<li><a href="interceptor">ValidationInterceptor</a> - 参数验证</li>
|
||||
<li><a href="interceptor">MonitorInterceptor</a> - 状态监控</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>📝 基础示例</h3>
|
||||
<div>
|
||||
<a class="btn" href="hello">Hello World</a>
|
||||
<a class="btn" href="calc">计算器</a>
|
||||
<a class="btn btn-green" href="user">用户管理</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>📚 学习路径</h2>
|
||||
|
||||
<div class="card">
|
||||
<h3>1. MVC 架构</h3>
|
||||
<ul>
|
||||
<li><strong>Model:</strong> Action 类 + JavaBean</li>
|
||||
<li><strong>View:</strong> JSP + Struts 标签库</li>
|
||||
<li><strong>Controller:</strong> StrutsPrepareAndExecuteFilter</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>2. 拦截器机制</h3>
|
||||
<ul>
|
||||
<li><code>Interceptor</code> 接口: init() → intercept() → destroy()</li>
|
||||
<li><code>interceptor-stack</code>: 组合多个拦截器</li>
|
||||
<li>执行顺序: 责任链模式(先入后出)</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>3. OGNL 表达式</h3>
|
||||
<ul>
|
||||
<li><code><s:property value="name"/></code> - 输出属性</li>
|
||||
<li><code><s:iterator value="list"></code> - 遍历集合</li>
|
||||
<li><code>#request.key</code> - 访问 request</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>4. 项目结构</h3>
|
||||
<pre>
|
||||
├── src/main/java/com/example/struts2/
|
||||
│ ├── action/ # Action 类
|
||||
│ └── interceptor/ # 自定义拦截器
|
||||
├── src/main/resources/
|
||||
│ └── struts.xml # 核心配置
|
||||
└── src/main/webapp/
|
||||
├── WEB-INF/web.xml # Servlet 配置
|
||||
└── *.jsp # 视图页面
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p><a href="/">← 返回首页</a></p>
|
||||
</body>
|
||||
</html>
|
||||
43
target/struts2-scaffold-1.0.0/user-form.jsp
Normal file
43
target/struts2-scaffold-1.0.0/user-form.jsp
Normal file
@@ -0,0 +1,43 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>用户表单 - Struts2</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 500px; margin: 50px auto; padding: 20px; }
|
||||
h1 { color: #e74c3c; }
|
||||
.form-group { margin: 15px 0; }
|
||||
label { display: block; margin-bottom: 5px; font-weight: bold; }
|
||||
input { width: 100%; padding: 10px; font-size: 14px; box-sizing: border-box; }
|
||||
button { background: #3498db; color: white; padding: 12px 24px; border: none; cursor: pointer; margin-top: 10px; }
|
||||
button:hover { background: #2980b9; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1><s:if test="user.id == null">添加用户</s:if><s:else>编辑用户</s:else></h1>
|
||||
|
||||
<s:form action="%{user.id == null ? 'user_add' : 'user_update'}" method="post">
|
||||
<s:hidden name="user.id"/>
|
||||
|
||||
<div class="form-group">
|
||||
<label>姓名:</label>
|
||||
<s:textfield name="user.name" placeholder="请输入姓名"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>邮箱:</label>
|
||||
<s:textfield name="user.email" placeholder="请输入邮箱"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>年龄:</label>
|
||||
<s:textfield name="user.age" placeholder="请输入年龄"/>
|
||||
</div>
|
||||
|
||||
<button type="submit">保存</button>
|
||||
</s:form>
|
||||
|
||||
<p><a href="user">← 返回用户列表</a></p>
|
||||
</body>
|
||||
</html>
|
||||
59
target/struts2-scaffold-1.0.0/user-list.jsp
Normal file
59
target/struts2-scaffold-1.0.0/user-list.jsp
Normal file
@@ -0,0 +1,59 @@
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>用户管理 - Struts2 CRUD 示例</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
|
||||
h1 { color: #e74c3c; }
|
||||
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
|
||||
th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
|
||||
th { background: #3498db; color: white; }
|
||||
tr:nth-child(even) { background: #f9f9f9; }
|
||||
.btn { padding: 5px 10px; text-decoration: none; border-radius: 3px; margin-right: 5px; }
|
||||
.btn-edit { background: #f39c12; color: white; }
|
||||
.btn-delete { background: #e74c3c; color: white; }
|
||||
.btn-add { background: #2ecc71; color: white; padding: 10px 20px; }
|
||||
.tip { background: #f9f9f9; padding: 15px; border-left: 4px solid #3498db; margin: 20px 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>👥 用户管理 - Struts2 CRUD 示例</h1>
|
||||
|
||||
<p><a class="btn btn-add" href="user_edit">+ 添加用户</a></p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>姓名</th>
|
||||
<th>邮箱</th>
|
||||
<th>年龄</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
<s:iterator value="userList" var="u">
|
||||
<tr>
|
||||
<td><s:property value="#u.id"/></td>
|
||||
<td><s:property value="#u.name"/></td>
|
||||
<td><s:property value="#u.email"/></td>
|
||||
<td><s:property value="#u.age"/></td>
|
||||
<td>
|
||||
<a class="btn btn-edit" href="user_edit?id=<s:property value='#u.id'/>">编辑</a>
|
||||
<a class="btn btn-delete" href="user_delete?id=<s:property value='#u.id'/>" onclick="return confirm('确定删除?')">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</s:iterator>
|
||||
</table>
|
||||
|
||||
<div class="tip">
|
||||
<strong>学习点:</strong>
|
||||
<ul>
|
||||
<li><code><s:iterator></code> 遍历集合</li>
|
||||
<li><code>redirectAction</code> 结果类型实现 PRG 模式</li>
|
||||
<li>动态方法调用处理不同操作</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p><a href="learn">← 返回学习中心</a></p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user