struts2的两种启动方式


Struts2 2.1.3版本开始使用strutsPrepareAndExecuteFilter 启动struts2,在此版本之前使用的DispatcherFilter

FilterDispatcher启动流程:

struts2是实现filter接口,所以我们在使用struts2的时候需要在web.xml文件中配置一个filter过滤器来启动struts2.

第一步: 初始化

public void init(FilterConfig filterConfig) throws ServletException {

        try {

            this.filterConfig = filterConfig;                        

 

            initLogging();                 //初始化struts2本身的日志工厂

 

            dispatcher = createDispatcher(filterConfig);   //创建dispatcher对象,具体见 

            dispatcher.init();       //初始化dispatcher,具体见②                

            dispatcher.getContainer().inject(this);     

//filterConfig设置到struts资源加载器中

            staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));

        } finally {

            ActionContext.setContext(null);

        }

    }

 

 

 

① 

protected Dispatcher createDispatcher(FilterConfig filterConfig) {

        Map<String, String> params = new HashMap<String, String>();

 //web.xml文件中读取初始化参数

        for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {

            String name = (String) e.nextElement(); 

            String value = filterConfig.getInitParameter(name);

            params.put(name, value);

        }

        return new Dispatcher(filterConfig.getServletContext(), params);   1.1

}

 

1.1

public Dispatcher(ServletContext servletContext, Map<String, String> initParams) {

        this.servletContext = servletContext;     //保存servletContext对象

        this.initParams = initParams;           //保存初始化参数

}

 

 

 

②public void init() {

 

     if (configurationManager == null) {

     configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);

     }

 

        try {

            init_DefaultProperties(); // [1]   初始化struts的默认属性配置文件加载到配置管理器中

            init_TraditionalXmlConfigurations(); // [2]读取web.xml中的config参数(如果没有则将读取系统默认的参数),将对应的配置文件加载到配置文件管理器 

            init_LegacyStrutsProperties(); // [3]

            init_CustomConfigurationProviders(); // [5]  自定义配置文件加载器加载到配置管理器中

            init_FilterInitParameters() ; // [6]      Filter中的初始化参数加载配置文件中

            init_AliasStandardObjects() ; // [7]      初始化一些可选属性配置

 

            Container container = init_PreloadConfiguration();//国际化修改时是否重新加载国际化文件设置

            container.inject(this);

            init_CheckConfigurationReloading(container);  //设置struts.xml文件修改是是否重新加载struts.xml文件

            init_CheckWebLogicWorkaround(container);//STRUTS_DISPATCHER_PARAMETERSWORKAROUND 初始化

 

            if (!dispatcherListeners.isEmpty()) {//dispatcherListenersstruts2自己本身是没有使用的,但是我们在对FilterDispatcher扩展的时候可以使用这个做一些我们想要的事

                for (DispatcherListener l : dispatcherListeners) {

                    l.dispatcherInitialized(this);

                }

            }

        } catch (Exception ex) {

            if (LOG.isErrorEnabled())

                LOG.error("Dispatcher initialization failed", ex);

            throw new StrutsException(ex);

        }

    }

 

 

 

 

第二步:对请求做过滤处理

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 {

            ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();//创建值栈对象

            ActionContext ctx = new ActionContext(stack.getContext());   //将值栈中的参数保存到ActionContext容器中,保证值栈与容器中的值一致

            ActionContext.setContext(ctx);

 

            UtilTimerStack.push(timerKey);

            request = prepareDispatcherAndWrapRequest(request, response);//第一次调用action时对dispatcher进行线程本地化,同时对request的编码和local进行设置,然后根据request类型进行装饰     

            ActionMapping mapping;

            try {

                mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager()); //根据request获得一个actionMapping   

            } catch (Exception ex) {

                log.error("error getting ActionMapping", ex);

                dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);

                return;

            }

 

            if (mapping == null) {

                // there is no action in this request, should we look for a static resource?

                String resourcePath = RequestUtils.getServletPath(request);

 

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

                    resourcePath = request.getPathInfo();

                }

 

                if (staticResourceLoader.canHandle(resourcePath)) {

                    staticResourceLoader.findStaticResource(resourcePath, request, response);

                } else {

                    // this is a normal request, let it pass through

                    chain.doFilter(request, response);

                }

                // The framework did its job here

                return;

            }

//正式开始对action进行处理   

            dispatcher.serviceAction(request, response, servletContext, mapping);

 

        } finally {

            try {

                ActionContextCleanUp.cleanUp(req);

            } finally {

                UtilTimerStack.pop(timerKey);

            }

        }

    }

 

 

 ③

