feat: expand struts demo lab

This commit is contained in:
Codex
2026-03-18 18:12:20 +08:00
parent 1f60832445
commit fba7b0497f
25 changed files with 1847 additions and 1447 deletions

View File

@@ -0,0 +1,48 @@
package com.demo.action;
import com.demo.model.User;
import com.opensymphony.xwork2.ActionSupport;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
public class AjaxAction extends ActionSupport {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private boolean success;
private String message;
private String serverTime;
private List<User> users;
@Override
public String execute() {
success = true;
message = "Mock AJAX response generated from the Struts2 action.";
serverTime = LocalDateTime.now().format(TIME_FORMATTER);
users = Arrays.asList(
new User(1L, "ops-admin", "ops-admin@example.com", "13800000001"),
new User(2L, "platform-owner", "platform-owner@example.com", "13800000002"),
new User(3L, "release-manager", "release-manager@example.com", "13800000003")
);
return SUCCESS;
}
public boolean isSuccess() {
return success;
}
public String getMessage() {
return message;
}
public String getServerTime() {
return serverTime;
}
public List<User> getUsers() {
return users;
}
}

View File

@@ -0,0 +1,93 @@
package com.demo.action;
import com.opensymphony.xwork2.ActionSupport;
import java.io.File;
import java.util.List;
public class FileUploadAction extends ActionSupport {
private File upload;
private String uploadFileName;
private String uploadContentType;
private List<File> uploads;
private List<String> uploadsFileName;
private List<String> uploadsContentType;
private int fileCount;
private String summary;
@Override
public String execute() {
fileCount = 0;
if (upload != null) {
fileCount++;
}
if (uploads != null) {
fileCount += uploads.size();
}
if (fileCount == 0) {
addActionError("Select at least one file before submitting the demo.");
return INPUT;
}
summary = "This demo captures upload metadata only. It does not persist files to disk, which keeps the sample safe for classroom use.";
return SUCCESS;
}
public File getUpload() {
return upload;
}
public void setUpload(File upload) {
this.upload = upload;
}
public String getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
public String getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public List<File> getUploads() {
return uploads;
}
public void setUploads(List<File> uploads) {
this.uploads = uploads;
}
public List<String> getUploadsFileName() {
return uploadsFileName;
}
public void setUploadsFileName(List<String> uploadsFileName) {
this.uploadsFileName = uploadsFileName;
}
public List<String> getUploadsContentType() {
return uploadsContentType;
}
public void setUploadsContentType(List<String> uploadsContentType) {
this.uploadsContentType = uploadsContentType;
}
public int getFileCount() {
return fileCount;
}
public String getSummary() {
return summary;
}
}

View File

@@ -2,33 +2,50 @@ package com.demo.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* Hello World 示例 Action
* 展示 Struts2 最基础的 Action 写法
*
* ActionSupport 提供了:
* - validate() 方法用于表单验证
* - getText() 方法用于国际化
* - addActionError()/addFieldError() 用于错误消息
*/
public class HelloAction extends ActionSupport {
private String name;
private String message;
private String tip;
private String nextStep;
private String requestSample;
@Override
public String execute() throws Exception {
// 业务逻辑
public String execute() {
if (name == null || name.trim().isEmpty()) {
name = "World";
} else {
name = name.trim();
}
message = "Hello, " + name + "! 欢迎学习 Struts2!";
message = "Hello, " + name + "! Welcome to the Struts2 demo lab.";
tip = "Struts2 injected the request parameter into the action property before execute() ran.";
nextStep = "Try the login flow or open the demo catalog to compare different action patterns.";
requestSample = "/hello?name=Platform%20Team";
return SUCCESS;
}
// Getter/Setter (Struts2 需要这些来获取/设置参数)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public String getTip() {
return tip;
}
public String getNextStep() {
return nextStep;
}
public String getRequestSample() {
return requestSample;
}
}

View File

