Spring-Boot-2.0.0-M1版本将默认的数据库连接池从tomcat jdbc pool改为了hikari,这里主要研究下hikari的默认配置
0. 创建Spring Boot项目,选中 Web、MySQL、JDBC 依赖
<!--集成mysql数据库--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
1. 启动类默认加载了DataSourceAutoConfiguration,默认数据源是HikariDataSource
@SpringBootApplicationpublic class SpringBootJdbcApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJdbcApplication.class, args);
}
}
2. 数据源配置文件属性
spring: datasource: url: jdbc:mysql://localhost:3306/springboot //系统自带的默认数据源配置中,用 url,若是自定义的HikariDataSource,用jdbcUrl (自定义的其它类型数据源名称取什么待测) username: root password: xiaochao driver-class-name: com.mysql.cj.jdbc.Driver //老版本用com.mysql.jdbc.Driver name: hikari
3. 测试
@RunWith(SpringRunner.class) @SpringBootTest public class SpringBootJdbcApplicationTests { @Autowired DataSource dataSource; @Test public void contextLoads() throws SQLException { System.out.println(dataSource.getClass().getName()); System.out.println(dataSource.getConnection()); } }
结果:
HikariProxyConnection@265939934 wrapping com.mysql.cj.jdbc.ConnectionImpl@14982a82
com.zaxxer.hikari.HikariDataSource
4. 自定义数据源
4.1 首先排除掉系统默认数据源
- exclude:排除,不包括,祛除,赶出,反义词 : include
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})public class SpringBootJdbcApplication { public static void main(String[] args) { SpringApplication.run(SpringBootJdbcApplication.class, args); } }
4.2 在配置类中加入自定义的线程池
-
@Bean @ConfigurationProperties("spring.datasource") //此配置项名称是自定义的,只要和配置文件中的各项名称对应上就好 public HikariDataSource dataSource() { return DataSourceBuilder.create().type(HikariDataSource.class).build(); }
-
4.3 把配置文件中的spring.datasource.url 改为spring.datasource.jdbcUrl
- 4.4 自动以tomcat jdbc 数据源 首先引入tomcat-jdbc依赖
-
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> <version>9.0.13</version> </dependency>
-
配置tomcat数据源Bean
@Configuration public class MyConfig { @Bean @ConfigurationProperties("spring.datasource") //此配置项名称是自定义的,只要能和配置文件中的各项名称对应上就好 public org.apache.tomcat.jdbc.pool.DataSource dataSource() { return DataSourceBuilder.create().type(org.apache.tomcat.jdbc.pool.DataSource.class).build(); } }
自定义其它类型的数据源方式同理
5. 数据源自动配置 源码解析
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.boot.autoconfigure.jdbc; import com.zaxxer.hikari.HikariDataSource; import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSource; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.context.annotation.Bean; import org.springframework.util.StringUtils; abstract class DataSourceConfiguration { DataSourceConfiguration() { } protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) { return properties.initializeDataSourceBuilder().type(type).build(); } @ConditionalOnMissingBean({DataSource.class}) @ConditionalOnProperty( name = {"spring.datasource.type"} ) static class Generic { Generic() { } @Bean public DataSource dataSource(DataSourceProperties properties) { return properties.initializeDataSourceBuilder().build(); } } @ConditionalOnClass({BasicDataSource.class}) @ConditionalOnMissingBean({DataSource.class}) @ConditionalOnProperty( name = {"spring.datasource.type"}, havingValue = "org.apache.commons.dbcp2.BasicDataSource", matchIfMissing = true ) static class Dbcp2 { Dbcp2() { } @Bean @ConfigurationProperties( prefix = "spring.datasource.dbcp2" ) public BasicDataSource dataSource(DataSourceProperties properties) { return (BasicDataSource)DataSourceConfiguration.createDataSource(properties, BasicDataSource.class); } } @ConditionalOnClass({HikariDataSource.class}) @ConditionalOnMissingBean({DataSource.class}) @ConditionalOnProperty( name = {"spring.datasource.type"}, havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true ) static class Hikari { Hikari() { } @Bean @ConfigurationProperties( prefix = "spring.datasource.hikari" ) public HikariDataSource dataSource(DataSourceProperties properties) { HikariDataSource dataSource = (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class); if (StringUtils.hasText(properties.getName())) { dataSource.setPoolName(properties.getName()); } return dataSource; } } @ConditionalOnClass({org.apache.tomcat.jdbc.pool.DataSource.class}) @ConditionalOnMissingBean({DataSource.class}) @ConditionalOnProperty( name = {"spring.datasource.type"}, havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true ) static class Tomcat { Tomcat() { } @Bean @ConfigurationProperties( prefix = "spring.datasource.tomcat" ) public org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) { org.apache.tomcat.jdbc.pool.DataSource dataSource = (org.apache.tomcat.jdbc.pool.DataSource)DataSourceConfiguration.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; } } }
参考文档:Spring Boot 官方文档 —— 84.1 Configure a Custom DataSource 章节
package org.springframework.boot.autoconfigure.jdbc; @Configuration @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) @EnableConfigurationProperties({DataSourceProperties.class}) @Import({DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class}) public class DataSourceAutoConfiguration { public DataSourceAutoConfiguration() {} 。。。。。。 }
@Configuration @Import({DataSourceInitializerInvoker.class, DataSourceInitializationConfiguration.Registrar.class}) class DataSourceInitializationConfiguration { DataSourceInitializationConfiguration() { } static class Registrar implements ImportBeanDefinitionRegistrar { private static final String BEAN_NAME = "dataSourceInitializerPostProcessor"; Registrar() { } public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { if (!registry.containsBeanDefinition("dataSourceInitializerPostProcessor")) { GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass(DataSourceInitializerPostProcessor.class); beanDefinition.setRole(2); beanDefinition.setSynthetic(true); registry.registerBeanDefinition("dataSourceInitializerPostProcessor", beanDefinition); } } } }
package org.springframework.boot.autoconfigure.jdbc; import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; //此类是一个监听器 class DataSourceInitializerInvoker implements ApplicationListener<DataSourceSchemaCreatedEvent>, InitializingBean { private static final Log logger = LogFactory.getLog(DataSourceInitializerInvoker.class); private final ObjectProvider<DataSource> dataSource; private final DataSourceProperties properties; private final ApplicationContext applicationContext; private DataSourceInitializer dataSourceInitializer; private boolean initialized; DataSourceInitializerInvoker(ObjectProvider<DataSource> dataSource, DataSourceProperties properties, ApplicationContext applicationContext) { this.dataSource = dataSource; this.properties = properties; this.applicationContext = applicationContext; } public void afterPropertiesSet() { DataSourceInitializer initializer = this.getDataSourceInitializer(); if (initializer != null) { boolean schemaCreated = this.dataSourceInitializer.createSchema(); //run DDL schema if (schemaCreated) { this.initialize(initializer); } } } private void initialize(DataSourceInitializer initializer) { try { this.applicationContext.publishEvent(new DataSourceSchemaCreatedEvent(initializer.getDataSource())); if (!this.initialized) { this.dataSourceInitializer.initSchema(); //run init data schema this.initialized = true; } } catch (IllegalStateException var3) { logger.warn("Could not send event to complete DataSource initialization (" + var3.getMessage() + ")"); } } //监听器监听到事件后运行的方法 public void onApplicationEvent(DataSourceSchemaCreatedEvent event) { DataSourceInitializer initializer = this.getDataSourceInitializer(); if (!this.initialized && initializer != null) { initializer.initSchema(); //run init data schema this.initialized = true; } } private DataSourceInitializer getDataSourceInitializer() { if (this.dataSourceInitializer == null) { DataSource ds = (DataSource)this.dataSource.getIfUnique(); if (ds != null) { this.dataSourceInitializer = new DataSourceInitializer(ds, this.properties, this.applicationContext); } } return this.dataSourceInitializer; } }
package org.springframework.boot.autoconfigure.jdbc; import ......; class DataSourceInitializer { //【初始化程序】 private static final Log logger = LogFactory.getLog(DataSourceInitializer.class); private final DataSource dataSource; private final DataSourceProperties properties; private final ResourceLoader resourceLoader; DataSourceInitializer(DataSource dataSource, DataSourceProperties properties, ResourceLoader resourceLoader) { this.dataSource = dataSource; this.properties = properties; this.resourceLoader = (ResourceLoader)(resourceLoader != null ? resourceLoader : new DefaultResourceLoader()); } DataSourceInitializer(DataSource dataSource, DataSourceProperties properties) { this(dataSource, properties, (ResourceLoader)null); } public DataSource getDataSource() { return this.dataSource; } //建表SQL,classpath*:schema-*.sql public boolean createSchema() {
//this.properties.getSchema()即:用户在配置文件中指定的 spring.datasource.schema=xxx List<Resource> scripts = this.getScripts("spring.datasource.schema", this.properties.getSchema(), "schema"); if (!scripts.isEmpty()) { if (!this.isEnabled()) { logger.debug("Initialization disabled (not running DDL scripts)"); return false; } String username = this.properties.getSchemaUsername(); String password = this.properties.getSchemaPassword(); this.runScripts(scripts, username, password); } return !scripts.isEmpty(); }
//初始化数据SQL ,classpath*:data-*.sql public void initSchema() {
//this.properties.getData 即:用户在配置文件中自定义的:spring.datasource.data=XXX List<Resource> scripts = this.getScripts("spring.datasource.data", this.properties.getData(), "data"); if (!scripts.isEmpty()) { if (!this.isEnabled()) { logger.debug("Initialization disabled (not running data scripts)"); return; } String username = this.properties.getDataUsername(); String password = this.properties.getDataPassword(); this.runScripts(scripts, username, password); } } 。。。。。。
//根据特定名称规则获取SQL脚本文件 private List<Resource> getScripts(String propertyName, List<String> resources, String fallback) { if (resources != null) { //指定名称的脚本文件名字集合 return this.getResources(propertyName, resources, true); //从指定名称的脚本名字文件集合中获取脚本SQL } else { //若是没有指定的,则在类路径下寻找通配规则的脚本文件 String platform = this.properties.getPlatform(); //平台,纲领 List<String> fallbackResources = new ArrayList();
//这里为啥add() 2个 SQL? fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql"); //DatasourceProperties中的构造器中,platform默认被赋值为 all fallbackResources.add("classpath*:" + fallback + ".sql"); return this.getResources(propertyName, fallbackResources, false); } } 。。。。。。 //运行SQL脚本 private void runScripts(List<Resource> resources, String username, String password) { if (!resources.isEmpty()) { ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.setContinueOnError(this.properties.isContinueOnError()); populator.setSeparator(this.properties.getSeparator()); if (this.properties.getSqlScriptEncoding() != null) { populator.setSqlScriptEncoding(this.properties.getSqlScriptEncoding().name()); } Iterator var5 = resources.iterator(); while(var5.hasNext()) { Resource resource = (Resource)var5.next(); populator.addScript(resource); } DataSource dataSource = this.dataSource; if (StringUtils.hasText(username) && StringUtils.hasText(password)) { dataSource = DataSourceBuilder.create(this.properties.getClassLoader()).driverClassName(this.properties.determineDriverClassName()).url(this.properties.determineUrl()).username(username).password(password).build(); } DatabasePopulatorUtils.execute(populator, dataSource); } } }
package org.springframework.boot.autoconfigure.jdbc; @ConfigurationProperties( prefix = "spring.datasource" ) public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {private Class<? extends DataSource> type; private String driverClassName; private String url; private String username; private String password;private DataSourceInitializationMode initializationMode; private String platform; private List<String> schema;private Charset sqlScriptEncoding; ......public DataSourceProperties() { this.initializationMode = DataSourceInitializationMode.EMBEDDED; this.platform = "all"; this.continueOnError = false; this.separator = ";"; this.embeddedDatabaseConnection = EmbeddedDatabaseConnection.NONE; this.xa = new DataSourceProperties.Xa(); } }
通配规则:schema‐*.sql、data‐*.sql, 优先级第三高 eg:schema-emp.sql, schema-dept.sql; data-emp.sql ,data-dept.sql
默认规则:schema.sql,schema‐all.sql (或者关系,给用户多个选择); 优先级第二高,
自定义规则:yml中配置,根据上面代码,优先级高
spring:
datasource:
schema:
‐ classpath: department.sql
‐ classpath: user.sql
......
data:
‐ classpath: department_initData.sql
‐ classpath: user_initData.sql
......
自定义指定的SQL文件
经过测验,schema.sql 和schema-all.sql 在resources目录下并没有生效,有待继续查验
6. jdbcTemplate操作数据库
@Controller @RequestMapping("/user") public class UserController { @Autowired JdbcTemplate jdbcTemplate; @ResponseBody @RequestMapping("/getById2/{id}") public List<Map<String, Object>> selectByPrimaryKey2(@PathVariable Integer id){
//这种query is OK List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT * FROM USER"); return maps; //以下几种方式都会产生error,error信息见下文:待查明 // Object[] obj = new Object[1]; // obj[0] = id; // return jdbcTemplate.queryForList("select * from user where id = ?", obj,User.class); // return jdbcTemplate.queryForList("SELECT * FROM USER", User.class); // return jdbcTemplate.queryForObject("select id,name,sex,age from user where id = " + id,User.class); } }
org.springframework.jdbc.IncorrectResultSetColumnCountException: Incorrect column count: expected 1, actual 4 at org.springframework.jdbc.core.SingleColumnRowMapper.mapRow(SingleColumnRowMapper.java:110) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:440) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:376) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:452) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:462) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.jdbc.core.JdbcTemplate.queryForList(JdbcTemplate.java:485) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at com.everjiankang.cache.controller.UserController.selectByPrimaryKey2(UserController.java:53) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.3.RELEASE.jar:5.1.3.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417) [tomcat-embed-core-9.0.13.jar:9.0.13] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.13.jar:9.0.13] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.13.jar:9.0.13] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]