【问题标题】:Using Spring boot with rest controller使用带有休息控制器的 Spring Boot
【发布时间】:2016-11-09 15:22:25
【问题描述】:

主类:

package com.rsc.springboot_test;
@SpringBootApplication
public class SpringBootTest {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootTest.class, args);
    }
}

控制器类:

package com.rsc.springboot_test_controller;
@RestController
public class testController {

    @RequestMapping("/home")
    public void home() {
        System.out.println("@@@Home Controller Called");
    }
}

POM 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany</groupId>
    <artifactId>springboot_test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>springboot_test</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <jjwt.version>0.7.0</jjwt.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jjwt.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.17</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.mobile</groupId>
            <artifactId>spring-mobile-device</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

它是一个简单的带有休息控制器的 Spring Boot 应用程序。

调用http://localhost:8084/springboot_test/会加载默认的index.html页面

问题是当我调用http://localhost:8084/springboot_test/home 时,它没有打印输出System.out.println("@@@Home Controller Called");,所以我猜这个请求不是在休息控制器本身上调用的。但是为什么不叫呢?

更新

按照@javaguy 的建议在rest Controller 上使用@ComponentScan("com.rsc.springboot_test") 有效,但我想在主类顶部应用@componentScan,以便它在启动时扫描所有包。

尝试以下会报错:

@SpringBootApplication
@ComponentScan(basePackages = { "com.rsc.*" })
public class SpringBootTest {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootTest.class, args);
    }
}

错误:

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@58f7ff2f: startup date [Wed Nov 09 21:08:20 IST 2016]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:404) [spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:253) ~[spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:578) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:554) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingleton(DefaultListableBeanFactory.java:954) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:523) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.destroySingletons(DefaultListableBeanFactory.java:961) [spring-beans-4.3.4.RELEASE.jar:4.3.4.RELEASE]


2016-11-09 21:08:20.765 ERROR 8500 --- [o-8084-exec-402] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.rsc.springboot_test.SpringBootTest]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'testController' for bean class [com.rsc.springboot_test_controller.testController] conflicts with existing, non-compatible bean definition of same name and class [com.rsc.springboot_test.controller.testController]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:180) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:324) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:246) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]

    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_102]
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'testController' for bean class [com.rsc.springboot_test_controller.testController] conflicts with existing, non-compatible bean definition of same name and class [com.rsc.springboot_test.controller.testController]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:320) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:259) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:137) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:268) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:230) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
09-Nov-2016 21:08:21.046 SEVERE [http-nio-8084-exec-402] org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start: 
 org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springboot_test]]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:166) ~[spring-context-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    ... 61 common frames omitted

    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725)

Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.rsc.springboot_test.SpringBootTest]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'testController' for bean class [com.rsc.springboot_test_controller.testController] conflicts with existing, non-compatible bean definition of same name and class [com.rsc.springboot_test.controller.testController]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:180)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:324)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:246)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270)

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'testController' for bean class [com.rsc.springboot_test_controller.testController] conflicts with existing, non-compatible bean definition of same name and class [com.rsc.springboot_test.controller.testController]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:320)


09-Nov-2016 21:08:21.200 SEVERE [http-nio-8084-exec-402] org.apache.catalina.startup.HostConfig.deployDescriptor Error deploying configuration descriptor C:\Users\Documents\AppData\Roaming\NetBeans\8.2\apache-tomcat-8.0.27.0_base\conf\Catalina\localhost\springboot_test.xml
 java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/springboot_test]]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:729)

【问题讨论】:

  • 你不应该打电话给http://localhost:8084/home吗?
  • @MarounMaroun 没有。因为调用http://localhost:8084/springboot_test/ 正在加载默认的 index.html 页面,所以我认为springboot_test/ 之后的任何内容都是对休息控制器的调用
  • SpringBootTest 类的包名是什么?添加包裹详情
  • @javaguy 使用包详细信息编辑了问题

标签: java spring spring-boot spring-restcontroller


【解决方案1】:

Spring容器没有检测到你的RestController,所以你需要将包的详细信息添加到ComponentScan,所以将main改成如下:

@SpringBootApplication
@ComponentScan(basePackages = { "com.rsc" })
public class SpringBootTest {
   public static void main(String[] args) {
    SpringApplication.run(SpringBootTest.class, args);
  }
}

另外,对于您的测试应用程序,您不需要任何 xml(因为我们使用注释并使用 componentsscan 扫描组件),您似乎已在以下路径中配置了一个:

C:\Users\Documents\AppData\Roaming\NetBeans\8.2\apache-tomcat-8.0.27.0_base\conf\Catalina\localhost\springboot_test.xml

您需要删除并重新启动服务器。

【讨论】:

  • 你是对的。但是我是否必须为我在应用程序中定义的所有其余控制器调用@ComponentScan`。不能有全局组件扫描吗?
  • 是的,现在编辑了我的答案检查,它位于 SpringBootTest 类的顶部
  • 是的,明白了。谢谢
  • 在顶级主类上提供@ComponentScan(basePackages = { "com.rsc.*" }) 会引发错误。用更新编辑了问题
  • 将控制器名称从 testController 更改为 TestController (T caps)
【解决方案2】:

@SpringBootApplication 默认情况下会在与注释类和所有子包相同的包上触发组件扫描。

在您的情况下,由于主类在 com.rsc.springboot_test 中,而控制器在 com.rsc.springboot_test_controller 中,因此不会扫描 TestController 类。

有两种方法可以解决:

  • 推荐:将TestController 移动到另一个包,以便它匹配默认的类路径扫描,例如com.rsc.springboot_test.controller
  • 修改@SpringBootApplication扫描其他包:
@SpringBootApplication(scanBasePackages = {
        "com.rsc.springboot_test",
        "com.rsc.springboot_test_controller"
})

【讨论】:

    【解决方案3】:

    您的问题是,您的 Application 课程在 ComponentScan 下。你的项目结构应该是:

    src
      main
        java
          com.company
            Application.java
            controller
              MyController.java
            service
            repository
    

    还有你的应用程序:

    @SpringBootApplication
    @ComponentScan(basePackages = { 
        "com.rsc.springboot_test_controller",
        "com.rsc.springboot_test_service",
         //etc... no ' at the end of the last package
     })
    public class SpringBootTest {
        public static void main(String[] args) {
            SpringApplication.run(SpringBootTest.class, args);
        }
    }
    

    实际上,以上是两种不同方法的混合,但会起作用。请记住,您的Application.java 应该位于所有其他包的根包中。

    再次阅读您的问题,我建议更改Controller

    package com.rsc.springboot_test_controller;
    @RestController
    public class testController {
    
        @RequestMapping("/home")
        public String home() {
            return "@@@Home Controller Called";
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-01
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      • 2019-03-27
      • 2017-07-07
      • 2019-10-09
      • 2021-06-15
      • 1970-01-01
      相关资源
      最近更新 更多