protected HttpServletRequest prepareDispatcherAndWrapRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException {

        Dispatcher du = Dispatcher.getInstance();

        if (du == null) {//第一次调用时对dispatcher进行预处理

            Dispatcher.setInstance(dispatcher);  //dispatcher保存到本地线程中

            dispatcher.prepare(request, response);//dispatcher defaultEncodingdefaultLocale属性设置,同时对requestEncodingLocale属性进行设置

        } else {

            dispatcher = du;

        }

 

        try {

            request = dispatcher.wrapRequest(request, getServletContext());//根据request请求类型,返回一个被装饰成StrutsRequestWrapper或者MultiPartRequestWrapper(用于文件上传)

        } catch (IOException e) {

            String message = "Could not wrap servlet request with MultipartRequestWrapper!";

            log.error(message, e);

            throw new ServletException(message, e);

        }

 

        return request;

    }

 

public ActionMapping getMapping(HttpServletRequest request,

            ConfigurationManager configManager) {

        ActionMapping mapping = new ActionMapping();

        String uri = getUri(request);//request中获取uriuri对应于request中的javax.servlet.include.servlet_path参数值)

 

        int indexOfSemicolon = uri.indexOf(";");

        uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri;

 

        uri = dropExtension(uri, mapping);   //去掉uri中的.action或其他后缀的扩展

        if (uri == null) {

            return null;

        }

        //解析uri获取命名空间和action名字

        parseNameAndNamespace(uri, mapping, configManager);

        //.x.y结尾的参数名进行处理

        handleSpecialParameters(request, mapping);

 

        if (mapping.getName() == null) {

            return null;

        }

        //mappingname进行解析,如果开启的动态方法name要重新设置

        parseActionName(mapping);

 

        return mapping;

    }

 

 

public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,ActionMapping mapping) throws ServletException {

     //requestresponseactionMappingparameter装到map

        Map<String, Object> extraContext = createContextMap(request, response, mapping, context);         //5.1

        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);//request中获取值栈

        boolean nullStack = stack == null;

        if (nullStack) {

            ActionContext ctx = ActionContext.getContext();  

            if (ctx != null) {

                stack = ctx.getValueStack();   //ActionContext中获取值栈

            }

        }

        if (stack != null) {

            extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.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, method, extraContext, true, false);

 

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

            if (mapping.getResult() != null) {

                Result result = mapping.getResult();

                result.execute(proxy.getInvocation());

            } else {

                proxy.execute();

            }

 

                      if (!nullStack) {request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);

            }

        } catch (ConfigurationException e) {

         // WW-2874 Only log error if in devMode

         if(devMode) {

         LOG.error("Could not find action or result", e);

         }

         else {

         LOG.warn("Could not find action or result", e);

         }

            sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);

        } catch (Exception e) {

            sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);

        } finally {

            UtilTimerStack.pop(timerKey);

        }

    }

 

5.1

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

        Map requestMap = new RequestMap(request);

        Map params = new HashMap(request.getParameterMap());

        Map session = new SessionMap(request);

        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;

    }

 

 

 

strutsPrepareAndExecuteFilter 方式启动struts2

public void init(FilterConfig filterConfig) throws ServletException {

        InitOperations init = new InitOperations();

        try {

            FilterHostConfig config = new FilterHostConfig(filterConfig);

            init.initLogging(config);

            Dispatcher dispatcher = init.initDispatcher(config);//等价于FilterDispatchercreateDispatcher(filterConfig)dispatcher.init();

            init.initStaticContentLoader(config, dispatcher);  //等价于FilterDispatcher的 staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));

 

            prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);//创建prepare对象;设置dispatcherServletContext属性

            execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);//创建execute对象;设置dispatcherServletContext属性

this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);//action后缀扩展获取

 

            postInit(dispatcher, filterConfig);  //可以通过继承该类,然后重写此方法来定制自己的功能

        } finally {

            init.cleanup();

        }

 

    }

 

//struts2本身对这个方法是没有做任何操作的

protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {

    }

 

 

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;

        HttpServletResponse response = (HttpServletResponse) res;

        try {

            prepare.setEncodingAndLocale(request, response);//设置request的编码格式和local

            prepare.createActionContext(request, response);//创建ActionContext容器环境

            prepare.assignDispatcherToThread();//dispatcher保存到本地线程中

if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {

//如果请求的扩展后缀与我们设置的后缀像匹配,匹配失败就跳过struts的操作

chain.doFilter(request, response);

} else {

request = prepare.wrapRequest(request);   //request进行装饰

ActionMapping mapping = prepare.findActionMapping(request, response, true);//通过url获取对应的actionmapping

if (mapping == null) {

boolean handled = execute.executeStaticResourceRequest(request, response);

//判断请求是否struts请求,如果是进入struts的工作,不是就跳过

if (!handled) {

chain.doFilter(request, response);

}

} else {

execute.executeAction(request, response, mapping);

}

}

        } finally {

            prepare.cleanupRequest(request);

        }

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值