spring boot tomcat jdbc pool的属性绑定

下面看下spring boot tomcat jdbc pool的属性绑定代码,具体代码如下所示:

spring:
 datasource:
 type: org.apache.tomcat.jdbc.pool.DataSource
 driver-class-name: org.postgresql.Driver
 url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000
 username: postgres
 password: postgres
 jmx-enabled: true
 initial-size: 1
 max-active: 5
 ## when pool sweeper is enabled, extra idle connection will be closed
 max-idle: 5
 ## when idle connection > min-idle, poolSweeper will start to close
 min-idle: 1

使用如上配置,最后发现initial-size,max-active,max-idle,min-idle等配置均无效,生成的tomcat jdbc datasource还是使用的默认的配置

正确配置

spring:
 datasource:
 type: org.apache.tomcat.jdbc.pool.DataSource
 driver-class-name: org.postgresql.Driver
 url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000
 username: postgres
 password: postgres
 jmx-enabled: true
 tomcat: ## 单个数据库连接池,而且得写上tomcat的属性配置才可以生效
  initial-size: 1
  max-active: 5
  ## when pool sweeper is enabled, extra idle connection will be closed
  max-idle: 5
  ## when idle connection > min-idle, poolSweeper will start to close
  min-idle: 1

注意,这里把具体tomcat数据库连接池的配置属性放到了spring.datasource.tomcat属性下面,这样才可以生效。

源码解析

spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java
@Configuration
 @Conditional(PooledDataSourceCondition.class)
 @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
 @Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
 DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,
 DataSourceConfiguration.Generic.class })
 @SuppressWarnings("deprecation")
 protected static class PooledDataSourceConfiguration {
 }

DataSourceConfiguration.Tomcat

spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration.java
/**
 * Tomcat Pool DataSource configuration.
 */
 @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
 @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)
 static class Tomcat extends DataSourceConfiguration {
 @Bean
 @ConfigurationProperties(prefix = "spring.datasource.tomcat")
 public org.apache.tomcat.jdbc.pool.DataSource dataSource(
 DataSourceProperties properties) {
 org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(
  properties, org.apache.tomcat.jdbc.pool.DataSource.class);
 DatabaseDriver databaseDriver = DatabaseDriver
  .fromJdbcUrl(properties.determineUrl());
 String validationQuery = databaseDriver.getValidationQuery();
 if (validationQuery != null) {
 dataSource.setTestOnBorrow(true);
 dataSource.setValidationQuery(validationQuery);
 }
 return dataSource;
 }
 }

可以看到这里的DataSourceProperties仅仅只有spring.datasource直接属性的配置,比如url,username,password,driverClassName。tomcat的具体属性都没有。

createDataSource

protected <T> T createDataSource(DataSourceProperties properties,
 Class<? extends DataSource> type) {
 return (T) properties.initializeDataSourceBuilder().type(type).build();
 }

直接createDataSource出来的org.apache.tomcat.jdbc.pool.DataSource的PoolProperties也是默认的配置

ConfigurationProperties

具体的魔力就在于@ConfigurationProperties(prefix = "spring.datasource.tomcat")这段代码,它在spring容器构造好代理bean返回之前会将spring.datasource.tomcat指定的属性设置到org.apache.tomcat.jdbc.pool.DataSource

spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java
private void postProcessBeforeInitialization(Object bean, String beanName,
 ConfigurationProperties annotation) {
 Object target = bean;
 PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(
 target);
 factory.setPropertySources(this.propertySources);
 factory.setValidator(determineValidator(bean));
 // If no explicit conversion service is provided we add one so that (at least)
 // comma-separated arrays of convertibles can be bound automatically
 factory.setConversionService(this.conversionService == null
 ? getDefaultConversionService() : this.conversionService);
 if (annotation != null) {
 factory.setIgnoreInvalidFields(annotation.ignoreInvalidFields());
 factory.setIgnoreUnknownFields(annotation.ignoreUnknownFields());
 factory.setExceptionIfInvalid(annotation.exceptionIfInvalid());
 factory.setIgnoreNestedProperties(annotation.ignoreNestedProperties());
 if (StringUtils.hasLength(annotation.prefix())) {
 factory.setTargetName(annotation.prefix());
 }
 }
 try {
 factory.bindPropertiesToTarget();
 }
 catch (Exception ex) {
 String targetClass = ClassUtils.getShortName(target.getClass());
 throw new BeanCreationException(beanName, "Could not bind properties to "
  + targetClass + " (" + getAnnotationDetails(annotation) + ")", ex);
 }
 }