@@ -2,46 +2,92 @@ package com.demo.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* 用户登录 Action
* 展示:
* - 表单参数接收
* - 数据验证
* - Session 使用
* - 返回不同结果
*/
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LoginAction extends ActionSupport {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private String username;
private String password;
private String displayName;
private String role;
private String loginTime;
private String recommendation;
@Override
public String execute() throws Exception {
// 模拟登录验证
if ("admin".equals(username) && "123456".equals(password)) {
// 登录成功,设置 session
return SUCCESS;
} else if (username != null && !username.isEmpty()) {
// 登录失败
addActionError("用户名或密码错误!");
public String execute() {
username = normalize(username);
password = normalize(password);
if (!hasSubmitted()) {
return INPUT;
}
if ("admin".equals(username) && "123456".equals(password)) {
displayName = "System Demo Admin";
role = "Administrator";
loginTime = LocalDateTime.now().format(TIME_FORMATTER);
recommendation = "Continue with the user form, validation sample, or upload flow to explore the rest of the demo.";
return SUCCESS;
}
addActionError("Invalid demo credentials. Use admin / 123456.");
return INPUT;
}
// 表单验证
@Override
public void validate() {
if (username == null || username.trim().length() < 3) {
addFieldError("username", "用户名至少3个字符");
if (!hasSubmitted()) {
return;
}
if (username == null || username.length() < 3) {
addFieldError("username", "Username must be at least 3 characters.");
}
if (password == null || password.length() < 6) {
addFieldError("password", "密码至少6个字符");
addFieldError("password", "Password must be at least 6 characters.");
}
}
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
private boolean hasSubmitted() {
return (username != null && !username.trim().isEmpty())
|| (password != null && !password.trim().isEmpty());
}
private String normalize(String value) {
return value == null ? null : value.trim();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDisplayName() {
return displayName;
}
public String getRole() {
return role;
}
public String getLoginTime() {
return loginTime;
}
public String getRecommendation() {
return recommendation;
}
}

View File

@@ -0,0 +1,84 @@
package com.demo.action;
import com.opensymphony.xwork2.ActionSupport;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class UserAction extends ActionSupport {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private String username;
private String email;
private String phone;
private String submittedAt;
private String profileStage;
public String submit() {
username = normalize(username);
email = normalize(email);
phone = normalize(phone);
if (!isValid()) {
return INPUT;
}
submittedAt = LocalDateTime.now().format(TIME_FORMATTER);
profileStage = (phone != null && phone.length() >= 7) ? "Profile ready for follow-up demos." : "Profile captured. Add a stronger phone number next time.";
return SUCCESS;
}
private boolean isValid() {
boolean valid = true;
if (username == null || username.length() < 3) {
addFieldError("username", "Username must be at least 3 characters.");
valid = false;
}
if (email == null || !email.contains("@")) {
addFieldError("email", "Enter a valid email address.");
valid = false;
}
if (phone == null || phone.replaceAll("[^0-9]", "").length() < 7) {
addFieldError("phone", "Enter at least 7 digits for the phone number.");
valid = false;
}
return valid;
}
private String normalize(String value) {
return value == null ? null : value.trim();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSubmittedAt() {
return submittedAt;
}
public String getProfileStage() {
return profileStage;
}
}

View File

@@ -0,0 +1,88 @@
package com.demo.action;
import com.opensymphony.xwork2.ActionSupport;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ValidationAction extends ActionSupport {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private String username;
private String email;
private Integer age;
private String bio;
private String scoreBand;
private String submittedAt;
@Override
public String execute() {
username = normalize(username);
email = normalize(email);
bio = normalize(bio);
scoreBand = age >= 30 ? "Mid-career operator profile" : "Early-career operator profile";
submittedAt = LocalDateTime.now().format(TIME_FORMATTER);
return SUCCESS;
}
@Override
public void validate() {
if (username == null || username.trim().length() < 3 || username.trim().length() > 20) {
addFieldError("username", "Username must be between 3 and 20 characters.");
}
if (email == null || !email.contains("@") || email.indexOf('@') == email.length() - 1) {
addFieldError("email", "Enter a valid email address.");
}
if (age == null || age < 18 || age > 60) {
addFieldError("age", "Age must be between 18 and 60.");
}
if (bio != null && bio.trim().length() > 240) {
addFieldError("bio", "Bio must stay under 240 characters.");
}
}
private String normalize(String value) {
return value == null ? null : value.trim();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
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 getBio() {
return bio;
}
public void setBio(String bio) {
this.bio = bio;
}
public String getScoreBand() {
return scoreBand;
}
public String getSubmittedAt() {
return submittedAt;
}
}

View File

@@ -0,0 +1,38 @@
package com.demo.action.rest;
import com.demo.model.User;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Arrays;
import java.util.List;
public class UserRestAction extends ActionSupport {
private boolean success;
private String message;
private List<User> users;
@Override
public String execute() {
success = true;
message = "REST-style demo payload";
users = Arrays.asList(
new User(101L, "alpha", "alpha@example.com", "13800001001"),
new User(102L, "beta", "beta@example.com", "13800001002"),
new User(103L, "gamma", "gamma@example.com", "13800001003")
);
return SUCCESS;
}
public boolean isSuccess() {
return success;
}
public String getMessage() {
return message;
}
public List<User> getUsers() {
return users;
}
}