5

在使用 Struts2 (2.3.20) 的项目中,我想在应用程序启动时运行配置的操作(名称、类、命名空间、方法)。

我在用着

  • Struts 2.3.20
  • struts-spring-plugin
  • struts 约定插件

供参考:我之前在 bean 和 Struts 注入方面做过一些工作,所以对此并不完全新鲜,但我一直在解决这里所说的问题。

任何有关如何获得这一点的指针将不胜感激。

进一步说明

阅读下面安德里亚的回答,我发现我需要解释我需要什么。

我正在为应用程序构建应用程序菜单构建器功能。我的计划是获取操作配置,并根据所选操作类和方法的注释信息构建“菜单节点”树。

我对来自配置浏览器的代码的问题是Configuration(xwork) 在 Struts 组件之外似乎不可用。由于这是一个应用程序启动任务,它并不真正适合 Struts 的 MVC 组件模型。我想将菜单构建初始化放在ServletContextListener.

假例子

这里的每个请求只是连接操作配置 <-> 注释 <-> my_custom_menu。由此,我可以生成由动作类和方法的注释提供的菜单结构。

public class ActionMenuBuilderListener implements ServletContextListener {
  @Override
  public void contextInitialized(ServletContextEvent arg0) {
    List<ActionCfg> actions = Struts.getConfiguredActions(); // thisi is where I'd like some help
    for(ActionCfg action : actions) {
      MenuAnnotation annotation = getAnnotationFromMethodOrClass(action);
      if(annotation != null) {
        addMenuItem(action, annotation);
      }
    }
  }
}

ActionCfg是 Struts 为操作配置返回的任何类,Struts.getConfiguredActions()将是对 Struts 组件的一个或多个调用,并且addMenu(...)是我将菜单项节点添加到我的结构的地方。该结构是稍后从 JSP-s 构建菜单的目标。

我不知道还要写多少代码。

我的解决方案

为了完整起见,我想我会包括由此产生的内容。

首先,我通过这个插入到 Struts 中 ServletContextListnere

public class ActionMenuBuilderListener implements
    ServletContextListener {

@Override
public void contextDestroyed(ServletContextEvent arg0) {
}

@Override
public void contextInitialized(ServletContextEvent event) {

    ActionMenuDispatcherListener listener =
    new ActionMenuDispatcherListener(); 
    ServletContext context = event.getServletContext();
    listener.setServletContext(context);

    Dispatcher.addDispatcherListener(listener);

}
}

然后,我写了DispatcherListener

public class ActionMenuDispatcherListener implements DispatcherListener {

private ServletContext servletContext;

...

@Override
public void dispatcherInitialized(Dispatcher dispatcher) {

    Map<String, PackageConfig> packages = dispatcher
        .getConfigurationManager().getConfiguration()
        .getPackageConfigs();

    Map<String, Map<String, ActionConfig>> runtimeActionConfigs = dispatcher
        .getConfigurationManager().getConfiguration()
        .getRuntimeConfiguration().getActionConfigs();

    for (String packageKey : runtimeActionConfigs.keySet()) {

    Map<String, ActionConfig> actionConfigs = runtimeActionConfigs
        .get(packageKey);

    for (String actionKey : actionConfigs.keySet()) {
        ActionConfig actionConfig = actionConfigs.get(actionKey);
        PackageConfig packageConfig = packages.get(actionConfig
            .getPackageName());

        if (packageConfig != null) {
        String actionName = actionConfig.getName();
        String namespace = packageConfig.getNamespace();
        try {

            ActionMenu methodAnnotation = getMethodAnnotation(actionConfig);

            if (methodAnnotation != null) {
            String annotationInfo = methodAnnotation.value();
            log.debug("[{}, {}, {}]", namespace, actionName,
                annotationInfo);
            }

        } catch (ClassNotFoundException e) {
            log.error("{}: {}", e.getClass().getSimpleName(),
                e.getMessage());
        }
        }
    }
    }
}

protected ActionMenu getMethodAnnotation(ActionConfig actionConfig)
    throws ClassNotFoundException {
    String className = actionConfig.getClassName();
    String methodName = actionConfig.getMethodName();
    Class<?> actionClass = Class.forName(className);
    try {
    Method method = actionClass.getDeclaredMethod(methodName, null);
    ActionMenu annotation = method.getAnnotation(ActionMenu.class);
    return annotation;
    } catch (NoSuchMethodException | SecurityException e) {
    // log.error("{}: {}", e.getClass().getSimpleName(),
    // e.getMessage());
    }
    return null;
}

}

以防万一其他人沿着这些思路思考:)

4

2 回答 2

6

首先,您需要在加载和解析配置后挂钩到应用程序初始化过程。其中一种方法是实现DispatcherListener您需要添加到Dispatcher. 你可以在ServletContextListener#contextInitialized方法中做到这一点。

第二个难题是获取动作配置。这非常简单,因为 的实例Dispatcher作为参数传递给dispatcherInitialized方法。要获取所有当前操作配置,获取RuntimeConfiguration其中包含数据的Map<String, Map<String, ActionConfig>>,其中第一个映射键是包命名空间,第二个映射键是操作名称并ActionConfig保存有关操作的所有信息。由于您需要一个类名,因此请使用getClassName()它的方法。

public class ActionMenuBuilderListener implements ServletContextListener,DispatcherListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        Dispatcher.addDispatcherListener(this);
    }

    @Override
    public void dispatcherInitialized(Dispatcher du) {
        Map<String, Map<String, ActionConfig>> runtimeActionConfigs = du
            .getConfigurationManager().getConfiguration().getRuntimeConfiguration()
            .getActionConfigs();
    }
    // other methods
}

当然不要忘记在 web.xml 中注册你的监听器。

于 2015-07-09T18:38:59.543 回答
4

您无需为个人成长而构建此东西,但请注意它已经存在

它被称为配置浏览器插件( struts2-config-browser-plugin-2.3.20.jar)。

它默认包含在 Maven 原型中,您必须记住在投入生产之前将其删除。

导入后,可在 URL 中使用:

//www.SERVER_NAME.com:8080/WEBAPP_NAME/config-browser/actionNames _

它为您提供了您正在寻找的确切信息:操作、方法、结果、参数、映射等,它看起来像这样:

在此处输入图像描述

于 2015-07-09T12:05:10.093 回答