HikariCP在” mvn spring-boot:run”时启动,但没有可部署的war文件

HikariCP starts when “mvn spring-boot:run” but not with a deployable war file

我们有一个Spring Boot应用程序。

当我们执行" mvn spring-boot:run"时,该应用程序将使用HikariCP。
当我们在tomcat上部署war文件时,CP不??同,并且在几个小时后关闭连接后崩溃。

在部署战争文件时如何强制Hikari?

这是我们的application.properties:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
spring.datasource.url=jdbc:mysql://localhost:3306/xxx?
autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&connectionCollation=utf8_general_ci&characterSetResults=utf8&autoDeserialize=true&useConfigs=maxPerformance
spring.datasource.username=root
spring.datasource.password=___
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.open-in-view=true
spring.jpa.show-sql=false
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.DefaultNamingStrategy
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
spring.jpa.properties.hibernate.hikari.dataSource.cachePrepStmts=true
spring.jpa.properties.hibernate.hikari.dataSource.prepStmtCacheSize=250
spring.jpa.properties.hibernate.hikari.dataSource.prepStmtCacheSqlLimit=2048
spring.jpa.properties.hibernate.hikari.dataSource.useServerPrepStmts=true
spring.jpa.properties.hibernate.generate_statistics=false
spring.jpa.properties.hibernate.cache.use_structured_entries=true
spring.jpa.properties.hibernate.archive.autodetection=class
spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.order_update=true
spring.jpa.properties.hibernate.connection.characterEncoding=utf-8
spring.jpa.properties.hibernate.connection.CharSet=utf-8
spring.jpa.properties.hibernate.connection.useUnicode=true
spring.jpa.properties.hibernate.connection.autocommit=true
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=com.hazelcast.hibernate.HazelcastLocalCacheRegionFactory
spring.jpa.properties.hibernate.cache.region_prefix=
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.use_minimal_puts=true
# JTA
spring.jta.enabled=true

这是应用程序类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package site.app;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.boot.orm.jpa.EntityScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.web.config.EnableSpringDataWebSupport;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Properties;

/**
 * to make this deployable as war, this is necessary:
 * http://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html
 */
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages ="site")
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"site.repository" } )
@EntityScan(basePackages="site.model")
@EnableJpaAuditing
@EnableSpringDataWebSupport
@SpringBootApplication//mist: so that it can be run as war file
public class Application  extends SpringBootServletInitializer {

    /** mist: so that it can be run as war file */
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
//      System.out.println("Let's inspect the beans provided by Spring Boot:");
//
//      String[] beanNames = ctx.getBeanDefinitionNames();
//      Arrays.sort(beanNames);
//      for (String beanName : beanNames) {
//          System.out.println(beanName);
//      }

//       UserRepository repository = context.getBean(UserRepository.class);
//       //example data
//       User user = new User();
//       user.setEmail("[email protected]");
//       user.setFirstName("test");
//       user.setLastName("test");
//
//       repository.save(user);
//       Iterable<User> allUsers = repository.findAll();
//       for(User theUser : allUsers){
//           System.out.println(theUser.getEmail());
//       }
//      
//       SponsorRepository sponsorRepository = context.getBean(SponsorRepository.class);
//      
//       Sponsor sponsor = new Sponsor();
//       sponsor.setEmail("[email protected]");
//       sponsor.setSponsorPackage(SponsorPackage.DIAMOND);
//      
//       sponsorRepository.save(sponsor);

//      Page page = new Page();
//      page.setName("home");
//      PageRepository pageRepository = context.getBean(PageRepository.class);
//      pageRepository.save(page);

//      Link link = new Link();
//      link.setName("Registration");
//      link.setUrl("/");
//      LinkRepository linkRepository = context.getBean(LinkRepository.class);
//      linkRepository.save(link);
//       context.close();
    }


//    private DataSource dataSource() {
//        final HikariDataSource ds = new HikariDataSource();
//        ds.setMaximumPoolSize(100);
//        ds.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
//        ds.addDataSourceProperty("url", url);
//        ds.addDataSourceProperty("user", username);
//        ds.addDataSourceProperty("password", password);
//        ds.addDataSourceProperty("cachePrepStmts", true);
//        ds.addDataSourceProperty("prepStmtCacheSize", 250);
//        ds.addDataSourceProperty("prepStmtCacheSqlLimit", 2048);
//        ds.addDataSourceProperty("useServerPrepStmts", true);
//        return ds;
//    }


