forked from admin/struts2-demo
227 lines
12 KiB
Plaintext
227 lines
12 KiB
Plaintext
<%@ 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"><?xml version="1.0" encoding="UTF-8"?></span>
|
||
<span class="keyword"><!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">></span>
|
||
|
||
<span class="keyword"><validators></span>
|
||
<span class="comment"><!-- 字段验证 --></span>
|
||
<span class="keyword"><field</span> name=<span class="string">"username"</span><span class="keyword">></span>
|
||
<span class="keyword"><field-validator</span> type=<span class="string">"requiredstring"</span><span class="keyword">></span>
|
||
<span class="keyword"><message></span>用户名不能为空<span class="keyword"></message></span>
|
||
<span class="keyword"></field-validator></span>
|
||
<span class="keyword"><field-validator</span> type=<span class="string">"stringlength"</span><span class="keyword">></span>
|
||
<span class="keyword"><param</span> name=<span class="string">"minLength"</span><span class="keyword">></span>3<span class="keyword"></param></span>
|
||
<span class="keyword"><param</span> name=<span class="string">"maxLength"</span><span class="keyword">></span>20<span class="keyword"></param></span>
|
||
<span class="keyword"><message></span>用户名长度3-20字符<span class="keyword"></message></span>
|
||
<span class="keyword"></field-validator></span>
|
||
<span class="keyword"></field></span>
|
||
|
||
<span class="comment"><!-- 字段验证:email --></span>
|
||
<span class="keyword"><field</span> name=<span class="string">"email"</span><span class="keyword">></span>
|
||
<span class="keyword"><field-validator</span> type=<span class="string">"email"</span><span class="keyword">></span>
|
||
<span class="keyword"><message></span>邮箱格式不正确<span class="keyword"></message></span>
|
||
<span class="keyword"></field-validator></span>
|
||
<span class="keyword"></field></span>
|
||
|
||
<span class="comment"><!-- 非字段验证 --></span>
|
||
<span class="keyword"><validator</span> type=<span class="string">"expression"</span><span class="keyword">></span>
|
||
<span class="keyword"><param</span> name=<span class="string">"expression"</span><span class="keyword">></span>password==confirmPassword<span class="keyword"></param></span>
|
||
<span class="keyword"><message></span>两次密码不一致<span class="keyword"></message></span>
|
||
<span class="keyword"></validator></span>
|
||
<span class="keyword"></validators></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"><%@ taglib prefix="s" uri="/struts-tags" %></span>
|
||
|
||
<span class="comment"><!-- 显示特定字段的错误 --></span>
|
||
<span class="keyword"><s:fielderror</span> fieldName=<span class="string">"username"</span>/>
|
||
|
||
<span class="comment"><!-- 显示所有字段错误 --></span>
|
||
<span class="keyword"><s:fielderror</span>/>
|
||
|
||
<span class="comment"><!-- 显示 Action 级别错误 --></span>
|
||
<span class="keyword"><s:actionerror</span>/>
|
||
|
||
<span class="comment"><!-- 显示 Action 级别消息 --></span>
|
||
<span class="keyword"><s:actionmessage</span>/></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> |