我有以下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 Beans的新手。我所拥有的只是一些Java编程经验,主要用于移动设备。我花了几天时间研究Spring Boot环境,但我真的不知所措。 所以,请用具体的例子给我一个确切的指示。更新: 当我应用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'
}
答案 0 :(得分:19)
将您的控制器更改为以下
@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
以及
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启动将创建DataSource
并将添加默认的JdbcTemplate
实例。
提示:删除org.apache.commons.dbcp
spring-boot的依赖项将为您提供更新的(和更好的IMHO)tomcat连接池(尽管名称可以完全独立使用)。
答案 1 :(得分:0)
我会以更好的方法重新编码您的代码。
首先,在使用Spring时不需要在代码中使用new运算符,因此可以使用Spring的强大功能,即依赖注入。
@RestController
public class DetailReportController
{ @Required
private JdbcTemplate jt;
//setter for the same
@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;
}
}
}
应用context.xml中
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="16000"/>
<property name="minIdle" value="0"/>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database.properties</value>
</property>
</bean>
<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate;">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="detailReportController" class="your class">
<property name="jt" ref="jt"/>
</bean>
另一个建议是你可以在DAO类中移动与数据库相关的代码,如果你想坚持你的方法,那么在Controller.Else中使用相同的非常糟糕的做法是使用java.util包的Properties类