我有下面的Spring Boot控制器代码有效。(一些敏感的文本已被替换)
package com.sample.server; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbcp.BasicDataSource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; @RestController public class DetailReportController { @RequestMapping(value="/report/detail", method=RequestMethod.GET) public List<UFGroup> detailReport() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("net.sourceforge.jtds.jdbc.Driver"); dataSource.setUrl("jdbc:jtds:sqlserver://111.11.11.11/DataBaseName;user=sa;password=password"); JdbcTemplate jt = new JdbcTemplate(dataSource); List<UFGroup> results = jt.query( "select NID, SCode, SName from UFGroup", new RowMapper<UFGroup>() { @Override public UFGroup mapRow(ResultSet rs, int rowNum) throws SQLException { return new UFGroup(rs.getInt("NID"), rs.getString("SCode"), rs.getString("SName")); } }); return results; } private static class UFGroup { public int nid; public String scode; public String sname; public UFGroup(int nid, String scode, String sname) { this.nid = nid; this.scode = scode; this.sname = sname; } } }
现在,我要外部化数据源的配置。也就是说,应将BasicDataSource类,驱动程序类名称,数据源URL放入application.properties。我怎样才能做到这一点?
顺便说一句,我是Spring,Spring Boot甚至Java Bean的新手。我所拥有的只是一些Java编程经验,主要是针对移动设备的。我花了几天时间研究Spring Boot环境,但是我实在不知所措。因此,请给出具体示例的确切说明。
UPDATE :当我应用M. Deinum的答案时,运行应用程序时发生以下错误:
2013-11-18 19:37:54.789 INFO 6868 --- [ main] com.logicplant.uflow.server.Application : Starting Application on zeo-PC with PID 6868 (C:\Projects\uFlow\Dev\Server\Spring\uFlowServer\build\libs\uFlowServer-1.0.0.jar started by zeo) 2013-11-18 19:37:54.830 INFO 6868 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7f83698f: startup date [Mon Nov 18 19:37:54 KST 2013]; root of context hierarchy 2013-11-18 19:37:55.931 INFO 6868 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 2013-11-18 19:37:55.932 INFO 6868 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.42 2013-11-18 19:37:56.009 INFO 6868 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2013-11-18 19:37:56.010 INFO 6868 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1183 ms 2013-11-18 19:37:56.165 INFO 6868 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet' 2013-11-18 19:37:56.165 INFO 6868 --- [ost-startStop-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2013-11-18 19:37:56.242 INFO 6868 --- [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] 2013-11-18 19:37:56.388 INFO 6868 --- [ost-startStop-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/report/detail],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.List<com.logicplant.uflow.server.DetailReportController$UFGroup> com.logicplant.uflow.server.DetailReportController.detailReport() 2013-11-18 19:37:56.438 INFO 6868 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2013-11-18 19:37:56.439 INFO 6868 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2013-11-18 19:37:56.788 INFO 6868 --- [ost-startStop-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 622 ms 2013-11-18 19:37:56.881 INFO 6868 --- [ main] o.apache.catalina.core.StandardService : Stopping service Tomcat java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:53) at java.lang.Thread.run(Unknown Source) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'detailReportController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.logicplant.uflow.server.DetailReportController.jt; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1139) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:299) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:295) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:665) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:509) at org.springframework.boot.SpringApplication.run(SpringApplication.java:278) at com.logicplant.uflow.server.Application.main(Application.java:17) ... 6 more Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.logicplant.uflow.server.DetailReportController.jt; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:505) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ... 20 more Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1051) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:919) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:820) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:477) ... 22 more
作为参考,build.grade文件的内容(我使用Gradle)如下:(按照M. Deinum的建议,我删除了对org.apache.commons.dbcp的依赖。)
buildscript { repositories { maven { url "http://repo.spring.io/libs-snapshot" } mavenLocal() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M5") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'spring-boot' jar { baseName = 'uFlowServer' version = '1.0.0' } repositories { mavenCentral() maven { url "http://repo.spring.io/libs-snapshot" } } dependencies { compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M5") compile("com.fasterxml.jackson.core:jackson-databind") compile("org.springframework:spring-jdbc:4.0.0.M3") runtime("net.sourceforge.jtds:jtds:1.3.1") testCompile("junit:junit:4.11") } task wrapper(type: Wrapper) { gradleVersion = '1.8' }
这是Application.java文件,它是主要的源文件。
package com.sample.server; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @EnableAutoConfiguration @ComponentScan public class Application { public static void main(String args[]) { SpringApplication app = new SpringApplication(Application.class); app.setShowBanner(false); app.run(args); } }
该错误怎么办?
更新 :正如M. Deinum所建议的那样,当我如下更改build.gradle文件时,该应用程序开始工作了!
buildscript { repositories { maven { url "http://repo.spring.io/libs-snapshot" } mavenLocal() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M6") } } apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'spring-boot' jar { baseName = 'uFlowServer' version = '1.0.0' } repositories { mavenCentral() maven { url "http://repo.spring.io/libs-snapshot" } } dependencies { compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M6") compile("org.springframework.boot:spring-boot-starter-jdbc:0.5.0.M6") compile("com.fasterxml.jackson.core:jackson-databind") runtime("net.sourceforge.jtds:jtds:1.3.1") testCompile("junit:junit:4.11") } task wrapper(type: Wrapper) { gradleVersion = '1.8' }
将您的控制器更改为以下内容
@RestController public class DetailReportController { @Autowired private JdbcTemplate jt; @RequestMapping(value="/report/detail", method=RequestMethod.GET) public List<UFGroup> detailReport() { List<UFGroup> results = jt.query( "select NID, SCode, SName from UFGroup", new RowMapper<UFGroup>(){ @Override public UFGroup mapRow(ResultSet rs, int rowNum) throws SQLException { return new UFGroup(rs.getInt("NID"), rs.getString("SCode"), rs.getString("SName")); } }); return results; } private static class UFGroup { public int nid; public String scode; public String sname; public UFGroup(int nid, String scode, String sname) { this.nid = nid; this.scode = scode; this.sname = sname; } } }
在src/main/resources添加application.properties以下内容
src/main/resources
application.properties
spring.datasource.driverClassName=net.sourceforge.jtds.jdbc.Driver spring.datasource.url=jdbc:jtds:sqlserver://111.11.11.11/DataBaseName spring.datasource.username=sa spring.datasource.password=password
只需启动您的应用程序。无需xml。Spring Boot将创建DataSource并添加一个默认JdbcTemplate实例。
DataSource
JdbcTemplate
提示:删除org.apache.commons.dbcpspring-boot 的依赖关系将为您提供更新的(更好的IMHO)tomcat连接池(尽管名称可以完全单独使用)。
org.apache.commons.dbcp