struts2 实现原理解析

struts2 实现原理解析

struts2 操作 action servlet,是通过在web.xml中配置一个filter实现的
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
     </filter>   

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
      注:现在新版本的struts2已经改成StrutsPrepareAndExecuteFilter,但原理大同小异,我们还按FilterDispatcher讲解
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
   

而这个Filter FilterDispatcher 实际做了下列工作   
  public class FilterDispatcher implements StrutsStatics, Filter
  • 1.filter的init()方法建立一个Dispatcher对象
以后struts2 都是围绕这个Dispatcher对象进行操作
init()方法将参数FilterConfig对象传给Dispatcher对象,实际就是将ServletContext对象传递给Dispatcher对象
而ServletContext包含了各种基本Servlet的运行环境,比如ServletContext提供了getAttribute(), setAttribute() 等方法
所以, 实际是Dispatcher对象接管了基本Servlet的一切功能
public void init(FilterConfig filterConfig) throws ServletException {
        dispatcher = createDispatcher(filterConfig);
        ...
        }
 protected Dispatcher createDispatcher(FilterConfig filterConfig) {
        ...
        return new Dispatcher(filterConfig.getServletContext(), params);
    }
  • 2.filter的doFilter()方法继续操作前面init()方法建立的作Dispatcher对象,将HttpServletRequest对象和HttpServletResponse对象传入Dispatcher中
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        ServletContext servletContext = getServletContext();
                ....
        dispatcher.serviceAction(request, response, servletContext, mapping);
    }
 


 Dispatcher对象是Struts2的核心操作对象,它主要实现实现了下面的工作
  •  1.它是线程安全的,即Dispatcher对象支持多线程,且每线程一副本
public class Dispatcher {

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

 //Store the dispatcher instance for this thread.
  public static void setInstance(Dispatcher instance) {
     Dispatcher.instance.set(instance);

     // Tie the ObjectFactory threadlocal instance to this Dispatcher instance
              if (instance != null) {
         Container cont = instance.getContainer();
                  if (cont != null) {
             ObjectFactory.setObjectFactory(cont.getInstance(ObjectFactory.class));
         } else {
             LOG.warn("This dispatcher instance doesn't have a container, so the object factory won't be set.");
         }
     } else {
         ObjectFactory.setObjectFactory(null);
     }
 }

 //Provide the dispatcher instance for the current thread.
   public static Dispatcher getInstance() {
     return instance.get();
 }
  • 2.上边说了,Dispatcher对象的建立/构造,是接受了参数FilterDispatcher过滤器的FilterConfig传来的ServletContext,这样才接管了基本Servlet的一切功能
private ServletContext servletContext;
private Map<String, String> initParams;

 public  Dispatcher(ServletContext servletContext, Map<String, String> initParams) {
     this.servletContext = servletContext;
     this.initParams = initParams;
 }
  • 3. 上边说了,FilterDispatcher过滤器的doFilter()方法,调用了Dispatcher对象的serviceAction()方法,并把HttpServletRequest对象和HttpServletResponse对象传入
  这个serviceAction()方法,就是整个Strtus2的主引擎.
  serviceAction内部完成了多项功能:
配置文件加载,配置初始化
调用ActionProxy对象实现对Action类的执行
ActionProxy对象又会按照Struts2的Stack结构依次执行Inteceptor,action,method
struts2 <wbr>实现原理解析 

public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,ActionMapping mapping) throws ServletException {
 
     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);
        if (stack != null) {
         extraContext.put(ActionContext.VALUE_STACK, ValueStackFactory.getFactory().createValueStack(stack));
     }

        try {
         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, extraContext, true, false);
         proxy.setMethod(method);
         request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

         // if the ActionMapping says to go straight to a result, do it!
          if (mapping.getResult() != null) {
             Result result = mapping.getResult();
             result.execute(proxy.getInvocation());
                 } else {
             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) {
     }
 }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值