Struts(5)——调用ServletAPI

Struts2 中有一个类,叫做ServletActionContext,它是Action的上下文,Struts2中的Action就通过它来访问原生Servlet的API。该类中封装了所有用于访问Servlet的方法:

1.static HttpServletResponse getResponse():获得HttpServletResponse对象;

2.static ServletContext getServletContext():获取web应用的上下文对象;

3.Map getSession():返回一个Map对象,该对象模拟了HttpSession实例;

4.Map getParameters():获得所有的请求参数,类似于HttpServletRequest的getPrameterMap();

5.static PageContext getPageContext():返回PageContext对象;

等等。。。

Struts2中访问ServletAPI 的关键在于ActionContext, ActionContext是一个Map类型的Class。它的生命周期取决于与之对应的request对象,它的每一次创建都是由于一个HTTPServletRequest创建的线程所启动的,请求完成之后销毁。

如何获得当前请求的ActionContext:将创建的ActionContext 绑定到当前线程,当然这不需要我们进行设计,这是Struts2设计好的,因而可以通过ThreadLocal获得。

下面详解访问ServletAPI的三种方式:

1.ActionContext

ActionContext ctx=ActionContext.getContext();
这里我们是有必要查看该方法的源码 
public static ActionContext getContext() {
    return (ActionContext)actionContext.get();
}
我们可以看到通过上述静态方法,获得了ActionContext对象

这里又指向了某个静态属性

static ThreadLocal<ActionContext> actionContext = new ThreadLocal();

补充一些ThreadLocal的知识点,ThreadLocal的翻译,我个人觉得比较合适的应该是“ 线程局部变量”,使得各线程能够各自保持一个独立的对象,它并非通过ThreadLocal.set()来实现,而是使用每个线程中的new方法创建对象。这个actionContext对象,就是一个典型。

接下来,假设我们要获取一个原生Session,那么

Map<String, Object> session = ctx.getSession();
需要记住,ActionContext本质的数据结构是Map类型,这意味着,getSession()的实现方式极有可能类似于Map中获取值的方式,源码如下:

public Map<String, Object> getSession() {
    return (Map)this.get("com.opensymphony.xwork2.ActionContext.session");
}
有意思的是,获取Request域对象的方法在形式上和原始的Map获取值的方法十分类似,

//获得request对象
Map<String, Object> request = (Map<String,Object>)ctx.get("request");
由于actionContext对象和request的生命周期一致,所以struts2并不推荐将属性放置到request中,直接放入actionContext似乎更为方便,如下:

ctx.put("attrName","attrValue");
在StrutsPreparedAndExcuteFilter中

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest)req;
    HttpServletResponse response = (HttpServletResponse)res;

    try {
        if (this.excludedPatterns != null && this.prepare.isUrlExcluded(request, this.excludedPatterns)) {
            chain.doFilter(request, response);
        } else {
            this.prepare.setEncodingAndLocale(request, response);
            this.prepare.createActionContext(request, response);
            this.prepare.assignDispatcherToThread();
 	    //此处对原生request对象进行了包装
            request = this.prepare.wrapRequest(request);
            ActionMapping mapping = this.prepare.findActionMapping(request, response, true);
            if (mapping == null) {
                boolean handled = this.execute.executeStaticResourceRequest(request, response);
                if (!handled) {
                    chain.doFilter(request, response);
                }
            } else {
                this.execute.executeAction(request, response, mapping);
            }
        }
    } finally {
        this.prepare.cleanupRequest(request);
    }

}

原生HttpServletRequest在这个Filter中被包装,以改变该域对象取值的位置,以便其搜寻ActionContext中的对象值,因而在取值时,和原来没有区别。

1.ServletContext

依然大致围观一下源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.struts2;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
//继承自ActionContext
public class ServletActionContext extends ActionContext implements StrutsStatics {
    private static final long serialVersionUID = -666854718275106687L;
    public static final String STRUTS_VALUESTACK_KEY = "struts.valueStack";
    public static final String ACTION_MAPPING = "struts.actionMapping";

    private ServletActionContext(Map context) {
        super(context);
    }

    public static ActionContext getActionContext(HttpServletRequest req) {
        ValueStack vs = getValueStack(req);
        return vs != null ? new ActionContext(vs.getContext()) : null;
    }

    public static ValueStack getValueStack(HttpServletRequest req) {
        return (ValueStack)req.getAttribute("struts.valueStack");
    }

    public static ActionMapping getActionMapping() {
        return (ActionMapping)ActionContext.getContext().get("struts.actionMapping");
    }

    public static PageContext getPageContext() {
        return (PageContext)ActionContext.getContext().get("com.opensymphony.xwork2.dispatcher.PageContext");
    }

    public static void setRequest(HttpServletRequest request) {
        ActionContext.getContext().put("com.opensymphony.xwork2.dispatcher.HttpServletRequest", request);
    }

    public static HttpServletRequest getRequest() {
        return (HttpServletRequest)ActionContext.getContext().get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
    }

    public static void setResponse(HttpServletResponse response) {
        ActionContext.getContext().put("com.opensymphony.xwork2.dispatcher.HttpServletResponse", response);
    }

    public static HttpServletResponse getResponse() {
        return (HttpServletResponse)ActionContext.getContext().get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
    }

    public static ServletContext getServletContext() {
        return (ServletContext)ActionContext.getContext().get("com.opensymphony.xwork2.dispatcher.ServletContext");
    }

    public static void setServletContext(ServletContext servletContext) {
        ActionContext.getContext().put("com.opensymphony.xwork2.dispatcher.ServletContext", servletContext);
    }
}
我们发现,首先它继承ActionContext,其次它本质上依然是通过调用ActionContext的方法来对ServletAPI进行访问,需要注意,它没有实现getSession方法,因为在获得原生request对象之后,调用request的getSession()方法即可。

3.实现接口

关于Servlet原生API的接口有ServletRequestAware、ServletResponseAware等等,通过实现接口,之后实现其接口方法,即可获取ServletAPI。

接口的功能实际上式通过Interceptor实现的,在struts-default.xml的配置中默认配置了20多个拦截器,其中有一个拦截器名为servletconfig,它的实现类为

package org.apache.struts2.interceptor
 

public String intercept(ActionInvocation invocation) throws Exception {
    Object action = invocation.getAction();
    ActionContext context = invocation.getInvocationContext();
    HttpServletRequest request;
    if (action instanceof ServletRequestAware) {
        request = (HttpServletRequest)context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
        ((ServletRequestAware)action).setServletRequest(request);
    }
通过ActionInvocation获得ActionContext然后去获取Servlet原生request,其他如response等等也是类似原理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值