Struts2初始化之Dispatcher

Dispatcher作为Struts2的核心分发器,承担项目初始化任务。本文聚焦其关键方法,如ThreadLocal实现线程安全,init()初始化,serviceAction()执行action流程,wrapRequest()请求包装,createContextMap()创建上下文映射,以及上传下载、容器、上下文和值栈的初始化配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Dispatcher也叫做核心分发器,Dispatcher类负责整个Struts2项目的初始化工作。这是一个很庞大的类,这里会挑选一些重要的方法进行分析。
很明显这是一个应用ThreadLocal的例子,它为当前线程中的一个叫做ThreadLocalMap的线程副本,使得线程与线程之间,每一个线程可以独立的修改自己的副本,而不会影响到其他线程的变量,从而使线程安全。
Dispatcher分发器的出现,作用是由刚刚处理过Http请求,并完成初始化后的struts2部分转入xwork部分。

   private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();

初始化国际化方法

  @Inject(value=StrutsConstants.STRUTS_LOCALE, required=false)
    public void setDefaultLocale(String val) {
        defaultLocale = val;
    }
 @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
    public void setDefaultEncoding(String val) {
        defaultEncoding = val;
    }

cleanup()方法,清除当前线程之中的对象实例,清空拦截器栈等。

 public void cleanup() {

        // clean up ObjectFactory
        //清除对象实例
        ObjectFactory objectFactory = getContainer().getInstance(ObjectFactory.class);
        if (objectFactory == null) {
            if (LOG.isWarnEnabled()) {
            LOG.warn("Object Factory is null, something is seriously wrong, no clean up will be performed");
            }
        }
        if (objectFactory instanceof ObjectFactoryDestroyable) {
            try {
                ((ObjectFactoryDestroyable)objectFactory).destroy();
            }
            catch(Exception e) {
                // catch any exception that may occurred during destroy() and log it
                LOG.error("exception occurred while destroying ObjectFactory [#0]", e, objectFactory.toString());
            }
        }

          //将当前分发器的引用置为null
        instance.set(null);

          //销毁Dispatcher监听器
        if (!dispatcherListeners.isEmpty()) {
            for (DispatcherListener l : dispatcherListeners) {
                l.dispatcherDestroyed(this);
            }
        }

        // clean up all interceptors by calling their destroy() method
        Set<Interceptor> interceptors = new HashSet<Interceptor>();
        Collection<PackageConfig> packageConfigs = configurationManager.getConfiguration().getPackageConfigs().values();
        for (PackageConfig packageConfig : packageConfigs) {
            for (Object config : packageConfig.getAllInterceptorConfigs().values()) {
                if (config instanceof InterceptorStackConfig) {
                    for (InterceptorMapping interceptorMapping : ((InterceptorStackConfig) config).getInterceptors()) {
                        interceptors.add(interceptorMapping.getInterceptor());
                    }
                }
            }
        }
        //清空拦截器栈
        for (Interceptor interceptor : interceptors) {
            interceptor.destroy();
        }

        // Clear container holder when application is unloaded / server shutdown
        ContainerHolder.clear();
        //销毁ActionContext
        ActionContext.setContext(null);

        // clean up configuration
        configurationManager.destroyConfiguration();
        configurationManager = null;
    }

Dispatcher最重要的方法就是init(),初始化方法。

  public void init() {
//判断ConfigurationManager对象是否为null,如果为null,new一个
        if (configurationManager == null) {
            configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
        }

        try {
        //对配置文件进行初始化
            init_FileManager();
            //default.properties初始化
            init_DefaultProperties(); // [1]
            //xwork配置文件的初始化
            init_TraditionalXmlConfigurations(); // [2]

            init_LegacyStrutsProperties(); // [3]
            init_CustomConfigurationProviders(); // [5]
            init_FilterInitParameters() ; // [6]
            init_AliasStandardObjects() ; // [7]
            //初始化国际化
            Container container = init_PreloadConfiguration();
            //注入容器,container
            container.inject(this);
            init_CheckWebLogicWorkaround(container);

            if (!dispatcherListeners.isEmpty()) {
                for (DispatcherListener l : dispatcherListeners) {
                    l.dispatcherInitialized(this);
                }
            }
        } catch (Exception ex) {
            if (LOG.isErrorEnabled())
                LOG.error("Dispatcher initialization failed", ex);
            throw new StrutsException(ex);
        }
    }

