Files
struts2-demo/web/demo/model/index.jsp
2026-03-18 15:18:30 +08:00

173 lines
8.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<%@ 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; }
</style>
</head>
<body>
<div class="container">
<div class="breadcrumb">
<a href="/">🏠 首页</a> / 数据封装
</div>
<div class="content">
<h1>📦 数据封装 - 属性驱动 vs 模型驱动</h1>
<div class="note">
<strong>📝 本节要点:</strong> 掌握 Struts2 两种数据封装方式,将请求参数封装到 Java 对象
</div>
<h2>1. 两种封装方式对比</h2>
<div class="section">
<table style="width:100%; border-collapse: collapse;">
<tr style="background:#667eea; color:white;">
<th style="padding:10px;">方式</th>
<th style="padding:10px;">实现</th>
<th style="padding:10px;">适用场景</th>
</tr>
<tr style="background:#f8f9fa;">
<td style="padding:10px;"><strong>属性驱动</strong></td>
<td style="padding:10px;">Action 中定义属性 + getter/setter</td>
<td style="padding:10px;">简单场景,属性较少</td>
</tr>
<tr>
<td style="padding:10px;"><strong>模型驱动</strong></td>
<td style="padding:10px;">实现 ModelDriven 接口</td>
<td style="padding:10px;">复杂对象,表单字段多</td>
</tr>
</table>
</div>
<h2>2. 方式一:属性驱动 (Property Driven)</h2>
<h3>2.1 基本属性封装</h3>
<div class="section">
<pre><span class="comment">/**
* 直接在 Action 中定义属性
* 表单: &lt;input name="username"&gt; 会自动调用 setUsername()
*/</span>
<span class="keyword">public class</span> UserAction <span class="keyword">extends</span> ActionSupport {
<span class="comment">// Struts2 自动调用 setter 注入参数</span>
<span class="keyword">private</span> String username;
<span class="keyword">private</span> String email;
<span class="keyword">private</span> Integer age;
<span class="annotation">@Override</span>
<span class="keyword">public</span> String execute() {
System.out.println(username + <span class="string">" - "</span> + email + <span class="string">" - "</span> + age);
<span class="keyword">return</span> SUCCESS;
}
<span class="comment">// 必须提供 setter 和 getter</span>
<span class="keyword">public</span> String getUsername() { <span class="keyword">return</span> username; }
<span class="keyword">public void</span> setUsername(String username) { <span class="keyword">this</span>.username = username; }
<span class="keyword">public</span> String getEmail() { <span class="keyword">return</span> email; }
<span class="keyword">public void</span> setEmail(String email) { <span class="keyword">this</span>.email = email; }
<span class="keyword">public</span> Integer getAge() { <span class="keyword">return</span> age; }
<span class="keyword">public void</span> setAge(Integer age) { <span class="keyword">this</span>.age = age; }
}</pre>
</div>
<h3>2.2 复杂属性 (嵌套对象)</h3>
<div class="section">
<p>表单中的 <code>user.username</code> 会自动调用 setUser(用户对象).setUsername()</p>
<pre><span class="comment">// Action</span>
<span class="keyword">private</span> User user; <span class="comment">// 包含 username, email 属性的对象</span>
<span class="comment">// 表单</span>
<span class="keyword">&lt;input</span> name=<span class="string">"user.username"</span>/&gt;
<span class="keyword">&lt;input</span> name=<span class="string">"user.email"</span>/&gt;</pre>
</div>
<h2>3. 方式二:模型驱动 (ModelDriven)</h2>
<div class="note">
<strong>💡 推荐:</strong> 对于复杂表单使用模型驱动更清晰Action 和 Model 分离
</div>
<div class="section">
<pre><span class="keyword">import</span> com.opensymphony.xwork2.ModelDriven;
<span class="comment">/**
* 实现 ModelDriven 接口
* 需要:
* 1. 实现 getModel() 方法
* 2. 泛型指定模型类型
*/</span>
<span class="keyword">public class</span> UserAction <span class="keyword">extends</span> ActionSupport <span class="keyword">implements</span> ModelDriven&lt;User&gt; {
<span class="comment">// 模型对象</span>
<span class="keyword">private</span> User user = <span class="keyword">new</span> User();
<span class="comment">/**
* 返回模型对象
* Struts2 会把参数注入到返回的对象中
*/</span>
<span class="annotation">@Override</span>
<span class="keyword">public</span> User getModel() {
<span class="keyword">return</span> user;
}
<span class="annotation">@Override</span>
<span class="keyword">public</span> String execute() {
<span class="comment">// 直接使用 user 对象</span>
System.out.println(user.getUsername());
<span class="keyword">return</span> SUCCESS;
}
}</pre>
</div>
<h2>4. List/Map 属性封装</h2>
<div class="section">
<pre><span class="comment">// Action - 接收 List</span>
<span class="keyword">private</span> List&lt;User&gt; users;
<span class="keyword">public void</span> setUsers(List&lt;User&gt; users) { <span class="keyword">this</span>.users = users; }
<span class="keyword">public</span> List&lt;User&gt; getUsers() { <span class="keyword">return</span> users; }
<span class="comment">// 页面表单 - users[0].username, users[1].username</span>
<span class="keyword">&lt;input</span> name=<span class="string">"users[0].username"</span> value=<span class="string">"张三"</span>/&gt;
<span class="keyword">&lt;input</span> name=<span class="string">"users[1].username"</span> value=<span class="string">"李四"</span>/&gt;
<span class="comment">// Action - 接收 Map</span>
<span class="keyword">private</span> Map&lt;String, User&gt; userMap;
<span class="keyword">&lt;input</span> name=<span class="string">"userMap['one'].username"</span>/&gt;</pre>
</div>
<h2>5. 封装流程图</h2>
<div class="section">
<pre style="text-align: center; font-size: 1.1em;">
请求参数 → Action setter 方法 → 属性赋值
实现 ModelDriven → getModel() → 模型对象赋值
值栈 (Value Stack)</pre>
</div>
<div style="margin-top: 30px;">
<a href="/demo/upload" class="btn">下一节:文件上传 →</a>
<a href="/" class="btn" style="background: #764ba2;">← 返回首页</a>
</div>
</div>
</div>
</body>
</html>