Update: web.xml and generated files

This commit is contained in:
likingcode
2026-03-18 15:18:30 +08:00
parent fb9d2d1206
commit 1f60832445
20 changed files with 2071 additions and 2 deletions

View File

@@ -0,0 +1,227 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表单验证 - Struts2 学习</title>
<style>
body { font-family: 'Segoe UI', 'PingFang SC', sans-serif; background: linear-gradient(135deg, #667eea, #764ba2); min-height: 100vh; margin: 0; padding: 20px; }
.container { max-width: 1200px; margin: 0 auto; }
.breadcrumb { background: white; padding: 15px 25px; border-radius: 10px; margin-bottom: 20px; }
.breadcrumb a { color: #667eea; text-decoration: none; }
.content { background: white; border-radius: 20px; padding: 40px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); }
h1 { color: #667eea; border-bottom: 3px solid #667eea; padding-bottom: 15px; }
h2 { color: #764ba2; margin-top: 30px; }
.section { margin: 25px 0; padding: 20px; background: #f8f9fa; border-radius: 10px; }
pre { background: #1e1e1e; color: #d4d4d4; padding: 20px; border-radius: 10px; overflow-x: auto; font-size: 0.9em; }
.keyword { color: #569cd6; }
.string { color: #ce9178; }
.comment { color: #6a9955; }
.btn { display: inline-block; padding: 12px 30px; background: #667eea; color: white; text-decoration: none; border-radius: 25px; margin-right: 10px; }
.note { background: #fff3e0; border-left: 4px solid #ff9800; padding: 15px; margin: 20px 0; border-radius: 0 10px 10px 0; }
.tip { background: #e3f2fd; border-left: 4px solid #2196f3; padding: 15px; margin: 20px 0; border-radius: 0 10px 10px 0; }
</style>
</head>
<body>
<div class="container">
<div class="breadcrumb">
<a href="/">🏠 首页</a> / 表单验证
</div>
<div class="content">
<h1>✅ 表单验证</h1>
<div class="note">
<strong>📝 本节要点:</strong> 掌握 Struts2 的两种验证方式:编程式验证和声明式验证
</div>
<h2>1. 验证方式概览</h2>
<div class="section">
<table style="width:100%; border-collapse: collapse;">
<tr style="background:#667eea; color:white;">
<th style="padding:10px; text-align:left;">方式</th>
<th style="padding:10px; text-align:left;">实现方式</th>
<th style="padding:10px; text-align:left;">适用场景</th>
</tr>
<tr style="background:#f8f9fa;">
<td style="padding:10px;">编程式</td>
<td style="padding:10px;">重写 validate() 方法</td>
<td style="padding:10px;">简单验证,逻辑复杂</td>
</tr>
<tr>
<td style="padding:10px;">声明式 - 方法级</td>
<td style="padding:10px;">validateXxx() 方法</td>
<td style="padding:10px;">特定方法的验证</td>
</tr>
<tr style="background:#f8f9fa;">
<td style="padding:10px;">声明式 - XML</td>
<td style="padding:10px;">XxxAction-validation.xml</td>
<td style="padding:10px;">可复用,团队协作</td>
</tr>
</table>
</div>
<h2>2. 方式一:编程式验证 (validate)</h2>
<div class="section">
<pre><span class="keyword">public class</span> LoginAction <span class="keyword">extends</span> ActionSupport {
<span class="keyword">private</span> String username;
<span class="keyword">private</span> String password;
<span class="annotation">@Override</span>
<span class="keyword">public</span> String execute() {
<span class="comment">// 登录逻辑...</span>
<span class="keyword">return</span> SUCCESS;
}
<span class="comment">/**
* 验证方法 - 对所有 execute 方法都生效
*/</span>
<span class="annotation">@Override</span>
<span class="keyword">public void</span> validate() {
<span class="comment">// 用户名验证</span>
<span class="keyword">if</span> (username == <span class="keyword">null</span> || username.trim().length() < 3) {
addFieldError(<span class="string">"username"</span>, <span class="string">"用户名至少3个字符"</span>);
}
<span class="comment">// 密码验证</span>
<span class="keyword">if</span> (password == <span class="keyword">null</span> || password.length() < 6) {
addFieldError(<span class="string">"password"</span>, <span class="string">"密码至少6个字符"</span>);
}
}
<span class="comment">// getter/setter...</span>
}</pre>
</div>
<h2>3. 方式二:方法级验证 (validateXxx)</h2>
<div class="section">
<pre><span class="comment">/**
* 只验证 register 方法,不验证 login 方法
*/</span>
<span class="keyword">public void</span> validateRegister() {
<span class="keyword">if</span> (email == <span class="keyword">null</span> || !email.contains(<span class="string">"@"</span>)) {
addFieldError(<span class="string">"email"</span>, <span class="string">"邮箱格式不正确"</span>);
}
}</pre>
</div>
<h2>4. 方式三XML 声明式验证</h2>
<div class="tip">
<strong>优点:</strong> 验证规则与代码分离,团队协作更清晰,可复用
</div>
<h3>4.1 创建验证文件</h3>
<div class="section">
<p>文件名格式:<code>ActionName-validation.xml</code></p>
<p>位置:<code>WEB-INF/classes/com/demo/action/</code></p>
<pre><span class="comment">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="keyword">&lt;!DOCTYPE validators PUBLIC</span>
<span class="string">"-//OpenSymphony Group//XWork Validator 1.0.3//EN"</span>
<span class="string">"http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd"</span><span class="keyword">&gt;</span>
<span class="keyword">&lt;validators&gt;</span>
<span class="comment">&lt;!-- 字段验证 --&gt;</span>
<span class="keyword">&lt;field</span> name=<span class="string">"username"</span><span class="keyword">&gt;</span>
<span class="keyword">&lt;field-validator</span> type=<span class="string">"requiredstring"</span><span class="keyword">&gt;</span>
<span class="keyword">&lt;message&gt;</span>用户名不能为空<span class="keyword">&lt;/message&gt;</span>
<span class="keyword">&lt;/field-validator&gt;</span>
<span class="keyword">&lt;field-validator</span> type=<span class="string">"stringlength"</span><span class="keyword">&gt;</span>
<span class="keyword">&lt;param</span> name=<span class="string">"minLength"</span><span class="keyword">&gt;</span>3<span class="keyword">&lt;/param&gt;</span>
<span class="keyword">&lt;param</span> name=<span class="string">"maxLength"</span><span class="keyword">&gt;</span>20<span class="keyword">&lt;/param&gt;</span>
<span class="keyword">&lt;message&gt;</span>用户名长度3-20字符<span class="keyword">&lt;/message&gt;</span>
<span class="keyword">&lt;/field-validator&gt;</span>
<span class="keyword">&lt;/field&gt;</span>
<span class="comment">&lt;!-- 字段验证email --&gt;</span>
<span class="keyword">&lt;field</span> name=<span class="string">"email"</span><span class="keyword">&gt;</span>
<span class="keyword">&lt;field-validator</span> type=<span class="string">"email"</span><span class="keyword">&gt;</span>
<span class="keyword">&lt;message&gt;</span>邮箱格式不正确<span class="keyword">&lt;/message&gt;</span>
<span class="keyword">&lt;/field-validator&gt;</span>
<span class="keyword">&lt;/field&gt;</span>
<span class="comment">&lt;!-- 非字段验证 --&gt;</span>
<span class="keyword">&lt;validator</span> type=<span class="string">"expression"</span><span class="keyword">&gt;</span>
<span class="keyword">&lt;param</span> name=<span class="string">"expression"</span><span class="keyword">&gt;</span>password==confirmPassword<span class="keyword">&lt;/param&gt;</span>
<span class="keyword">&lt;message&gt;</span>两次密码不一致<span class="keyword">&lt;/message&gt;</span>
<span class="keyword">&lt;/validator&gt;</span>
<span class="keyword">&lt;/validators&gt;</span></pre>
</div>
<h2>5. 常用验证器类型</h2>
<div class="section">
<table style="width:100%; border-collapse: collapse;">
<tr style="background:#667eea; color:white;">
<th style="padding:10px; text-align:left;">验证器</th>
<th style="padding:10px; text-align:left;">说明</th>
<th style="padding:10px; text-align:left;">示例</th>
</tr>
<tr style="background:#f8f9fa;">
<td style="padding:10px;">required</td>
<td style="padding:10px;">必填</td>
<td style="padding:10px;">username 不能为空</td>
</tr>
<tr>
<td style="padding:10px;">requiredstring</td>
<td style="padding:10px;">字符串必填</td>
<td style="padding:10px;">不能为空字符串</td>
</tr>
<tr style="background:#f8f9fa;">
<td style="padding:10px;">stringlength</td>
<td style="padding:10px;">字符串长度</td>
<td style="padding:10px;">minLength, maxLength</td>
</tr>
<tr>
<td style="padding:10px;">email</td>
<td style="padding:10px;">邮箱格式</td>
<td style="padding:10px;">xxx@xxx.com</td>
</tr>
<tr style="background:#f8f9fa;">
<td style="padding:10px;">regex</td>
<td style="padding:10px;">正则表达式</td>
<td style="padding:10px;">手机号、身份证等</td>
</tr>
<tr>
<td style="padding:10px;">int</td>
<td style="padding:10px;">整数范围</td>
<td style="padding:10px;">min, max</td>
</tr>
<tr style="background:#f8f9fa;">
<td style="padding:10px;">url</td>
<td style="padding:10px;">URL 格式</td>
<td style="padding:10px;">http://xxx.com</td>
</tr>
<tr>
<td style="padding:10px;">date</td>
<td style="padding:10px;">日期范围</td>
<td style="padding:10px;">min, max</td>
</tr>
</table>
</div>
<h2>6. 在 JSP 中显示错误</h2>
<div class="section">
<pre><span class="comment">&lt;%@ taglib prefix="s" uri="/struts-tags" %&gt;</span>
<span class="comment">&lt;!-- 显示特定字段的错误 --&gt;</span>
<span class="keyword">&lt;s:fielderror</span> fieldName=<span class="string">"username"</span>/&gt;
<span class="comment">&lt;!-- 显示所有字段错误 --&gt;</span>
<span class="keyword">&lt;s:fielderror</span>/&gt;
<span class="comment">&lt;!-- 显示 Action 级别错误 --&gt;</span>
<span class="keyword">&lt;s:actionerror</span>/&gt;
<span class="comment">&lt;!-- 显示 Action 级别消息 --&gt;</span>
<span class="keyword">&lt;s:actionmessage</span>/&gt;</pre>
</div>
<div style="margin-top: 30px;">
<a href="/demo/model" class="btn">下一节:数据封装 →</a>
<a href="/" class="btn" style="background: #764ba2;">← 返回首页</a>
</div>
</div>
</div>
</body>
</html>