//    @Value("${spring.datasource.username}")
//    private String user;
//
//    @Value("${spring.datasource.password}")
//    private String password;
//
//    @Value("${spring.datasource.url}")
//    private String dataSourceUrl;
//
//    @Value("${spring.datasource.driverClassName}")
//    private String driverClassName;
//
////    @Value("${spring.datasource.connectionTestQuery}")
////    private String connectionTestQuery;
//
//    @Bean
//    public DataSource primaryDataSource() {
//        Properties dsProps = new Properties();
//        dsProps.setProperty("url", dataSourceUrl);
//        dsProps.setProperty("user", user);
//        dsProps.setProperty("password", password);
//
//        Properties configProps = new Properties();
////        configProps.setProperty("connectionTestQuery", connectionTestQuery);
//        configProps.setProperty("driverClassName", driverClassName);
//        configProps.setProperty("jdbcUrl", dataSourceUrl);
//
//        HikariConfig hc = new HikariConfig(configProps);
//        hc.setDataSourceProperties(dsProps);
////        hc.setMetricRegistry(metricRegistry);
//        return new HikariDataSource(hc);
//    }

}

这是pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<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>org.bgjug</groupId>
    site</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name> web site</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        spring-boot-starter-parent</artifactId>
        <version>1.2.2.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
            <!--mist: exists in tomcat-->
            <!--<scope>provided</scope>-->
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            spring-aspects</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.data</groupId>
            spring-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            hibernate-entitymanager</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            mysql-connector-java</artifactId>
        </dependency>

        <!--TODO mist: hikariCP stays here. I couldn't make it use it (I'm missing something). Now it uses either tomcat's pool or commons' pool-->
        <dependency>
            <groupId>com.zaxxer</groupId>
            HikariCP</artifactId>
            <scope>compile</scope>
        </dependency>

        <!--  I need this to make entities auditable -->
        <dependency>
            <groupId>joda-time</groupId>
            joda-time</artifactId>
        </dependency>

        <dependency>
            <groupId>joda-time</groupId>
            joda-time-jsptags</artifactId>
            <version>1.1.1</version>
        </dependency>

        <dependency>
            <groupId>org.jadira.usertype</groupId>
            usertype.core</artifactId>
            <version>${jadira.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            javax.servlet-api</artifactId>
            <!--mist: exists in tomcat-->
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            jstl</artifactId>
        </dependency>

        <!--  spring security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            spring-security-taglibs</artifactId>
        </dependency>

        <!-- email -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>com.hazelcast</groupId>
            hazelcast-hibernate4</artifactId>
            <version>${hazelcast.version}</version>
        </dependency>

        <!-- testing -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            hamcrest-core</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            h2</artifactId>
            <version>1.4.186</version>
        </dependency>
    </dependencies>

    <!--mist: a profile that has the spring-boot:run plugin and a couple of dependencies, so that-->
    <!--spring-boot:run will work with an embedded tomcat. This profile is activated by default so that-->
    <!--no extra conf is needed. when we deploy on the server, we deactivate the profile, because we don't-->
    <!--want these dependencies in the war.-->
    <profiles>
        <profile>
           
                true</activeByDefault>
            </activation>
            <id>run.as.spring-boot.run</id>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        spring-boot-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    spring-boot-starter-web</artifactId>
                </dependency>
                <dependency>
                    <groupId>org.apache.tomcat.embed</groupId>
                    tomcat-embed-jasper</artifactId>
                </dependency>
            </dependencies>
        </profile>
    </profiles>

    <properties>
        <start-class>site.app.Application</start-class>
        <spring.version>4.1.5.RELEASE</spring.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-data-jpa.version>1.5.0.M1</spring-data-jpa.version>
        <hibernate-entitymanager.version>4.3.0.Final</hibernate-entitymanager.version>
        <jadira.version>3.1.0.CR10</jadira.version>
        <hazelcast.version>3.4</hazelcast.version>
        <rest-assured.version>2.4.0</rest-assured.version>
        <h2-database.version>1.3.156</h2-database.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


所以我在评论中被告知,它不会隐式工作,因为Tomcat的数据库池以某种方式优先,这对我来说很奇怪。

一个人可以像这样显式配置它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Configuration
@ConfigurationProperties//: so that the conf properties are supplied here
@SpringBootApplication//: so that it can be run as war file
...
public class Application  extends SpringBootServletInitializer {
    @Value("${spring.datasource.username}")
    private String user;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.url}")
    private String dataSourceUrl;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Bean
    public DataSource primaryDataSource() {
        Properties dsProps = new Properties();
        dsProps.setProperty("url", dataSourceUrl);
        dsProps.setProperty("user", user);
        dsProps.setProperty("password", password);

        Properties configProps = new Properties();
        configProps.setProperty("driverClassName", driverClassName);
        configProps.setProperty("jdbcUrl", dataSourceUrl);

        HikariConfig hc = new HikariConfig(configProps);
        hc.setDataSourceProperties(dsProps);
        return new HikariDataSource(hc);
    }
}


