前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >filter builder_苹果数据分析代码怎么看

filter builder_苹果数据分析代码怎么看

作者头像
全栈程序员站长
发布2022-09-22 21:42:35
3140
发布2022-09-22 21:42:35
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。 在FilterDispatcher中首先关注的方法是init()和doFilter(),两个有用的局部变量(或者状态)

代码语言:javascript
复制
private FilterConfig filterConfig;
protected Dispatcher dispatcher;

filterConfig用来向filter传递信息,提供了四个方法:

代码语言:javascript
复制
public abstract java.lang.String getFilterName();
public abstract javax.servlet.ServletContext getServletContext();
public abstract java.lang.String getInitParameter(java.lang.String arg0);
public abstract java.util.Enumeration getInitParameterNames();

dispatcher做了FilterDispatcher大部分的工作。 首先来看init方法:

代码语言:javascript
复制
    public void init(FilterConfig filterConfig) throws ServletException {
  
  
    	 this.filterConfig = filterConfig;
    	 //把filterConfig中的parameters和servletContext传递给new Dispatcher(filterConfig.getServletContext(), params)
        dispatcher = createDispatcher(filterConfig);
        //加载各种配置
        dispatcher.init();

        String param = filterConfig.getInitParameter("packages");
        String packages = DEFAULT_STATIC_PACKAGES;
        if (param != null) {
  
  
            packages = param + " " + packages;
        }
        this.pathPrefixes = parse(packages);
    }
代码语言:javascript
复制
   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  
  


        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        ServletContext servletContext = getServletContext();

        String timerKey = "FilterDispatcher_doFilter: ";
        try {
  
  
            UtilTimerStack.push(timerKey);
            request = prepareDispatcherAndWrapRequest(request, response);
            ActionMapping mapping;//ActionMapping有四个字段 method, name, namespace,params, result对应着XML配置文件
            try {
  
  
                //装配mappings
                mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
            } catch (Exception ex) {
  
  
                LOG.error("error getting ActionMapping", ex);
                dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
                return;
            }
             // 如果mapping是空的,则去找static的内容
            if (mapping == null) {
  
  

                String resourcePath = RequestUtils.getServletPath(request);

                if ("".equals(resourcePath) && null != request.getPathInfo()) {
  
  
                    resourcePath = request.getPathInfo();
                }

                if (serveStatic && resourcePath.startsWith("/struts")) {
  
  
                    findStaticResource(resourcePath, findAndCheckResources(resourcePath), request, response);
                } else {
  
  
                    // this is a normal request, let it pass through
                    chain.doFilter(request, response);
                }
                // The framework did its job here
                return;
            }
            //这个方法是关键
            dispatcher.serviceAction(request, response, servletContext, mapping);

        } finally {
  
  
            try {
  
  
                ActionContextCleanUp.cleanUp(req);
            } finally {
  
  
                UtilTimerStack.pop(timerKey);
            }
        }
    }

我们再来查看Dispatcher中的serviceAction。

代码语言:javascript
复制
   public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
                              ActionMapping mapping) throws ServletException {
  
  

        //创建上下文,extraContext中包括parameterMap, sessionMap, applicationMap, locale, request, response, servletContext等等
        Map<String, Object> extraContext = createContextMap(request, response, mapping, context);

        //如果request之前有value stack,则复制一个并把它放到上下文中。        
        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
        if (stack != null) {
  
  
            extraContext.put(ActionContext.VALUE_STACK, ValueStackFactory.getFactory().createValueStack(stack));
        }

        String timerKey = "Handling request from Dispatcher";
        try {
  
  
            UtilTimerStack.push(timerKey);
            String namespace = mapping.getNamespace();
            String name = mapping.getName();
            String method = mapping.getMethod();

            Configuration config = configurationManager.getConfiguration();
            //利用工厂方法新建一个ActionProxy,它提供诸多代理方法。
            ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                    namespace, name, extraContext, true, false);
            proxy.setMethod(method);
            request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

            // 如果mapping中定义了Result,则运行这个Result。Result还是非常值得一讲的
            if (mapping.getResult() != null) {
  
  
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            } else {
  
  
                //没有则运行execute,即调用Invocation.invoke()
                proxy.execute();
            }

            // If there was a previous value stack then set it back onto the request
            if (stack != null) {
  
  
                request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
            }
        } catch (ConfigurationException e) {
  
  
            LOG.error("Could not find action or result", e);
            sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
        } catch (Exception e) {
  
  
            throw new ServletException(e);
        } finally {
  
  
            UtilTimerStack.pop(timerKey);
        }
    }
