diff --git a/src/main/java/com/example/struts2/OgnlLabAction.java b/src/main/java/com/example/struts2/OgnlLabAction.java new file mode 100644 index 0000000..0a279d4 --- /dev/null +++ b/src/main/java/com/example/struts2/OgnlLabAction.java @@ -0,0 +1,71 @@ +package com.example.struts2; + +import com.opensymphony.xwork2.ActionSupport; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class OgnlLabAction extends ActionSupport { + private String keyword; + private Integer minAge; + private DemoUser user = new DemoUser(); + private List tags = new ArrayList<>(); + private List users; + private List filteredUsers; + + public String execute() { + loadUsers(); + filteredUsers = users; + return SUCCESS; + } + + public String bind() { + loadUsers(); + filteredUsers = users.stream() + .filter(u -> keyword == null || keyword.isBlank() || u.getName().contains(keyword) || u.getEmail().contains(keyword)) + .filter(u -> minAge == null || u.getAge() >= minAge) + .collect(Collectors.toList()); + return SUCCESS; + } + + private void loadUsers() { + users = Arrays.asList( + new DemoUser("张三", "zhangsan@example.com", 22), + new DemoUser("李四", "lisi@example.com", 28), + new DemoUser("王五", "wangwu@example.com", 34), + new DemoUser("赵六", "zhaoliu@example.com", 19) + ); + } + + public static class DemoUser { + private String name; + private String email; + private Integer age; + + public DemoUser() {} + public DemoUser(String name, String email, Integer age) { + this.name = name; + this.email = email; + this.age = age; + } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public Integer getAge() { return age; } + public void setAge(Integer age) { this.age = age; } + } + + public String getKeyword() { return keyword; } + public void setKeyword(String keyword) { this.keyword = keyword; } + public Integer getMinAge() { return minAge; } + public void setMinAge(Integer minAge) { this.minAge = minAge; } + public DemoUser getUser() { return user; } + public void setUser(DemoUser user) { this.user = user; } + public List getTags() { return tags; } + public void setTags(List tags) { this.tags = tags; } + public List getUsers() { return users; } + public List getFilteredUsers() { return filteredUsers; } +} diff --git a/src/main/resources/struts.xml b/src/main/resources/struts.xml index d944f02..101265e 100644 --- a/src/main/resources/struts.xml +++ b/src/main/resources/struts.xml @@ -64,6 +64,14 @@ /interceptor-demo.jsp + + + /ognl-lab.jsp + + + + /ognl-lab.jsp + diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index eb15fc8..a3978af 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -61,6 +61,11 @@

从列表页到表单页,再到新增/编辑/删除,形成完整的 Struts2 业务流学习闭环。

进入 CRUD +
+

🧪 OGNL / 参数绑定实验

+

可视化体验普通字段、嵌套对象、多选列表是如何被 Struts2 自动绑定到 Action 的。

+ 进入实验室 +
diff --git a/src/main/webapp/interceptor-demo.jsp b/src/main/webapp/interceptor-demo.jsp index 4085245..20f6f08 100644 --- a/src/main/webapp/interceptor-demo.jsp +++ b/src/main/webapp/interceptor-demo.jsp @@ -53,10 +53,29 @@

🔗 拦截器链演示

当前使用: customStack (日志 + 计时 + 监控 + 默认栈)

- 使用 API 限流栈 + 切换到 API 限流栈 + 恢复默认栈

API 栈包含: 日志 + 限流 + 验证 + 计时 + 默认栈

+ + + + + + + +
拦截器作用你应该观察什么
LoggingInterceptor记录请求进入/退出看日志顺序,理解责任链
TimingInterceptor统计执行耗时看 executionTime 如何注入 request
MonitorInterceptor累积 Action 调用统计连续刷新看调用数增长
RateLimitInterceptor限制频率API 栈里观察限流触发
ValidationInterceptor校验输入思考错误应该在哪一层拦截
+
+

🧪 快速实验建议

+
    +
  • 先刷新当前页两次,看调用统计是否增加
  • +
  • 再切到 interceptor_api,对比多了哪些拦截器
  • +
  • 观察“先进入后退出”的洋葱模型
  • +
  • 思考:如果你要加鉴权,应放在哪个拦截器位置最合理?
  • +
+
+

📚 拦截器执行顺序

diff --git a/src/main/webapp/learn.jsp b/src/main/webapp/learn.jsp
index 20ec3ff..878a788 100644
--- a/src/main/webapp/learn.jsp
+++ b/src/main/webapp/learn.jsp
@@ -62,6 +62,11 @@
             

通过用户管理体验列表页、表单页、重定向和状态更新。

打开用户管理
+
+

🧪 OGNL / 参数绑定实验

+

通过真正可交互的表单观察 Struts2 的字段绑定、嵌套对象绑定和集合绑定。

+ 打开 OGNL 实验室 +

📚 学习路径

diff --git a/src/main/webapp/ognl-lab.jsp b/src/main/webapp/ognl-lab.jsp new file mode 100644 index 0000000..fa58335 --- /dev/null +++ b/src/main/webapp/ognl-lab.jsp @@ -0,0 +1,83 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + OGNL / 参数绑定实验室 - Struts2 + + + +

🧪 OGNL / 参数绑定实验室

+ +
+ 实验任务卡 +
    +
  • 输入关键字和最小年龄,观察 Struts2 如何自动绑定请求参数到 Action 字段
  • +
  • 注意 keywordminAgeuser.name 这类命名会如何映射
  • +
  • 观察页面里 <s:property><s:iterator> 如何读取 Action 中的数据
  • +
+
+ +
+

参数过滤实验

+ +
+ + +
+
+ + +
+ +
+
+ +
+

绑定结果观察

+

keyword =

+

minAge =

+

user.name =

+

tags =

+
+ +
+

过滤后的用户列表

+ + + + + + + + + +
姓名邮箱年龄
+
+ +
+

学习点

+
    +
  • keyword → 直接绑定到 Action 同名字段
  • +
  • user.name → 绑定到嵌套对象属性
  • +
  • tags → 多选值绑定到 List<String>
  • +
  • <s:iterator> 会遍历 Action 暴露出来的集合
  • +
+
+ +

← 返回学习中心

+ +