最近由于用到spring boot这个框架,于是乎就对着官方的文档开始学习了spring boot,由于是新接触spring boot,导致一开始遇到各种各样的问题的,排查也花了很长的时间,这里对就简单的对新建一个工程和出现的相应的问题排查过程做一个记录,方便大家参考。由于是初学者,可能也有很多的不对的地方,希望大家指正。
首先,学习spring boot最好的资料,当然是官方的文档,这里贴上官方文档的地址:
https://docs.spring.io/spring-boot/docs/2.0.0.M6/reference/htmlsingle/
按照官方的文档,建立一个spring boot的工程有很多中方法,这里我们采用最常见的eclipse的来建一个web工程
1. 首先,按照如下操作 “右击”---> “import"--->“maven project” 然后创建一个新的maven工程
在如下的窗口中填写group Id和Artifact Id 然后选择下一步
填写好之后,我们得到了如下的maven结构的工程项目,首先,我们要在pom.xml中添加对应的maven依赖,这个可以直接从spring的官方demo中拷贝,这个有哪些注释不懂的地方,请参考官方文档。
<?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.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M6</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- Package as an executable jar -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- Add Spring repositories -->
<!-- (you don't need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
在配置好了Maven依赖之后,接下来的事情,就是要配置启动类,在App.java中,我们添加注解SpringbootApplication,然后启动spring boot程序,spring boot一个明显的优势,就是提供了很多的注解,避免了spring很多的xml的配置,同时优化了很多的注解。
@SpringBootApplication
public class App {
public static void main( String[] args ) {
SpringApplication.run(App.class, args);
}
}
具体的代码如下,在这里我们添加注解@Controller,这里面只有一个方法home,返回结果是字符串“hello world",在这里我们通过/index,这里添加了两个注解@RequestMapping和@ResponseBody,具体的含义,可以查看官方文档。
@Controller
public class HomeController {
@RequestMapping(value="/index")
@ResponseBody
public String home(){
return "hello world";
}
}
配置好之后,我们启动spring boot容器,由于内部内置了tomcat的容器,所以直接启动就行了,看到启动日志如下,说明容器启动成功了
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.0.M6)
2017-11-08 12:48:16.518 INFO 48353 --- [ main] com.spring.app.App : Starting App on fhldeMacBook-Air.local with PID 48353 (/Users/fhl/Documents/project_1/spring-test/spring-test01/target/classes started by fhl in /Users/fhl/Documents/project_1/spring-test/spring-test01)
2017-11-08 12:48:16.525 INFO 48353 --- [ main] com.spring.app.App : No active profile set, falling back to default profiles: default
2017-11-08 12:48:16.656 INFO 48353 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@5223e5ee: startup date [Wed Nov 08 12:48:16 CST 2017]; root of context hierarchy
2017-11-08 12:48:19.350 INFO 48353 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$fa2a7ef0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-11-08 12:48:20.275 INFO 48353 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2017-11-08 12:48:20.294 INFO 48353 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2017-11-08 12:48:20.296 INFO 48353 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.23
2017-11-08 12:48:20.326 INFO 48353 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/fhl/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2017-11-08 12:48:20.513 INFO 48353 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2017-11-08 12:48:20.513 INFO 48353 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3864 ms
2017-11-08 12:48:21.262 WARN 48353 --- [ost-startStop-1] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2017-11-08 12:48:21.617 INFO 48353 --- [ost-startStop-1] com.zaxxer.hikari.HikariDataSource : testdb - Starting...
2017-11-08 12:48:22.059 INFO 48353 --- [ost-startStop-1] com.zaxxer.hikari.HikariDataSource : testdb - Start completed.
2017-11-08 12:48:22.202 INFO 48353 --- [ost-startStop-1] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2017-11-08 12:48:22.243 INFO 48353 --- [ost-startStop-1] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2017-11-08 12:48:22.428 INFO 48353 --- [ost-startStop-1] org.hibernate.Version : HHH000412: Hibernate Core {5.2.12.Final}
2017-11-08 12:48:22.431 INFO 48353 --- [ost-startStop-1] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2017-11-08 12:48:22.513 INFO 48353 --- [ost-startStop-1] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2017-11-08 12:48:22.713 INFO 48353 --- [ost-startStop-1] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2017-11-08 12:48:23.241 INFO 48353 --- [ost-startStop-1] o.h.t.schema.internal.SchemaCreatorImpl : HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@118f0fa4'
2017-11-08 12:48:23.247 INFO 48353 --- [ost-startStop-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2017-11-08 12:48:23.390 INFO 48353 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/index]}" onto public java.lang.String com.spring.app.controller.HomeController.home()
2017-11-08 12:48:23.407 INFO 48353 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-11-08 12:48:23.409 INFO 48353 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-11-08 12:48:23.492 INFO 48353 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-11-08 12:48:23.492 INFO 48353 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-11-08 12:48:23.574 INFO 48353 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-11-08 12:48:24.262 INFO 48353 --- [ost-startStop-1] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/application/status],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2017-11-08 12:48:24.263 INFO 48353 --- [ost-startStop-1] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/application/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2017-11-08 12:48:24.265 INFO 48353 --- [ost-startStop-1] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/application],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto private java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest)
2017-11-08 12:48:24.411 INFO 48353 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2017-11-08 12:48:24.427 INFO 48353 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webMetricsFilter' to: [/*]
2017-11-08 12:48:24.435 INFO 48353 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-11-08 12:48:24.436 INFO 48353 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-11-08 12:48:24.437 INFO 48353 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-11-08 12:48:24.438 INFO 48353 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2017-11-08 12:48:24.439 INFO 48353 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*]
2017-11-08 12:48:25.243 INFO 48353 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@5223e5ee: startup date [Wed Nov 08 12:48:16 CST 2017]; root of context hierarchy
2017-11-08 12:48:25.397 WARN 48353 --- [ main] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
2017-11-08 12:48:26.168 INFO 48353 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2017-11-08 12:48:26.170 INFO 48353 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'dataSource' has been autodetected for JMX exposure
2017-11-08 12:48:26.186 INFO 48353 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2017-11-08 12:48:26.309 INFO 48353 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http)
2017-11-08 12:48:26.316 INFO 48353 --- [ main] com.spring.app.App : Started App in 10.699 seconds (JVM running for 11.348)
2017-11-08 12:48:56.565 INFO 48353 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-11-08 12:48:56.565 INFO 48353 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2017-11-08 12:48:56.598 INFO 48353 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 33 ms
2017-11-08 16:58:53.073 WARN 48353 --- [tdb housekeeper] com.zaxxer.hikari.pool.HikariPool : testdb - Thread starvation or clock leap detected (housekeeper delta=4h9m30s640ms).
2017-11-08 20:18:09.840 WARN 48353 --- [tdb housekeeper] com.zaxxer.hikari.pool.HikariPool : testdb - Thread starvation or clock leap detected (housekeeper delta=2h58m46s520ms).
容器启动成功之后,我们可以通过浏览器访问了 http://localhost:8080/index,但是我们页面上并没有看到我们期望的hell word,却是如下的错误,这说明的我们的Controller初始化失败。。。。一脸懵逼,这是为啥?
针对以上的问题,查了很多资料,Google了,百度了,还是没找到为啥出错,最后看到一个网友说,可能是controller初始化失败,没有扫描到该controller注解,然后又去翻阅官方的资料。发现SpringBootApplication注解虽然相当于spring的三个注解之和,
@EnableAutoConfiguration 和 @ComponentScan和@Configuration,于是有怀疑是不是@ComponentScan,启动扫描的注解没加上,然后没扫描到这个Controller,加上之后还是不行,于是去查官方文档,终于发现了如下...
@SpringBootApplication 相当于spring的三个注解的作用,但是其他注解如果想要被扫描掉,就必须和该类在同一级目录下,或者子目录下。
然后我又去查看项目的结构,反向App.java的目录结构com.spring.app包下面,而HomeController.java在com.spring.controller下,就是说Controller不在App.java的同级目录或者子目录下,自然是扫描到,于是做了如下修改。
然后重新启动spring boot程序,在浏览器中访问http://localhost:8080/index,然后得到了后面的我们想要的结果
此致,我们是首个spring boot的容器总算成功的搭建起来了,事后,我又分析了一下两者之间的启动日志,其实从日志中也能看出一点端倪,首先,我们看启动失败的日志
在如下的日志中,并没有看到配置的请求路径/index说明该controller并没有被初始化
随后,我们看下如下的正却的日志中,出现了我们在Controller中配置的映射的URL,如图所示:,说明我们配置的注解成功了。
Mapped "{[/index]}" onto public java.lang.String com.spring.app.controller.HomeController.home()
鉴于此,总算找到了个这个问题的根源,再次记录一下,希望给大家提供参考,虽然是一点小问题,可能有的时候,真的要花很长时间排查。