Java Spring在运行时不会发现新上下文的@RequestMapping注释
我只是尝试为我的spring boot web应用程序开发一个插件系统。应用程序使用根上下文路径部署在tomcat服务器上。插件系统允许我在运行时加载特别准备的jar文件。系统还应该能够在运行时取消部署插件。这些JAR包含在当前工作目录的插件文件夹中。我希望每个插件都有自己的spring上下文来操作。依赖项注入按预期工作,但spring没有发现插件上下文的@RequestMapping注释。所以我的问题是:如何让spring发现我的插件的@RequestMapping注释(在运行时) 我使用的是最新的spring boot版本和以下application.yml:Java Spring在运行时不会发现新上下文的@RequestMapping注释,java,spring,spring-mvc,spring-boot,request-mapping,Java,Spring,Spring Mvc,Spring Boot,Request Mapping,我只是尝试为我的spring boot web应用程序开发一个插件系统。应用程序使用根上下文路径部署在tomcat服务器上。插件系统允许我在运行时加载特别准备的jar文件。系统还应该能够在运行时取消部署插件。这些JAR包含在当前工作目录的插件文件夹中。我希望每个插件都有自己的spring上下文来操作。依赖项注入按预期工作,但spring没有发现插件上下文的@RequestMapping注释。所以我的问题是:如何让spring发现我的插件的@RequestMapping注释(在运行时) 我使用的是
# Server
server:
error:
whitelabel:
enabled: true
session:
persistent: true
tomcat:
uri-encoding: UTF-8
# Spring
spring:
application:
name: Plugins
mvc:
favicon:
enabled: false
favicon:
enabled: false
thymeleaf:
encoding: UTF-8
# Logging
logging:
file: application.log
level.: error
这是加载插件的代码:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] { plugin.getPluginURL() }, getClass().getClassLoader()); // plugin.getPluginURL will refer to a jar file with the plugin code (see below).
context.setClassLoader(urlClassLoader);
context.setParent(applicationContext); // applicationContext is the the context of the original spring application. It was autowired.
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
scanner.scan("my.plugin.package");
context.refresh();
控制器代码(在我的插件中):
但是,我仍在寻找一种方法,使用spring方式使其工作:
感谢阅读。您是否在spring_servlet.xml中的context:component scan base package=“location”中添加了控制器位置SpringMvc有自己的缓存
@RequestMapping
,详细代码是RequestMappingHandlerMapping
。如您所见,显示了init方法,也许您可以在加载新插件后调用init方法
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
if (isHandler(getApplicationContext().getType(beanName))){
detectHandlerMethods(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
这是spring3的
RequestMappingHandlerMapping
code,可能spring4的impl中有一些变化。我认为,您需要添加
<context:component-scan base-package="package_name" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />
在你的xxx-servlet.xml文件中。你能发布你的application.properties吗?@Alex我刚刚更新了帖子以包含我的应用程序。ymlI刚刚注意到你的pluginestcontroller.doGet方法是私有的。我目前无法测试它,但您确定这是受支持的吗?好的,查一下,它是被支持的。()但我还是会尝试将方法更改为public@Alex我只是尝试了一下,但仍然不起作用。我想您可能需要在容器中注册Spring的DispatcherServlet的新实例。在这里进行推测,但当您初始化SpringWeb应用程序时,spring的DispatcherServlet和相关的委托会找出如何将请求映射到您的bean。您可能需要一个新的web应用上下文,其中包含与servlet容器相关的管道(例如tomcat或jetty),在单独的评论中建议一种替代方法,因为我已经用完了spi,我使用spring boot和rhe java annotatiom驱动的方式来配置我的控制器。因此,该项目没有spring_servlet.xml。这实际上非常有用,与我昨晚已经计算出的代码类似。到目前为止,我正在使用一种类似的方法,基于这个问题的答案:。我刚刚更新了我的答案,加入了使控制器为我工作的代码。我不认为我的aproach是完美的,但至少现在它的工作。我将看看spring4实现它的方式。谢谢你指出代码。我很高兴能帮助你,如果你有新的研究结果,你会更新这篇文章吗?我使用spring boot和java注释驱动的方式来配置我的控制器。因此,该项目没有spring_servlet.xml。这个问题也已经得到了回答
protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}
String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
for (String beanName : beanNames) {
if (isHandler(getApplicationContext().getType(beanName))){
detectHandlerMethods(beanName);
}
}
handlerMethodsInitialized(getHandlerMethods());
}
<context:component-scan base-package="package_name" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />