0%

struts2访问web资源

Struts2 访问 Web 资源的两种方式详解

在 Struts2 框架中,Web 资源(如HttpServletRequestHttpSessionServletContext等)的访问方式分为与 Servlet API 解耦与 Servlet API 耦合两种。两种方式各有适用场景,下面详细解析其实现方式与使用场景。

与 Servlet API 解耦的方式

这种方式通过 Struts2 封装的 API 访问 Web 资源,不直接依赖 Servlet 原生类,便于进行单元测试,适合大多数业务场景。

1. 使用 ActionContext(核心方式)

ActionContext是 Struts2 的上下文对象,封装了当前请求的所有信息,可通过它间接访问 Web 资源对应的 Map 对象。

核心方法与示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import com.opensymphony.xwork2.ActionContext;
import java.util.Map;

public class UserAction {
public String execute() {
// 获取ActionContext实例(单例,与当前请求绑定)
ActionContext actionContext = ActionContext.getContext();

// 1. 获取application域(对应ServletContext)
Map<String, Object> applicationMap = actionContext.getApplication();
applicationMap.put("appKey", "全局应用数据"); // 存储数据
Object appValue = applicationMap.get("appKey"); // 获取数据

// 2. 获取session域
Map<String, Object> sessionMap = actionContext.getSession();
sessionMap.put("userName", "张三"); // 存储用户会话数据
Object user = sessionMap.get("userName");

// 3. 获取request域(需通过"request"键获取,Struts2未直接提供getRequest()方法)
Map<String, Object> requestMap = (Map<String, Object>) actionContext.get("request");
requestMap.put("msg", "请求数据");
Object msg = requestMap.get("msg");

// 4. 获取请求参数(封装为Map,键是参数名,值是参数值数组)
Map<String, Object> params = actionContext.getParameters();
String[] ids = (String[]) params.get("id"); // 适用于多值参数
String name = (String) params.get("name"); // 单值参数

return "success";
}
}
特点:
  • 间接访问:通过Map对象模拟 Servlet 域对象,操作方式与原生 API 类似;
  • 线程安全ActionContext与当前请求绑定,线程安全;
  • 局限性:无法调用 Servlet 原生方法(如request.getHeader())。

2. 实现 XxxAware 接口(依赖注入方式)

Struts2 提供了一系列Aware接口,通过依赖注入(DI)方式将 Web 资源的 Map 对象注入 Action,更符合面向接口编程思想。

常用接口与示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;
import java.util.Map;

// 实现接口,通过setter方法注入对应Map
public class TestAwareAction implements ApplicationAware, SessionAware, RequestAware {
// 注入的application域Map
private Map<String, Object> application;
// 注入的session域Map
private Map<String, Object> session;
// 注入的request域Map
private Map<String, Object> request;

// 实现ApplicationAware接口的方法
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}

// 实现SessionAware接口的方法
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}

// 实现RequestAware接口的方法
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
}

public String execute() {
// 使用注入的Map操作Web资源
application.put("appKey", "通过Aware注入的全局数据");
session.put("userId", "1001");
request.put("pageNum", 1);
return "success";
}
}
特点:
  • 依赖注入:Struts2 在创建 Action 时自动注入 Map 对象,无需手动获取;
  • 代码清晰:通过接口明确声明依赖的资源,可读性强;
  • 适用场景:适合中型项目,平衡了封装性与易用性。

与 Servlet API 耦合的方式

这种方式直接使用 Servlet 原生 API(如HttpServletRequestHttpServletResponse),可调用所有原生方法,适合需要深度操作 Web 资源的场景(如文件上传、设置响应头)。

1. 使用 ServletActionContext(工具类方式)

ServletActionContext是 Struts2 提供的工具类,直接暴露 Servlet 原生对象,是访问原生 API 的便捷方式。

核心方法与示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletContext;