注意,这里的annotation就是@ConfigurationProperties(prefix = "spring.datasource.tomcat"),它的prefix是spring.datasource.tomcat PropertiesConfigurationFactory的targetName就是spring.datasource.tomcat

PropertiesConfigurationFactory.bindPropertiesToTarget
spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/PropertiesConfigurationFactory.java
public void bindPropertiesToTarget() throws BindException {
 Assert.state(this.propertySources != null, "PropertySources should not be null");
 try {
 if (logger.isTraceEnabled()) {
 logger.trace("Property Sources: " + this.propertySources);
 }
 this.hasBeenBound = true;
 doBindPropertiesToTarget();
 }
 catch (BindException ex) {
 if (this.exceptionIfInvalid) {
 throw ex;
 }
 PropertiesConfigurationFactory.logger
  .error("Failed to load Properties validation bean. "
  + "Your Properties may be invalid.", ex);
 }
 }

委托给doBindPropertiesToTarget方法

PropertiesConfigurationFactory.doBindPropertiesToTarget
private void doBindPropertiesToTarget() throws BindException {
 RelaxedDataBinder dataBinder = (this.targetName != null
 ? new RelaxedDataBinder(this.target, this.targetName)
 : new RelaxedDataBinder(this.target));
 if (this.validator != null
 && this.validator.supports(dataBinder.getTarget().getClass())) {
 dataBinder.setValidator(this.validator);
 }
 if (this.conversionService != null) {
 dataBinder.setConversionService(this.conversionService);
 }
 dataBinder.setAutoGrowCollectionLimit(Integer.MAX_VALUE);
 dataBinder.setIgnoreNestedProperties(this.ignoreNestedProperties);
 dataBinder.setIgnoreInvalidFields(this.ignoreInvalidFields);
 dataBinder.setIgnoreUnknownFields(this.ignoreUnknownFields);
 customizeBinder(dataBinder);
 Iterable<String> relaxedTargetNames = getRelaxedTargetNames();
 Set<String> names = getNames(relaxedTargetNames);
 PropertyValues propertyValues = getPropertySourcesPropertyValues(names,
 relaxedTargetNames);
 dataBinder.bind(propertyValues);
 if (this.validator != null) {
 dataBinder.validate();
 }
 checkForBindingErrors(dataBinder);
 }

这里借助RelaxedDataBinder.bind方法

getRelaxedTargetNames
private Iterable<String> getRelaxedTargetNames() {
 return (this.target != null && StringUtils.hasLength(this.targetName)
 ? new RelaxedNames(this.targetName) : null);
 }

这里new了一个RelaxedNames,可以识别多个变量的变种

RelaxedNames

spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/RelaxedNames.java
private void initialize(String name, Set<String> values) {
 if (values.contains(name)) {
 return;
 }
 for (Variation variation : Variation.values()) {
 for (Manipulation manipulation : Manipulation.values()) {
 String result = name;
 result = manipulation.apply(result);
 result = variation.apply(result);
 values.add(result);
 initialize(result, values);
 }
 }
 }
 /**
 * Name variations.
 */
 enum Variation {
 NONE {
 @Override
 public String apply(String value) {
 return value;
 }
 },
 LOWERCASE {
 @Override
 public String apply(String value) {
 return value.isEmpty() ? value : value.toLowerCase();
 }
 },
 UPPERCASE {
 @Override
 public String apply(String value) {
 return value.isEmpty() ? value : value.toUpperCase();
 }
 };
 public abstract String apply(String value);
 }

即支持org.springframework.boot.bind.RelaxedNames@6ef81f31[name=spring.datasource.tomcat,values=[spring.datasource.tomcat, spring_datasource_tomcat, springDatasourceTomcat, springdatasourcetomcat, SPRING.DATASOURCE.TOMCAT, SPRING_DATASOURCE_TOMCAT, SPRINGDATASOURCETOMCAT]]这7中配置的写法

