访问 web 资源

Servlet API解耦的访问方式 
 
为了避免与 Servlet API 耦合在一起, 方便 Action 做单元测试, Struts2 对 HttpServletRequest, HttpSession 和 ServletContext 进行了封装, 构造了 3 个 Map 对象来替代这 3 个对象, 在 Action 中可以直接使用 HttpServletRequest, HttpServletSession, ServletContext 对应的 Map 对象来保存和读取数据. 
 
I:通过 ActionContext 访问 Web 资源
 
ActionContext 是 Action 执行的上下文对象, 在 ActionContext 中保存了 Action 执行所需要的所有对象, 包括 parameters, request, session, application 等.
获取 HttpSession 对应的 Map 对象:    
public Map getSession()
获取 ServletContext 对应的 Map 对象:
public Map getApplication()
获取请求参数对应的 Map 对象:
public Map getParameters()
获取 HttpServletRequest 对应的 Map 对象:
public Object get(Object key): ActionContext 类中没有提供类似 getRequest() 这样的方法来获取 HttpServletRequest 对应的 Map 对象. 要得到 HttpServletRequest 对应的 Map 对象, 可以通过为 get() 方法传递 “request” 参数实现
 
 
II:通过实现 Aware 接口访问 Web 资源
 
ction 类通过可以实现某些特定的接口, 让 Struts2 框架在运行时向 Action 实例注入 parameters, request, session 和 application 对应的 Map 对象: 
Servlet 耦合的访问方式 API
 
直接访问 Servlet API 将使 Action 与 Servlet 环境耦合在一起,  测试时需要有 Servlet 容器, 不便于对 Action 的单元测试.
直接获取 HttpServletRequest 对象:
ServletActionContext.getRequest()
直接获取 HttpSession 对象
ServletActionContext.getRequest().getSession()
直接获取 ServletContext 对象
ServletActionContext.getServletContext()

通过实现 ServletRequestAware, ServletContextAware 等接口的方式
 
 
不推荐使用耦合的访问方式 特殊情况下需要使用Servlet API 的时候可以通过ServletActionContext.getXXX()的方式
 
Dispatcher管理调度 装配默认设置等等
 
public class Dispatcher {
//程序读取默认配置文件的顺序
private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml" ;
     //读取设置配置参数
 private void init_TraditionalXmlConfigurations() {
        String configPaths = initParams.get("config" );
        if (configPaths == null) {
            configPaths = DEFAULT_CONFIGURATION_PATHS;
        }
        String[] files = configPaths.split("\\s*[,]\\s*" );
        for (String file : files) {
            if (file.endsWith(".xml" )) {
                if ("xwork.xml" .equals(file)) {
                  configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false));
                } else { //在这里设置基本配置
configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
                }
            } else {
               
            }
        }
    }
public Map<String,Object> createContextMap(HttpServletRequest request, HttpServletResponse response,
            ActionMapping mapping, ServletContext context) {
 
      //使用包装的模式把request对象包装成一个Map集合 可以去看RequestMap的实现源码
        Map requestMap = new RequestMap(request);
        Map params = new HashMap(request.getParameterMap());
        Map session = new SessionMap(request); 
        Map application = new ApplicationMap(context); 
        //extraContext 把所有的Servlet的APi封装成一个Map中后,再放入到一个大的map中
        Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);
        if (mapping != null) {
          //
            extraContext.put(ServletActionContext.ACTION_MAPPING , mapping);
        }
        return extraContext;
    }
 
 public HashMap<String,Object> createContextMap(Map requestMap,
                                    Map parameterMap,
                                    Map sessionMap,
                                    Map applicationMap,
                                    HttpServletRequest request,
                                    HttpServletResponse response,
                                    ServletContext servletContext) {
        HashMap<String,Object> extraContext = new HashMap<String,Object>();
        extraContext.put(ActionContext. PARAMETERS, new HashMap(parameterMap));
        extraContext.put(ActionContext. SESSION, sessionMap);
        extraContext.put(ActionContext. APPLICATION, applicationMap);
 
        Locale locale;
        if (defaultLocale != null) {
            locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
        } else {
            locale = request.getLocale();
        }
 
        extraContext.put(ActionContext. LOCALE, locale);
 
       // String HTTP_REQUEST ="com.opensymphony.xwork2.dispatcher.HttpServletRequest"
     在ognl的值栈中可以看到 
 
        //有xwork包装后的HttpServletRequest
        extraContext.put(StrutsStatics. HTTP_REQUEST, request);
        extraContext.put(StrutsStatics. HTTP_RESPONSE, response);
        extraContext.put(StrutsStatics. SERVLET_CONTEXT, servletContext);
 
        //这个Map的方式访问对象
        extraContext.put( "request", requestMap);
        extraContext.put( "session", sessionMap);
        extraContext.put( "application", applicationMap);
        extraContext.put( "parameters", parameterMap);
      //把所有访问对象放入一个attr为key的map集合中去,(这也就是为什么我们可以用attr的方式访问域的对象值还有默认的搜索的顺序request,session,application,parameters)
        AttributeMap attrMap = new AttributeMap(extraContext);
        extraContext.put( "attr", attrMap);
 
        return extraContext;
    }
 
//包装request 成一个Map的结构,事实还是一个request对象进行操作
public class RequestMap extends AbstractMap implements Serializable {
 
    private static final long serialVersionUID = -7675640869293787926L;
 
    private Set<Object> entries;
    private HttpServletRequest request 
    public RequestMap( final HttpServletRequest request) {
        this.request = request;
    }
  
    public Object get(Object key) {
        return request .getAttribute(key.toString());
    } 
    public Object put(Object key, Object value) {
        Object oldValue = get(key);
        entries = null;
        request.setAttribute(key.toString(), value);
        return oldValue;
    }
 
}
以上的执行都是在Struts 的StrutsPrepareAndExecuteFilter 过滤器中执行完成的还没有开始执行拦截器
 
当我们在一个action中实现了RequestAware的接口 在什么时候对我们的action实现注入Request的值呢?
 
这个注入在ServletConfigInterceptor拦截器中进行注入Request的 可以从源码中看到
 
public class ServletConfigInterceptor extends AbstractInterceptor implements StrutsStatics {
 
 //这里就实现了所有你实现的 有关Servlet的API的接口的注入到你的action中的对象中
 
    public String intercept(ActionInvocation invocation) throws Exception {
        final Object action = invocation.getAction();
        final ActionContext context = invocation.getInvocationContext();
          //判断是否实现了 ServletRequestAware接口
        if (action instanceof ServletRequestAware) {
            HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST );
            ((ServletRequestAware) action).setServletRequest(request);
        }
 
        if (action instanceof ServletResponseAware) {
            HttpServletResponse response = (HttpServletResponse) context.get(HTTP_RESPONSE );
            ((ServletResponseAware) action).setServletResponse(response);
        }
 
        if (action instanceof ParameterAware) {
            ((ParameterAware) action).setParameters((Map)context.getParameters());
        }
 
        if (action instanceof ApplicationAware) {
            ((ApplicationAware) action).setApplication(context.getApplication());
        }
       
        if (action instanceof SessionAware) {
            ((SessionAware) action).setSession(context.getSession());
        }
       
        if (action instanceof RequestAware) {
            ((RequestAware) action).setRequest((Map) context.get("request" ));
        }
 
        if (action instanceof PrincipalAware) {
            HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST );
            if(request != null) {
                
                ((PrincipalAware) action).setPrincipalProxy(new ServletPrincipalProxy(request));
            }
        }
        if (action instanceof ServletContextAware) {
            ServletContext servletContext = (ServletContext) context.get(SERVLET_CONTEXT );
            ((ServletContextAware) action).setServletContext(servletContext);
        }
        return invocation.invoke();
    }
}
 
 
以上都是单步调试看到的,
posted @ 2015-04-07 13:28  山寨少主  阅读(174)  评论(0编辑  收藏  举报