在 Struts2 中获取已配置操作的列表
Getting a list of configured actions in Struts2
在使用 Struts2 (2.3.20) 的项目中,我想 运行 通过
在应用程序启动时配置的操作(名称、class、命名空间、方法)。
我正在使用
- Struts 2.3.20
- struts-spring-插件
- struts-约定插件
供参考:我之前用 beans 和 Struts 注入做过一些工作,所以对此并不完全新鲜,但我一直在解决此处所述的问题。
任何关于如何获得它的指示将不胜感激。
进一步说明
阅读下面 Andrea 的回答,我发现我需要解释我的需要。
我正在为应用程序构建应用程序菜单生成器功能。我的计划是获取操作配置并根据所选操作 classes 和方法的注释中的信息构建 "menu nodes" 树。
我对来自配置浏览器的代码的问题是 Configuration
(xwork) 似乎在 Struts 组件之外不可用。由于这是一个应用程序启动任务,它并不真正适合 Struts' MVC 组件模型。我想将菜单构建初始化放在 ServletContextListener
.
中
假例子
此处的每个请求只是连接 actionconfig <-> 注释 <-> my_custom_menu。由此,我可以根据操作 classes 和方法的注释生成一个菜单结构。
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
是 class Struts 将 return 用于操作配置的任何内容,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;
}
}
以防其他人也这么想:)
您无需为个人成长构建此内容,但请注意它已经存在。
叫做Config Browser Plugin (struts2-config-browser-plugin-2.3.20.jar
).
它默认包含在 Maven 原型中,您必须记住在投入生产之前将其删除。
导入后可在 URL:
//www.SERVER_NAME.com:8080/WEBAPP_NAME/config-browser/actionNames
它为您提供了您正在寻找的确切信息:操作、方法、结果、参数、映射等,它看起来像这样:
首先,您需要在加载和解析配置后挂接到应用程序初始化过程。其中一种方法是实现 DispatcherListener
,您需要将其添加到 Dispatcher
。这可以在 ServletContextListener#contextInitialized
方法中完成。
第二块拼图是获取动作配置。这非常简单,因为 Dispatcher
的实例作为参数传递给 dispatcherInitialized
方法。要获取所有当前操作配置,请获取 RuntimeConfiguration
,它在 Map<String, Map<String, ActionConfig>>
中保存数据,其中第一个映射键是包命名空间,第二个映射键是操作名称,ActionConfig
保存有关操作的所有信息。由于您需要一个 class 名称,因此请使用它的 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 中注册您的监听器。
在使用 Struts2 (2.3.20) 的项目中,我想 运行 通过 在应用程序启动时配置的操作(名称、class、命名空间、方法)。
我正在使用
- Struts 2.3.20
- struts-spring-插件
- struts-约定插件
供参考:我之前用 beans 和 Struts 注入做过一些工作,所以对此并不完全新鲜,但我一直在解决此处所述的问题。
任何关于如何获得它的指示将不胜感激。
进一步说明
阅读下面 Andrea 的回答,我发现我需要解释我的需要。
我正在为应用程序构建应用程序菜单生成器功能。我的计划是获取操作配置并根据所选操作 classes 和方法的注释中的信息构建 "menu nodes" 树。
我对来自配置浏览器的代码的问题是 Configuration
(xwork) 似乎在 Struts 组件之外不可用。由于这是一个应用程序启动任务,它并不真正适合 Struts' MVC 组件模型。我想将菜单构建初始化放在 ServletContextListener
.
假例子
此处的每个请求只是连接 actionconfig <-> 注释 <-> my_custom_menu。由此,我可以根据操作 classes 和方法的注释生成一个菜单结构。
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
是 class Struts 将 return 用于操作配置的任何内容,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;
}
}
以防其他人也这么想:)
您无需为个人成长构建此内容,但请注意它已经存在。
叫做Config Browser Plugin (struts2-config-browser-plugin-2.3.20.jar
).
它默认包含在 Maven 原型中,您必须记住在投入生产之前将其删除。
导入后可在 URL:
//www.SERVER_NAME.com:8080/WEBAPP_NAME/config-browser/actionNames
它为您提供了您正在寻找的确切信息:操作、方法、结果、参数、映射等,它看起来像这样:
首先,您需要在加载和解析配置后挂接到应用程序初始化过程。其中一种方法是实现 DispatcherListener
,您需要将其添加到 Dispatcher
。这可以在 ServletContextListener#contextInitialized
方法中完成。
第二块拼图是获取动作配置。这非常简单,因为 Dispatcher
的实例作为参数传递给 dispatcherInitialized
方法。要获取所有当前操作配置,请获取 RuntimeConfiguration
,它在 Map<String, Map<String, ActionConfig>>
中保存数据,其中第一个映射键是包命名空间,第二个映射键是操作名称,ActionConfig
保存有关操作的所有信息。由于您需要一个 class 名称,因此请使用它的 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 中注册您的监听器。