getPropertySourcesPropertyValues
private PropertyValues getPropertySourcesPropertyValues(Set<String> names,
 Iterable<String> relaxedTargetNames) {
 PropertyNamePatternsMatcher includes = getPropertyNamePatternsMatcher(names,
 relaxedTargetNames);
 return new PropertySourcesPropertyValues(this.propertySources, names, includes,
 this.resolvePlaceholders);
 }

这个方法会把spring.datasource.tomact底下的属性配置拉取到PropertyValues对象里头

RelaxedDataBinder.bind

spring-boot-1.5.9.RELEASE-sources.jar!/org/springframework/boot/bind/RelaxedDataBinder.java的bind方法调用的是父类的方法 spring-context-4.3.13.RELEASE-sources.jar!/org/springframework/validation/DataBinder.java
/**
 * Bind the given property values to this binder's target.
 * <p>This call can create field errors, representing basic binding
 * errors like a required field (code "required"), or type mismatch
 * between value and bean property (code "typeMismatch").
 * <p>Note that the given PropertyValues should be a throwaway instance:
 * For efficiency, it will be modified to just contain allowed fields if it
 * implements the MutablePropertyValues interface; else, an internal mutable
 * copy will be created for this purpose. Pass in a copy of the PropertyValues
 * if you want your original instance to stay unmodified in any case.
 * @param pvs property values to bind
 * @see #doBind(org.springframework.beans.MutablePropertyValues)
 */
 public void bind(PropertyValues pvs) {
 MutablePropertyValues mpvs = (pvs instanceof MutablePropertyValues) ?
 (MutablePropertyValues) pvs : new MutablePropertyValues(pvs);
 doBind(mpvs);
 }
 /**
 * Actual implementation of the binding process, working with the
 * passed-in MutablePropertyValues instance.
 * @param mpvs the property values to bind,
 * as MutablePropertyValues instance
 * @see #checkAllowedFields
 * @see #checkRequiredFields
 * @see #applyPropertyValues
 */
 protected void doBind(MutablePropertyValues mpvs) {
 checkAllowedFields(mpvs);
 checkRequiredFields(mpvs);
 applyPropertyValues(mpvs);
 }
 /**
 * Apply given property values to the target object.
 * <p>Default implementation applies all of the supplied property
 * values as bean property values. By default, unknown fields will
 * be ignored.
 * @param mpvs the property values to be bound (can be modified)
 * @see #getTarget
 * @see #getPropertyAccessor
 * @see #isIgnoreUnknownFields
 * @see #getBindingErrorProcessor
 * @see BindingErrorProcessor#processPropertyAccessException
 */
 protected void applyPropertyValues(MutablePropertyValues mpvs) {
 try {
 // Bind request parameters onto target object.
 getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields());
 }
 catch (PropertyBatchUpdateException ex) {
 // Use bind error processor to create FieldErrors.
 for (PropertyAccessException pae : ex.getPropertyAccessExceptions()) {
 getBindingErrorProcessor().processPropertyAccessException(pae, getInternalBindingResult());
 }
 }
 }
 /**
 * Return the underlying PropertyAccessor of this binder's BindingResult.
 */
 protected ConfigurablePropertyAccessor getPropertyAccessor() {
 return getInternalBindingResult().getPropertyAccessor();
 }

最后通过getPropertyAccessor()来设置,这个propertyAccessor就是org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanWrapper: wrapping object [org.apache.tomcat.jdbc.pool.DataSource@6a84bc2a],也就包装的org.apache.tomcat.jdbc.pool.DataSource

