访问 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();
    }
}
 
 
以上都是单步调试看到的,

转载于:https://www.cnblogs.com/lflx/p/4398060.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值