首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Struts 2 檔案上傳、多檔上傳、自定義攔截器與驗證完整指南

     編輯:Java 程式設計入門

前言

Struts 2 透過攔截器機制內建檔案上傳、參數封裝、驗證等功能。本文系統整理:單檔/多檔上傳配置、自定義權限攔截器、手動驗證與 XML 驗證兩種模式,並釐清常見坑點。

一、存取 Scope 屬性

public String scope() {
    ActionContext ctx = ActionContext.getContext();
    ctx.getApplication().put("app", "應用範圍");  // ServletContext
    ctx.getSession().put("ses", "Session 範圍");  // HttpSession
    ctx.put("req", "Request 範圍");              // HttpServletRequest
    return "scope";
}

JSP 取值:${applicationScope.app}、${sessionScope.ses}、${requestScope.req}。

二、取得原生 Servlet API 物件

方式 1:ServletActionContext 靜態方法

HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext servletContext = ServletActionContext.getServletContext();
HttpSession session = request.getSession();

方式 2:實作 Aware 介面(DI 注入)

public class MyAction implements ServletRequestAware, ServletResponseAware, ServletContextAware {
    private HttpServletRequest request;
    private HttpServletResponse response;
    private ServletContext servletContext;

    @Override public void setServletRequest(HttpServletRequest request) { this.request = request; }
    @Override public void setServletResponse(HttpServletResponse response) { this.response = response; }
    @Override public void setServletContext(ServletContext context) { this.servletContext = context; }
}

推薦方式 2,利於單元測試(可注入 Mock 物件)。

三、單檔上傳

1. 依賴

<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency>

2. JSP 表單

<form action="${pageContext.request.contextPath}/upload.action" method="post" enctype="multipart/form-data">
    <input type="file" name="uploadImage" />
    <input type="submit" value="上傳" />
</form>

3. Action 屬性命名規則

private File uploadImage;                 // 檔案內容(臨時檔)
private String uploadImageContentType;    // MIME 類型
private String uploadImageFileName;       // 原始檔名
// getter/setter 省略

屬性名稱 = 表單 name + ContentType/FileName。

4. 儲存邏輯

public String upload() {
    String saveDir = ServletActionContext.getServletContext().getRealPath("/images");
    File dir = new File(saveDir);
    if (!dir.exists()) dir.mkdirs();
    File dest = new File(dir, uploadImageFileName);
    FileUtils.copyFile(uploadImage, dest);  // commons-io
    return "success";
}

四、多檔上傳

表單同名 name="uploadImages" 多個 <input type="file">,Action 改用陣列:

private File[] uploadImages;
private String[] uploadImagesContentType;
private String[] uploadImagesFileName;

public String upload() {
    String saveDir = ServletActionContext.getServletContext().getRealPath("/images");
    File dir = new File(saveDir);
    if (!dir.exists()) dir.mkdirs();
    for (int i = 0; i < uploadImages.length; i++) {
        FileUtils.copyFile(uploadImages[i], new File(dir, uploadImagesFileName[i]));
    }
    return "success";
}

五、自定義攔截器

1. 實作 Interceptor 介面

public class PermissionInterceptor implements Interceptor {
    @Override public void init() {}
    @Override public void destroy() {}

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        HttpSession session = ServletActionContext.getRequest().getSession();
        if (session.getAttribute("user") != null) {
            return invocation.invoke();  // 通過
        }
        return "logon";  // 重導登入
    }
}

2. struts.xml 註冊並組合 defaultStack

<package name="demo" namespace="/" extends="struts-default">
    <interceptors>
        <interceptor name="permission" class="com.demo.PermissionInterceptor" />
        <interceptor-stack name="permissionStack">
            <interceptor-ref name="defaultStack" />   <!-- 必須包含,否則失去檔案上傳、驗證等功能 -->
            <interceptor-ref name="permission" />
        </interceptor-stack>
    </interceptors>

    <default-interceptor-ref name="permissionStack" />  <!-- 整包預設 -->

    <action name="upload" class="com.demo.UploadAction">
        <result>/success.jsp</result>
        <result name="input">/upload.jsp</result>  <!-- 驗證失敗導向 -->
    </action>
</package>

關鍵:自定義攔截器必須引用 defaultStack,否則檔案上傳、參數封裝、驗證等核心功能失效。

六、驗證機制

1. 程式碼驗證(繼承 ActionSupport)

  • validate():驗證所有 execute() 同簽名方法。
  • validateXxx():僅驗證 xxx() 方法(Xxx 首字母大寫)。
public void validate() {
    if (mobile == null || mobile.trim().isEmpty()) {
        addFieldError("mobile", "手機號不可為空");
    } else if (!mobile.matches("^1[358]\\d{9}$")) {
        addFieldError("mobile", "手機號格式錯誤");
    }
}

public void validateAdd() {  // 僅驗證 add() 方法
    if (username == null || username.trim().isEmpty()) {
        addFieldError("username", "用戶名不可為空");
    }
}

驗證失敗自動導向 name="input" 的 Result,JSP 用 <s:fielderror/> 顯示。

2. XML 驗證(ActionClassName-validation.xml)

檔案置於 Action 同包,命名 UserAction-validation.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN"
    "https://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<validators>
    <field name="username">
        <field-validator type="requiredstring">
            <param name="trim">true</param>
            <message>用戶名不可為空</message>
        </field-validator>
    </field>
    <field name="email">
        <field-validator type="email">
            <message>Email 格式錯誤</message>
        </field-validator>
    </field>
</validators>

常用驗證器:requiredstring、int、double、date、email、url、regex、stringlength。

七、驗證流程順序

  1. 類型轉換(字串 → 目標型別),失敗由 conversionError 攔截器收集。
  2. 呼叫 validateXxx()(若存在)。
  3. 呼叫 validate()。
  4. 若 fieldErrors 不為空 → 導向 input Result;否則執行 Action 方法。

常見坑點總結

  • 上傳大小限制:struts.multipart.maxSize(預設 2MB),需在 struts.xml 或 struts.properties 調大。
  • 臨時檔清理:上傳失敗/例外時,Struts 2 不會自動刪除臨時檔,建議在 finally 或攔截器中清理。
  • 驗證國際化:<message key="error.username.required"/> 配合資源檔。
  • 攔截器順序:defaultStack 內順序固定,自定義攔截器置於最後執行業務邏輯前。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved