让我们开始这篇关于Struts2框架入门的专业技术博客吧。

一、Struts2框架概述

Struts2是一个基于MVC设计模式的Web应用框架,它是Struts1的下一代产品。与Struts1相比,Struts2在架构上有了很大的改进,它采用了WebWork的核心技术,提供了更加灵活和强大的功能。

Struts2的核心思想是将请求处理过程分为几个清晰的层次:控制器(Action)、模型(业务逻辑)和视图(JSP等)。这种分离使得应用程序更易于维护和扩展。

技术栈说明:本文所有示例基于Java 8 + Struts2 2.5 + Tomcat 9环境。

二、Struts2核心配置详解

配置Struts2应用主要涉及三个核心文件:web.xml、struts.xml和struts.properties。让我们详细看看每个文件的配置方法。

  1. web.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <!-- 配置Struts2的核心过滤器 -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
  1. struts.xml配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
    "http://struts.apache.org/dtds/struts-2.5.dtd">
    
<struts>
    <!-- 开发模式,修改配置文件后不需要重启服务器 -->
    <constant name="struts.devMode" value="true" />
    
    <!-- 配置包,name属性任意但必须唯一 -->
    <package name="default" namespace="/" extends="struts-default">
        
        <!-- 配置Action -->
        <action name="hello" class="com.example.action.HelloAction">
            <!-- 配置结果映射 -->
            <result name="success">/hello.jsp</result>
        </action>
        
    </package>
</struts>

三、Action类开发实战

Action类是Struts2框架的核心组件,它负责处理用户请求并返回结果视图。下面我们通过一个完整的示例来演示如何开发Action类。

  1. 基本Action类示例:
package com.example.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * HelloAction示例类
 * 继承ActionSupport类可以获得一些常用功能
 */
public class HelloAction extends ActionSupport {
    
    private String message;  // 用于存储消息
    private String username; // 用于接收用户输入
    
    /**
     * 默认执行方法
     * @return 返回结果字符串,对应struts.xml中的result配置
     */
    public String execute() throws Exception {
        if(username == null || username.trim().equals("")) {
            message = "请输入用户名!";
            return INPUT;  // 返回输入页面
        }
        
        message = "你好, " + username + "! 欢迎使用Struts2!";
        return SUCCESS;  // 返回成功页面
    }
    
    // Getter和Setter方法
    public String getMessage() {
        return message;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getUsername() {
        return username;
    }
}
  1. 使用注解配置的Action类示例:
package com.example.action;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;

/**
 * 使用注解配置的UserAction类
 * 这种方式可以减少struts.xml的配置
 */
@Results({
    @Result(name="success", location="/user.jsp"),
    @Result(name="input", location="/userForm.jsp")
})
public class UserAction {
    
    private String userId;
    private String userName;
    
    @Action("/user/show")
    public String showUser() {
        // 业务逻辑代码
        return "success";
    }
    
    @Action("/user/save")
    public String saveUser() {
        // 保存用户逻辑
        return "success";
    }
    
    // Getter和Setter方法
    public String getUserId() {
        return userId;
    }
    
    public void setUserId(String userId) {
        this.userId = userId;
    }
    
    public String getUserName() {
        return userName;
    }
    
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

四、Struts2进阶特性

除了基本的Action开发,Struts2还提供了许多强大的特性,让我们看看其中几个重要的。

  1. 拦截器使用示例:
package com.example.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

/**
 * 自定义日志拦截器
 * 记录每个Action的执行时间
 */
public class LoggingInterceptor extends AbstractInterceptor {
    
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        long startTime = System.currentTimeMillis();
        
        // 执行Action
        String result = invocation.invoke();
        
        long endTime = System.currentTimeMillis();
        String actionName = invocation.getAction().getClass().getName();
        
        System.out.println("Action " + actionName + " 执行时间: " 
            + (endTime - startTime) + "ms");
            
        return result;
    }
}

在struts.xml中配置拦截器:

<package name="secured" extends="default">
    
    <!-- 定义拦截器栈 -->
    <interceptors>
        <interceptor name="logger" class="com.example.interceptor.LoggingInterceptor"/>
        
        <!-- 自定义拦截器栈 -->
        <interceptor-stack name="myStack">
            <interceptor-ref name="logger"/>
            <interceptor-ref name="defaultStack"/>
        </interceptor-stack>
    </interceptors>
    
    <!-- 设置默认拦截器栈 -->
    <default-interceptor-ref name="myStack"/>
    
    <action name="secure" class="com.example.action.SecureAction">
        <result>/secure.jsp</result>
    </action>
</package>
  1. 验证框架示例:
package com.example.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 使用验证框架的RegisterAction
 */
public class RegisterAction extends ActionSupport {
    
    private String username;
    private String password;
    private String confirmPassword;
    private String email;
    
    /**
     * 验证方法
     */
    public void validate() {
        if(username == null || username.trim().isEmpty()) {
            addFieldError("username", "用户名不能为空");
        }
        
        if(password == null || password.trim().isEmpty()) {
            addFieldError("password", "密码不能为空");
        } else if(!password.equals(confirmPassword)) {
            addFieldError("confirmPassword", "两次输入的密码不一致");
        }
        
        if(email == null || !email.matches("[\\w\\.-]+@[\\w\\.-]+\\.[\\w\\.-]+")) {
            addFieldError("email", "请输入有效的电子邮件地址");
        }
    }
    
    public String execute() {
        // 注册逻辑
        return SUCCESS;
    }
    
    // Getter和Setter方法
    // ...
}

五、应用场景与技术分析

Struts2适合开发中大型的Web应用程序,特别是那些需要严格遵循MVC模式的项目。它的主要应用场景包括:

  1. 企业级Web应用开发
  2. 需要复杂表单处理的系统
  3. 需要高度可配置和可扩展的项目
  4. 需要与多种视图技术集成的应用

技术优点:

  • 清晰的MVC分离
  • 强大的拦截器机制
  • 丰富的标签库
  • 灵活的配置方式
  • 良好的国际化和验证支持

技术缺点:

  • 学习曲线相对较陡
  • 配置相对复杂
  • 性能不如一些新兴框架
  • 社区活跃度有所下降

注意事项:

  1. 安全性:Struts2历史上出现过一些安全漏洞,务必使用最新版本
  2. 性能:对于高并发场景需要合理配置和优化
  3. 拦截器顺序:拦截器的执行顺序很重要,需要仔细设计
  4. 线程安全:Action类默认是原型模式(每次请求创建新实例),但要注意共享资源的线程安全

六、总结

Struts2作为一个成熟的MVC框架,虽然现在可能不是最热门的选择,但它仍然是一个强大且功能完备的解决方案。通过本文的介绍,你应该已经掌握了Struts2的核心配置和Action开发的基本方法。在实际项目中,建议结合具体需求选择合适的框架,Struts2特别适合那些需要严格分层和复杂业务逻辑处理的企业级应用。

记住,框架只是工具,最重要的是理解其设计思想和工作原理。Struts2的许多概念,如拦截器、值栈等,在其他框架中也有类似实现。掌握了这些核心概念,学习其他框架也会事半功倍。