在StackOverflow上搜索了各种类似的问题之后,我确定大多数遭受此问题困扰的人都无法正确扫描其控制器所在的模块。一些解决方案要求将要扫描的文件与应用程序(有效)组合到同一模块中,但是我不想移动任何.java文件。相反,我想使@ComponentScan
工作。
我具有以下项目结构
Project
|
settings.gradle
build.gradle
module1
|
src/main/java/com.test.application
| |
| Application.java
| SwaggerConfig.java
build.gradle
module2
|
src/main/java/com.test.service
| |
| Service.java
| Controller.java
build.gradle
Application.java
@SpringBootApplication
@ComponentScan("com.test")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
请注意,我正在组件扫描中扫描com.test
。我在@ComponentScan documentation(或StackOverflow)上找不到任何暗示我在错误使用@ComponentScan
的东西。
Controller.java
@RestController
@RequestMapping("/test")
public class GearParsingController {
private SomeService someService;
@Autowired
public SomeController(SomeService someService) {
this.someService = someService;
}
@GetMapping("/path")
public ResponseEntity<String> getSomeService() {
return new ResponseEntity<String>("Default message", HttpStatus.OK);
}
}
项目build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE")
}
}
subprojects {
repositories {
mavenCentral()
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
}
module1 build.gradle
dependencies {
implementation project(':module2')
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.6.RELEASE'
}
module2 build.gradle
dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.6.RELEASE'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0-RC2'
}
当我尝试访问位于localhost:8080/test/path
的端点时,我遇到了:
{
"timestamp": "2019-06-29T19:19:52.275+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/test/path"
}
在调试模式下启动程序时,得到以下输出:
2019-06-29 13:58:58.345 INFO 8272 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-06-29 13:58:58.387 INFO 8272 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-06-29 13:58:58.387 INFO 8272 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.21]
2019-06-29 13:58:58.522 INFO 8272 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-06-29 13:58:58.522 DEBUG 8272 --- [ main] o.s.web.context.ContextLoader : Published root WebApplicationContext as ServletContext attribute with name [org.springframework.web.context.WebApplicationContext.ROOT]
2019-06-29 13:58:58.522 INFO 8272 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1786 ms
2019-06-29 13:58:58.544 DEBUG 8272 --- [ main] o.s.b.w.s.ServletContextInitializerBeans : Mapping filters: characterEncodingFilter urls=[/*], hiddenHttpMethodFilter urls=[/*], formContentFilter urls=[/*], requestContextFilter urls=[/*]
2019-06-29 13:58:58.545 DEBUG 8272 --- [ main] o.s.b.w.s.ServletContextInitializerBeans : Mapping servlets: dispatcherServlet urls=[/]
2019-06-29 13:58:58.583 DEBUG 8272 --- [ main] o.s.b.w.s.f.OrderedRequestContextFilter : Filter 'requestContextFilter' configured for use
2019-06-29 13:58:58.583 DEBUG 8272 --- [ main] .s.b.w.s.f.OrderedHiddenHttpMethodFilter : Filter 'hiddenHttpMethodFilter' configured for use
2019-06-29 13:58:58.583 DEBUG 8272 --- [ main] s.b.w.s.f.OrderedCharacterEncodingFilter : Filter 'characterEncodingFilter' configured for use
2019-06-29 13:58:58.584 DEBUG 8272 --- [ main] o.s.b.w.s.f.OrderedFormContentFilter : Filter 'formContentFilter' configured for use
2019-06-29 13:58:58.896 DEBUG 8272 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : 5 mappings in 'requestMappingHandlerMapping'
2019-06-29 13:58:58.990 INFO 8272 --- [ main] pertySourcedRequestMappingHandlerMapping : Mapped URL path [/v2/api-docs] onto method [public org.springframework.http.ResponseEntity<springfox.documentation.spring.web.json.Json> springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(java.lang.String,javax.servlet.http.HttpServletRequest)]
2019-06-29 13:58:59.045 DEBUG 8272 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Patterns [/**/favicon.ico] in 'faviconHandlerMapping'
2019-06-29 13:58:59.128 INFO 8272 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-06-29 13:58:59.146 DEBUG 8272 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice
2019-06-29 13:58:59.257 DEBUG 8272 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Patterns [/webjars/**, /**] in 'resourceHandlerMapping'
2019-06-29 13:58:59.263 DEBUG 8272 --- [ main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice
2019-06-29 13:58:59.442 INFO 8272 --- [ main] d.s.w.p.DocumentationPluginsBootstrapper : Context refreshed
2019-06-29 13:58:59.481 INFO 8272 --- [ main] d.s.w.p.DocumentationPluginsBootstrapper : Found 1 custom documentation plugin(s)
2019-06-29 13:58:59.519 INFO 8272 --- [ main] s.d.s.w.s.ApiListingReferenceScanner : Scanning for api listing references
所以,我的问题是:为什么ComponentScan无法检测到我的REST控制器?
答案 0 :(得分:1)
以这种方式制作文件:
项目build.gradle (已将spring插件应用程序删除到所有模块项目中)
@app.route('/hook/reservation', methods=['POST'])
def fn_th_reservation():
task_attributes = json.loads(request.form['TaskAttributes'])
channel_sid = task_attributes["channelSid"]
worker_sid = request.form['WorkerSid']
reservation_sid = request.form["ReservationSid"]
workspace_sid = request.form["WorkspaceSid"]
task_sid = request.form["TaskSid"]
# implement app specific logic here. you can use channel_sid and
# worker_sid to compare them to a mapping from you database for instance
is_right_worker = ...
reservation_status = 'accepted' if is_right_worker else 'rejected'
client = Client(account_sid, auth_token)
# accept or reject reservation
reservation = client.taskrouter.workspaces(workspace_sid) \
.tasks(task_sid).reservations(reservation_sid) \
.update(reservation_status=reservation_status)
print(reservation.worker_name)
print(reservation.reservation_status)
return('200')
module1 build.gradle (应用spring插件和bootJar目标)
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE")
}
}
subprojects {
repositories {
mavenCentral()
}
apply plugin: 'java'
apply plugin: 'idea'
}
module2 build.gradle (添加了jar目标)
dependencies {
implementation project(':module2')
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.6.RELEASE'
}
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'module1'
version = '0.0.1-SNAPSHOT'
}
settings.gradle
dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.6.RELEASE'
}
jar {
baseName = 'module2'
version = '0.0.1-SNAPSHOT'
}
要点是,我们希望将第二个模块构建为普通jar,而将主模块构建为spring boot runnable。通过该设置,只需include 'module1'
include 'module2'
,然后从主项目文件夹中gradle build
。
答案 1 :(得分:0)
我认为,如果您想从“ com.test”包中提取控制器,请使用@ComponentScan的basePackages选项:
@ComponentScan(basePackages = "com.test")
答案 2 :(得分:0)
您的主应用程序Application.java
位于目录com.test.application
下,这意味着默认情况下,当springboot应用程序启动时,@SpringBootApplication
注释将在packgae {{下查找bean和配置。 1}}。在springboot documentation中,我们指定应将Main应用程序放在根软件包下,以便spring扫描其下的所有内容。
@SpringBootApplication是一个方便注释,它添加了所有 以下:
- @Configuration将类标记为应用程序上下文的bean定义的源。
- @EnableAutoConfiguration告诉Spring Boot根据类路径设置,其他bean和各种属性开始添加bean
设置。- 通常,您会为Spring MVC应用添加@EnableWebMvc,但是当Spring Boot在服务器上看到spring-webmvc时,它会自动添加它。 类路径。这会将应用程序标记为Web应用程序,
激活关键行为,例如设置DispatcherServlet。- @ComponentScan告诉Spring在hello包中查找其他组件,配置和服务,以使其
找到控制器。
因此,要解决您的问题,请尝试将主应用程序移至软件包的根目录
com.test.application
,也可以使用注释com.test
来指定需要扫描哪些所有软件包,如:
@ComponentScan
答案 3 :(得分:0)
根据Spring Boot约定,控制器必须位于com.test.controller
包中。