public class TestServletActionContextAction {
public String execute() {
// 1. 获取HttpServletRequest对象
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("msg", "原生request数据");
String ip = request.getRemoteAddr(); // 调用原生方法(获取客户端IP)

// 2. 获取HttpServletResponse对象
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("text/html;charset=UTF-8"); // 设置响应编码
response.setHeader("Cache-Control", "no-cache"); // 设置响应头

// 3. 获取HttpSession对象(两种方式)
HttpSession session = request.getSession(); // 方式1:通过request获取
HttpSession session2 = ServletActionContext.getRequest().getSession(); // 方式2:直接获取
session.setAttribute("user", new User("李四"));

// 4. 获取ServletContext对象
ServletContext application = ServletActionContext.getServletContext();
application.setAttribute("appName", "Struts2应用");
String realPath = application.getRealPath("/"); // 获取应用真实路径

return "success";
}
}
特点:
  • 直接操作原生对象:支持所有 Servlet API 方法,功能完整;
  • 静态方法调用:通过ServletActionContext的静态方法直接获取,代码简洁;
  • 耦合性高:依赖 Servlet API,单元测试需依赖容器(如 Spring TestContext)。

2. 实现 ServletXxxAware 接口(注入原生对象)

通过实现 Struts2 的ServletXxxAware接口,可直接注入 Servlet 原生对象,适合需要长期持有原生对象的场景。

常用接口与示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletContext;

public class TestServletAwareAction implements ServletRequestAware, ServletResponseAware, ServletContextAware {
// 注入的原生对象
private HttpServletRequest request;
private HttpServletResponse response;
private ServletContext application;

// 实现ServletRequestAware接口
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}

// 实现ServletResponseAware接口
@Override
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}

// 实现ServletContextAware接口
@Override
public void setServletContext(ServletContext application) {
this.application = application;
}

public String execute() {
// 使用原生对象操作
request.setAttribute("data", "通过Aware注入的request数据");
response.setStatus(200); // 设置响应状态码
application.log("操作日志:用户访问了资源"); // 调用ServletContext的日志方法
return "success";
}
}
特点:
  • 对象持久化:原生对象通过成员变量持有,可在 Action 的多个方法中复用;
  • 功能完整:支持所有原生方法,适合复杂 Web 操作(如文件下载、Cookie 处理);
  • 侵入性强:Action 与 Servlet API 强耦合,灵活性较低。

两种方式的对比与选择建议

维度 与 Servlet API 解耦方式(ActionContext/Aware 接口) 与 Servlet API 耦合方式(ServletActionContext/ServletXxxAware)
依赖关系 依赖 Struts2 封装的 Map,不依赖 Servlet 原生类 直接依赖 Servlet API(如HttpServletRequest
功能完整性 支持基本操作(存 / 取数据),不支持原生方法 支持所有 Servlet API 方法,功能完整
单元测试难度 易(可模拟 Map 对象) 难(需依赖 Servlet 容器)
代码侵入性 低(通过 Struts2 API 操作) 高(直接使用 Servlet 类)
适用场景 大多数业务逻辑(数据存储、参数获取) 复杂 Web 操作(文件上传、响应头设置、Cookie 处理等)

选择建议:

  1. 优先使用解耦方式:对于简单的数据存储与获取,推荐使用ActionContextXxxAware接口,降低框架耦合度,便于测试;
  2. 必要时使用耦合方式:当需要调用 Servlet 原生方法(如getHeader()setContentType())时,使用ServletActionContextServletXxxAware接口;
  3. 混合使用注意事项:两种方式可共存,但需注意数据同步(如通过ActionContextsessionMap存储的数据,可通过原生HttpSession获取,两者本质是同一数据)。

常见问题与解决方案

  1. request 对象获取方式差异
    解耦方式中,ActionContext没有直接提供getRequest()方法,需通过actionContext.get("request")获取 Map 对象;耦合方式中可直接通过ServletActionContext.getRequest()获取原生HttpServletRequest
  2. 参数获取的注意事项
    解耦方式中,actionContext.getParameters()返回的是Map<String, Object>,其中多值参数(如复选框)的值是String[]类型,需强制转换;耦合方式中request.getParameterValues()更直观。
  3. 线程安全问题
    两种方式均线程安全,ActionContextServletActionContext的对象与当前请求绑定,不会出现线程干扰

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10