AbstractPropertyAccessor.setPropertyValues
spring-beans-4.3.13.RELEASE-sources.jar!/org/springframework/beans/AbstractPropertyAccessor.java
@Override
 public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
 throws BeansException {
 List<PropertyAccessException> propertyAccessExceptions = null;
 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ?
 ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues()));
 for (PropertyValue pv : propertyValues) {
 try {
 // This method may throw any BeansException, which won't be caught
 // here, if there is a critical failure such as no matching field.
 // We can attempt to deal only with less serious exceptions.
 setPropertyValue(pv);
 }
 catch (NotWritablePropertyException ex) {
 if (!ignoreUnknown) {
  throw ex;
 }
 // Otherwise, just ignore it and continue...
 }
 catch (NullValueInNestedPathException ex) {
 if (!ignoreInvalid) {
  throw ex;
 }
 // Otherwise, just ignore it and continue...
 }
 catch (PropertyAccessException ex) {
 if (propertyAccessExceptions == null) {
  propertyAccessExceptions = new LinkedList<PropertyAccessException>();
 }
 propertyAccessExceptions.add(ex);
 }
 }
 // If we encountered individual exceptions, throw the composite exception.
 if (propertyAccessExceptions != null) {
 PropertyAccessException[] paeArray =
  propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
 throw new PropertyBatchUpdateException(paeArray);
 }
 }
 @Override
 public void setPropertyValue(PropertyValue pv) throws BeansException {
 PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
 if (tokens == null) {
 String propertyName = pv.getName();
 AbstractNestablePropertyAccessor nestedPa;
 try {
 nestedPa = getPropertyAccessorForPropertyPath(propertyName);
 }
 catch (NotReadablePropertyException ex) {
 throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
  "Nested property in path '" + propertyName + "' does not exist", ex);
 }
 tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
 if (nestedPa == this) {
 pv.getOriginalPropertyValue().resolvedTokens = tokens;
 }
 nestedPa.setPropertyValue(tokens, pv);
 }
 else {
 setPropertyValue(tokens, pv);
 }
 }

这里的nestedPa.setPropertyValue(tokens, pv);真正把spring.datasource.tomcat的属性值设置进去 这里的nestedPa就是org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanWrapper: wrapping object [org.apache.tomcat.jdbc.pool.DataSource@6a84bc2a] 最后是调用AbstractNestablePropertyAccessor.processLocalProperty

AbstractNestablePropertyAccessor.processLocalProperty
spring-beans-4.3.13.RELEASE-sources.jar!/org/springframework/beans/AbstractNestablePropertyAccessor.java
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) {
 PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
 if (ph == null || !ph.isWritable()) {
 if (pv.isOptional()) {
 if (logger.isDebugEnabled()) {
  logger.debug("Ignoring optional value for property '" + tokens.actualName +
  "' - property not found on bean class [" + getRootClass().getName() + "]");
 }
 return;
 }
 else {
 throw createNotWritablePropertyException(tokens.canonicalName);
 }
 }
 Object oldValue = null;
 try {
 Object originalValue = pv.getValue();
 Object valueToApply = originalValue;
 if (!Boolean.FALSE.equals(pv.conversionNecessary)) {
 if (pv.isConverted()) {
  valueToApply = pv.getConvertedValue();
 }
 else {
  if (isExtractOldValueForEditor() && ph.isReadable()) {
  try {
  oldValue = ph.getValue();
  }
  catch (Exception ex) {
  if (ex instanceof PrivilegedActionException) {
  ex = ((PrivilegedActionException) ex).getException();
  }
  if (logger.isDebugEnabled()) {
  logger.debug("Could not read previous value of property '" +
   this.nestedPath + tokens.canonicalName + "'", ex);
  }
  }
  }
  valueToApply = convertForProperty(
  tokens.canonicalName, oldValue, originalValue, ph.toTypeDescriptor());
 }
 pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
 }
 ph.setValue(this.wrappedObject, valueToApply);
 }
 catch (TypeMismatchException ex) {
 throw ex;
 }
 catch (InvocationTargetException ex) {
 PropertyChangeEvent propertyChangeEvent = new PropertyChangeEvent(
  this.rootObject, this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
 if (ex.getTargetException() instanceof ClassCastException) {
 throw new TypeMismatchException(propertyChangeEvent, ph.getPropertyType(), ex.getTargetException());
 }
 else {
 Throwable cause = ex.getTargetException();
 if (cause instanceof UndeclaredThrowableException) {
  // May happen e.g. with Groovy-generated methods
  cause = cause.getCause();
 }
 throw new MethodInvocationException(propertyChangeEvent, cause);
 }
 }
 catch (Exception ex) {
 PropertyChangeEvent pce = new PropertyChangeEvent(
  this.rootObject, this.nestedPath + tokens.canonicalName, oldValue, pv.getValue());
 throw new MethodInvocationException(pce, ex);
 }
 }

它使其是使用class org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler来设置

BeanWrapperImpl$BeanPropertyHandler.setValue
spring-beans-4.3.13.RELEASE-sources.jar!/org/springframework/beans/BeanWrapperImpl.java
@Override
 public void setValue(final Object object, Object valueToApply) throws Exception {
 final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
  ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
  this.pd.getWriteMethod());
 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
 if (System.getSecurityManager() != null) {
  AccessController.doPrivileged(new PrivilegedAction<Object>() {
  @Override
  public Object run() {
  writeMethod.setAccessible(true);
  return null;
  }
  });
 }
 else {
  writeMethod.setAccessible(true);
 }
 }
 final Object value = valueToApply;
 if (System.getSecurityManager() != null) {
 try {
  AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
  @Override
  public Object run() throws Exception {
  writeMethod.invoke(object, value);
  return null;
  }
  }, acc);
 }
 catch (PrivilegedActionException ex) {
  throw ex.getException();
 }
 }
 else {
 writeMethod.invoke(getWrappedInstance(), value);
 }
 }
 }