serviceAction()方法,这个方法也是执行action的主要流程的方法

  public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
                              ActionMapping mapping) throws ServletException {
//创建action对应的上下文映射,在我看来是一种封装
        Map<String, Object> extraContext = createContextMap(request, response, mapping, context);

        // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
        //获取值栈
        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
        boolean nullStack = stack == null;
        if (nullStack) {
        //创建ActionContext,也就是我们所说的上下文
            ActionContext ctx = ActionContext.getContext();
            if (ctx != null) {
                stack = ctx.getValueStack();
            }
        }
        if (stack != null) {
        //将action对应的映射压入值栈
            extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
        }

        String timerKey = "Handling request from Dispatcher";
        try {
            UtilTimerStack.push(timerKey);
            //获取action的信息,action名,方法等
            String namespace = mapping.getNamespace();
            String name = mapping.getName();
            String method = mapping.getMethod();

            Configuration config = configurationManager.getConfiguration();
            //利用容器创建实例,动态的创建代理
            ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                    namespace, name, method, extraContext, true, false);

            request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

            // if the ActionMapping says to go straight to a result, do it!
            //拦截器执行完毕后返回的resultCode如果不为null,就执行结果集
            if (mapping.getResult() != null) {
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            } else {
            //执行完结果集后执行execute()方法
                proxy.execute();
            }

            // If there was a previous value stack then set it back onto the request
            if (!nullStack) {
                request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
            }
        } catch (ConfigurationException e) {
            // WW-2874 Only log error if in devMode
            if (devMode) {
                String reqStr = request.getRequestURI();
                if (request.getQueryString() != null) {
                    reqStr = reqStr + "?" + request.getQueryString();
                }
                LOG.error("Could not find action or result\n" + reqStr, e);
            } else {
                if (LOG.isWarnEnabled()) {
                    LOG.warn("Could not find action or result", e);
                }
            }
            sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
        } catch (Exception e) {
            if (handleException || devMode) {
                sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
            } else {
                throw new ServletException(e);
            }
        } finally {
            UtilTimerStack.pop(timerKey);
        }
    }

wrapRequest()方法,是对HttpServletRequest 类型的请求进行包装,应用了装饰器模式,目的是将Http服务端与初始化解耦,将其分离

 public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {
        // don't wrap more than once
        if (request instanceof StrutsRequestWrapper) {
            return request;
        }

        String content_type = request.getContentType();
        if (content_type != null && content_type.contains("multipart/form-data")) {
            MultiPartRequest mpr = getMultiPartRequest();
            LocaleProvider provider = getContainer().getInstance(LocaleProvider.class);
            request = new MultiPartRequestWrapper(mpr, request, getSaveDir(servletContext), provider);
        } else {
            request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);
        }

        return request;
    }

createContextMap()方法,创建上下文映射,并将其压栈

 public Map<String,Object> createContextMap(HttpServletRequest request, HttpServletResponse response,
            ActionMapping mapping, ServletContext context) {

        // request map wrapping the http request objects
        Map requestMap = new RequestMap(request);

        // parameters map wrapping the http parameters.  ActionMapping parameters are now handled and applied separately
        Map params = new HashMap(request.getParameterMap());

        // session map wrapping the http session
        Map session = new SessionMap(request);

        // application map wrapping the ServletContext
        Map application = new ApplicationMap(context);

        Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);

        if (mapping != null) {
            extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
        }
        return extraContext;
    }

其余的方法是对,上传下载,对容器,上下文,值栈的初始化,以及国际化,字符编码的初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值