代码语言:javascript
复制
public interface ActionProxy {
  
  

    /** 在所有的依赖都配置好调用,在DefaultActionProxyFactory.createActionProxy中使用 */
    void prepare() throws Exception;

    /** @return 返回所代理的对象 */
    Object getAction();

    /** @return 返回所代理的对象的名字 */
    String getActionName();

    /** @return ActionProxy产生所借助的ActionConfig */
    ActionConfig getConfig();

    /** 设置是否在运行完Action之后运行Action所返回的Result */
    void setExecuteResult(boolean executeResult);

    /** @return the status of whether the ActionProxy is set to execute the Result after the Action is executed
     */
    boolean getExecuteResult();

    /** @return the ActionInvocation:表示Action的运行状态,包括Interceptors和Action的实例 */
    ActionInvocation getInvocation();

    /**
     * @return the namespace the ActionConfig for this ActionProxy is mapped to
     */
    String getNamespace();

    /**
     * 运行ActionProxy. 把ActionContext 设置为 ActionInvocation中的 ActionContext
     * 关键还是调用ActionInvocation.invoke()。
     * DefaultActionProxy中的实现
     *public String execute() throws Exception {
  
  
     *   ActionContext nestedContext = ActionContext.getContext();
     *   ActionContext.setContext(invocation.getInvocationContext());

     *   String retCode = null;

     *   String profileKey = "execute: ";
     *   try {
  
  
     *   	UtilTimerStack.push(profileKey);

     *       retCode = invocation.invoke();
     *   } finally {
  
  
     *       if (cleanupContext) {
  
  
     *           ActionContext.setContext(nestedContext);
     *       }
     *       UtilTimerStack.pop(profileKey);
     *   }

     *   return retCode;
     *}
     */
    String execute() throws Exception;

    /** 设置Invocation中的Method的,如果空的话就用execute。 */
    void setMethod(String method);

    /**
     * Returns the method to execute, or null if no method has been specified (meaning "execute" will be invoked)
     */
    String getMethod();

}

再来看一下ActionInvocation.invoke()的实现:

代码语言:javascript
复制
   public String invoke() throws Exception {
  
  
    	String profileKey = "invoke: ";
    	try {
  
  
    		UtilTimerStack.push(profileKey);
    		//如果运行过了,就抛出异常
    		if (executed) {
  
  
    			throw new IllegalStateException("Action has already executed");
    		}
                //运行Interceptor
    		if (interceptors.hasNext()) {
  
  
    			final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
                        //UtilTimerStack.profile()即
        /*public static <T> T profile(String name, ProfilingBlock<T> block) throws Exception {
  
  
    	UtilTimerStack.push(name);
    	try {
  
  
    		return block.doProfiling();
    	}
    	finally {
  
  
    		UtilTimerStack.pop(name);
    	}
    }*/
    			UtilTimerStack.profile("interceptor: "+interceptor.getName(), 
    					new UtilTimerStack.ProfilingBlock<String>() {
  
  
							public String doProfiling() throws Exception {
  
  
				    			resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
				    			return null;
							}
    			});
    		} else {
  
  
    			resultCode = invokeActionOnly();
    		}

    		// this is needed because the result will be executed, then control will return to the Interceptor, which will
    		// return above and flow through again

[color=red]没看懂,好像是由于在下面还要调用result.execute(ActionInvocation),那么还是有可能再次调用这个地方?[/color]
    		if (!executed) {
  
  
    			if (preResultListeners != null) {
  
  
    				for (Iterator iterator = preResultListeners.iterator();
    					iterator.hasNext();) {
  
  
    					PreResultListener listener = (PreResultListener) iterator.next();

    					String _profileKey="preResultListener: ";
    					try {
  
  
    						UtilTimerStack.push(_profileKey);
    						listener.beforeResult(this, resultCode);
    					}
    					finally {
  
  
    						UtilTimerStack.pop(_profileKey);
    					}
    				}
    			}

    			// now execute the result, if we're supposed to
    			if (proxy.getExecuteResult()) {
  
  
                                //调用result.execute(ActionInvocation);
    				executeResult();
    			}

    			executed = true;
    		}

    		return resultCode;
    	}
    	finally {
  
  
    		UtilTimerStack.pop(profileKey);
    	}
    }

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/170656.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档