这里利用反射找出setXXX方法( 比如setMaxActive ),然后设置进去

多数据源的配置

上面的配置对于单数据源来说是没有问题的,对于多数据源,则配置如下

@Configuration
public class MasterDatasourceConfig {

 @Bean("masterDataSource")
 @ConfigurationProperties(prefix = "spring.datasource.master")
 public DataSource masterDataSource() {
  return DataSourceBuilder.create().build();
 }
}

注意,这里要添加ConfigurationProperties注入tomcat jdbc pool的额外设置

spring:
 datasource:
 master:
  type: org.apache.tomcat.jdbc.pool.DataSource
  driver-class-name: org.postgresql.Driver
  url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000
  username: postgres
  password: postgres
  jmx-enabled: true
# tomcat: ## 多数据源的话,这里要去掉tomcat,通通放在数据源前缀下面
  initial-size: 1
  max-active: 5
  ## when pool sweeper is enabled, extra idle connection will be closed
  max-idle: 5
  ## when idle connection > min-idle, poolSweeper will start to close
  min-idle: 1

原先tomcat的配置都要放在数据源前缀的底下,放在spring.datasource.tomcat或者spring.datasource.master.tomcat底下均无法生效。

您可能感兴趣的文章:

  • 详解springboot-修改内置tomcat版本
  • springboot项目打成war包部署到tomcat遇到的一些问题
  • SpringBoot 创建web项目并部署到外部Tomcat
  • Spring Boot 项目发布到 Tomcat 服务器的操作步骤
  • Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动
  • 如何把spring boot项目部署到tomcat容器中
(0)