我也遇到了这个问题,最终这只是一个小问题。只有在确保tomcat-jdbc.jar或commons-dbcp.jar永远不会出现在您的类路径中的情况下,它绝对优先。您可以通过将这些依赖项(如果我通过传递方式下载)排除在外来确保这一点(这就是我所做的,只是找出pom中的哪些依赖关系在您的类路径中通过传递方式将它们下载)。完成此操作后,您的application.properties应该如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
# hikariCP
  spring.jpa.databasePlatform=org.hibernate.dialect.MySQLDialect
  spring.datasource.url=jdbc:mysql://localhost:3306/exampledb
  spring.datasource.username=root
  spring.datasource.password=
  spring.datasource.poolName=SpringBootHikariCP
  spring.datasource.maximumPoolSize=5
  spring.datasource.minimumIdle=3
  spring.datasource.maxLifetime=2000000
  spring.datasource.connectionTimeout=30000
  spring.datasource.idleTimeout=30000
  spring.datasource.pool-prepared-statements=true
  spring.datasource.max-open-prepared-statements=2500

它将隐式配置HikariCP数据源。但是还有一点,它将使用驱动程序而不是推荐的dataSourceClassName。在这种情况下,必须在application.properties:

中具有spring.datasource.dataSourceClassName = com.mysql.jdbc.jdbc2.optional.MysqlDataSource之后使用Java Config。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@Configuration
@ComponentScan
class DataSourceConfig {

  @Value("${spring.datasource.username}")
  private String user;

  @Value("${spring.datasource.password}")
  private String password;

  @Value("${spring.datasource.url}")
  private String dataSourceUrl;

  @Value("${spring.datasource.dataSourceClassName}")
  private String dataSourceClassName;

  @Value("${spring.datasource.poolName}")
  private String poolName;

  @Value("${spring.datasource.connectionTimeout}")
  private int connectionTimeout;

  @Value("${spring.datasource.maxLifetime}")
  private int maxLifetime;

  @Value("${spring.datasource.maximumPoolSize}")
  private int maximumPoolSize;

 @Value("${spring.datasource.minimumIdle}")
 private int minimumIdle;

 @Value("${spring.datasource.idleTimeout}")
 private int idleTimeout;

 @Bean
 public DataSource primaryDataSource() {
      Properties dsProps = new Properties();
      dsProps.put("url", dataSourceUrl);
      dsProps.put("user", user);
      dsProps.put("password", password);
      dsProps.put("prepStmtCacheSize",250);
      dsProps.put("prepStmtCacheSqlLimit",2048);
      dsProps.put("cachePrepStmts",Boolean.TRUE);
      dsProps.put("useServerPrepStmts",Boolean.TRUE);

      Properties configProps = new Properties();
         configProps.put("dataSourceClassName", dataSourceClassName);
         configProps.put("poolName",poolName);
         configProps.put("maximumPoolSize",maximumPoolSize);
         configProps.put("minimumIdle",minimumIdle);
         configProps.put("minimumIdle",minimumIdle);
         configProps.put("connectionTimeout", connectionTimeout);
         configProps.put("idleTimeout", idleTimeout);
         configProps.put("dataSourceProperties", dsProps);

     HikariConfig hc = new HikariConfig(configProps);
     HikariDataSource ds = new HikariDataSource(hc);
     return ds;
    }
  }

在application.properties中定义dataSourceClassName以进行隐式自动配置,并抛出异常:

1
Caused by: java.lang.IllegalStateException: both driverClassName and dataSourceClassName are specified, one or the other should be used.

由于spring boot从url属性推断出Driver,因此您无法同时为隐式自动配置设置Driver(推断)和dataSourceClassName。