相关推荐

  • springboot项目打成war包部署到tomcat遇到的一些问题

    开发环境使用jdk1.8.0_60,把springboot 项目打成war包后, 部署到apache-tomcat-7.0.68时报错如下,换成apache-tomcat-8.0.9解决 org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/my-springboot-web-0.0.1

  • 详解springboot-修改内置tomcat版本

    详解springboot-修改内置tomcat版本 1.解析Spring Boot父级依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> </parent> 这块配置就是Spring

  • 如何把spring boot项目部署到tomcat容器中

    把spring-boot项目按照平常的web项目一样发布到tomcat容器下 一.修改打包形式 在pom.xml里设置 <packaging>war</packaging> 二.移除嵌入式tomcat插件 在pom.xml里找到spring-boot-starter-web依赖节点,在其中添加如下代码, <dependency> <groupId>org.springframework.boot</groupId> <artifactId&

  • Spring Boot 项目发布到 Tomcat 服务器的操作步骤

    第 1 步:将这个 Spring Boot 项目的打包方式设置为 war. <packaging>war</packaging> SpringBoot 默认有内嵌的 tomcat 模块,因此,我们要把这一部分排除掉. 即:我们在 spring-boot-starter-web 里面排除了 spring-boot-starter-tomcat ,但是我们为了在本机测试方便,我们还要引入它,所以我们这样写: <dependency> <groupId>org.s

  • Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动

    之前在Spring Boot启动过程(二)提到过createEmbeddedServletContainer创建了内嵌的Servlet容器,我用的是默认的Tomcat. private void createEmbeddedServletContainer() { EmbeddedServletContainer localContainer = this.embeddedServletContainer; ServletContext localServletContext = getServ

  • SpringBoot 创建web项目并部署到外部Tomcat

    前言 使用SpringBoot来开发项目相对于传统模式,要快速优雅许多,相信目前国内绝大部分web项目的开发还没有使用SpringBoot来做,如果你正需要开发一个web项目,不妨尝试使用SpringBoot来做. 本身SpringBoot是内嵌了web服务器,不需要单独的Tomcat,但是实际生产环境中,如果是web项目,Tomcat肯定是运维部门部署好了的,这个Tomcat,做了一些个性化的设置,开发出来的项目需要部署到这个Tomcat,如果是使用SpringBoot开发web服务,我认为可

  • spring boot tomcat jdbc pool的属性绑定

    下面看下spring boot tomcat jdbc pool的属性绑定代码,具体代码如下所示: spring: datasource: type: org.apache.tomcat.jdbc.pool.DataSource driver-class-name: org.postgresql.Driver url: jdbc:postgresql://192.168.99.100:5432/postgres?connectTimeout=6000&socketTimeout=6000 use

  • 关于Spring Boot对jdbc的支持问题

    项目结构 pom.xml pom.xml: <?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.ap

  • Spring Boot如何读取自定义外部属性详解

    测试的环境:Spring Boot2 + Maven +lombok 准备需要用到的基础类: public class People { private String name; private String address; private String phone; } 准备默认的配置文件application.properties,内容如下 people.default.name=zs people.default.address=ccc people.default.phone=1221

  • 关于spring boot使用 jdbc+mysql 连接的问题

    1.创建文件,勾选JDBC和mysql pom.xml中添加了mysql驱动包和jdbc启动器 2.application.yml添加数据库的配置 spring: datasource: username: root password: 123456 # 针对mysql8版本以上的驱动包,需要指定时区 url: jdbc:mysql://127.0.0.1:3306/jdbc?serverTimezong=GMT%2B8 # 针对mysql8版本以上的驱动包,需要指定新的驱动类 driver-c

  • 一篇超详细的Spring Boot对jdbc支持的文章

    目录 项目结构 pom.xml 启动类 Dao层 Service层 Controller层 测试类测试 总结 项目结构 pom.xml pom.xml: <?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-

  • Spring Boot中使用JDBC Templet的方法教程

    前言 Spring 的 JDBC Templet 是 Spring 对 JDBC 使用的一个基本的封装.他主要是帮助程序员实现了数据库连接的管理,其余的使用方式和直接使用 JDBC 没有什么大的区别. 业务需求 JDBC 的使用大家都比较熟悉了.这里主要为了演示在 SpringBoot 中使用 Spring JDBC Templet 的步骤,所以我们就设计一个简单的需求.一个用户对象的 CURD 的操作.对象有两个属性,一个属性是id,一个属性是名称.存储在 MySQL 的 auth_user

  • spring boot中配置hikari连接池属性方式

    目录 spring boot配置hikari连接池属性 spring-boot默认连接池 Hikari配置 Hikari连接池配置说明 spring boot配置hikari连接池属性 事件起因与一个简单应用经常发生Young GC,甚至在没有请求量的情况下也经常发生GC (Allocation Failure),后来使用mat工具进行分析,发现mysql连接相关的class居然占了40%+堆内空间. 才发现spring boot的连接池大小没有配置,默认是10个连接,但实际上该应用不需要这么多

  • 详解Spring Boot 属性配置和使用

    spring Boot 允许通过外部配置让你在不同的环境使用同一应用程序的代码,简单说就是可以通过配置文件来注入属性或者修改默认的配置. Spring Boot 支持多种外部配置方式 这些方式优先级如下: 命令行参数 来自java:comp/env的JNDI属性 Java系统属性(System.getProperties()) 操作系统环境变量 RandomValuePropertySource配置的random.*属性值 jar包外部的application-{profile}.propert

  • Spring Boot如何使用JDBC获取相关的数据详解

    什么是JDBC Java Database Connectivity 是一种用于执行SQL语句的Java API,与数据库建立连接.发送 操作数据库的语句并处理结果. Spring Boot 使用 JDBC 增加依赖 修改pom.xml:将dependecies 修改为如下两个 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>s

  • 玩转spring boot 结合AngularJs和JDBC(4)

    参考官方例子:http://spring.io/guides/gs/relational-data-access/  一.项目准备 在建立mysql数据库后新建表"t_order" SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `t_order` -- ---------------------------- DROP TABLE IF EXISTS `t_order`;

随机推荐