ZetCode

Spring HikariCP

最后修改于 2020 年 7 月 13 日

在本教程中,我们将展示如何在经典的Spring应用程序中使用HikariCP连接池。在该应用程序中,我们使用Spring JdbcTemplate连接到MySQL数据库。我们使用FreeMarker作为模板引擎。该应用程序部署在Tomcat服务器上。

Spring 是一个流行的Java应用程序框架,用于用Java开发企业应用程序。它也是一个非常好的集成系统,有助于将各种企业组件连接在一起。

HikariCP 是一个稳定、高性能的JDBC连接池。 连接池 是由数据库系统维护的数据库连接缓存,用于在需要未来的数据库请求时重用连接。使用连接池,我们可以显著降低整体资源使用。

JdbcTemplate 是一个Spring库,可帮助程序员创建与关系数据库和JDBC一起工作的应用程序。它负责许多繁琐且容易出错的低级细节,例如处理事务、清理资源以及正确处理异常。JdbcTemplate包含在Spring的spring-jdbc模块中。

cars.sql
-- SQL for the Cars table

START TRANSACTION;
DROP TABLE IF EXISTS Cars;

CREATE TABLE Cars(Id INTEGER PRIMARY KEY, Name VARCHAR(50), Price INTEGER);
INSERT INTO Cars VALUES(1, 'Audi', 52642);
INSERT INTO Cars VALUES(2, 'Mercedes', 57127);
INSERT INTO Cars VALUES(3, 'Skoda', 9000);
INSERT INTO Cars VALUES(4, 'Volvo', 29000);
INSERT INTO Cars VALUES(5, 'Bentley', 350000);
INSERT INTO Cars VALUES(6, 'Citroen', 21000);
INSERT INTO Cars VALUES(7, 'Hummer', 41400);
INSERT INTO Cars VALUES(8, 'Volkswagen', 21600);
COMMIT;

在代码示例中,我们使用此表。

mysql> source cars.sql

使用mysql命令行工具及其source命令,我们创建了Cars表。 MySQL教程提供了有关如何设置和使用MySQL数据库的更多信息。

├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── bean
    │   │           │   └── Car.java
    │   │           ├── service
    │   │           │   └── CarService.java
    │   │           └── web
    │   │              └── MyController.java
    │   ├── resources
    │   │   └── application-context.xml
    │   └── webapp
    │       ├── META-INF
    │       │   └── context.xml
    │       └── WEB-INF
    │           ├── spring-servlet.xml
    │           ├── views
    │           │   ├── allCars.ftl
    │           │   └── index.ftl
    │           └── web.xml
    └── test
        └── java

这是项目结构。

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.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>SpringJdbcTemplateWebEx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>SpringJdbcTemplateWebEx</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>        
        <spring-version>4.3.7.RELEASE</spring-version>
    </properties>
    
    <dependencies>
        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>              
        
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.25-incubating</version>
        </dependency>   
        
         <!--Needed for freemarker FreeMarkerConfigurer--> 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring-version}</version>
        </dependency>                
        
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>2.5.1</version>
        </dependency>      
        
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.22</version>
        </dependency>          
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-version}</version>
        </dependency>         
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring-version}</version>
        </dependency>              
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

在此Maven构建文件中,我们为Spring应用程序核心、HikariCP连接池、FreeMarker模板引擎、JdbcTemplate库和MySQL驱动程序提供了依赖项。

web.xml
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>    
    
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

web.xml文件中,我们设置了Spring的DispatcherServletDispatcherServlet是HTTP请求处理程序的中央调度程序。

context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/SpringJdbcTemplateWebEx">

    <Resource name="jdbc/myDs" auth="Container"
              factory="com.zaxxer.hikari.HikariJNDIFactory"
              dataSourceClassName="com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
              dataSource.url="jdbc:mysql:///testdb?useSSL=false"
              type="javax.sql.DataSource"
              minimumIdle="5" 
              maximumPoolSize="10"
              connectionTimeout="300000"
              database="testdb"
              server="localhost"
              dataSource.user="testuser"
              dataSource.password="test623"
              dataSource.cachePrepStmts="true"
              dataSource.prepStmtCacheSize="250"
              dataSource.prepStmtCacheSqlLimit="2048"
              closeMethod="close"
    />
    
</Context>

Tomcat的context.xml文件包含数据源定义。该数据源使用HikariCP连接池。

spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.zetcode" />
    <import resource="classpath:application-context.xml" />
    
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/views/"/>
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="cache" value="true"/>
        <property name="prefix" value=""/>
        <property name="suffix" value=".ftl"/>
    </bean>   
                
</beans>

在spring servlet context XML文件中,我们定义了两个bean:freemarkerConfigviewResolver。这些是FreeMarker的配置bean。spring-servlet.xml位于WEB-INF子目录中。

<context:component-scan base-package="com.zetcode" />

我们启用了com.zetcode包的组件扫描。

<import resource="classpath:application-context.xml" />

我们导入了另一个上下文文件,名为application-context.xml。它位于类路径上——在src/main/resources目录中。

application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                          http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/myDs"/>
    </bean>    
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>    

</beans>

application-context.xml中,我们定义了两个bean:dataSourcejdbcTemplate

com/zetcode/Car.java
package com.zetcode.bean;

public class Car {
    
    private int Id;
    private String Name;
    private int Price;

    public int getId() {
        return Id;
    }

    public void setId(int Id) {
        this.Id = Id;
    }

    public String getName() {
        return Name;
    }

    public void setName(String Name) {
        this.Name = Name;
    }

    public int getPrice() {
        return Price;
    }

    public void setPrice(int Price) {
        this.Price = Price;
    }

    @Override
    public String toString() {
        return "Car{" + "Id=" + Id + ", Name=" + 
                Name + ", Price=" + Price + '}';
    }
}

这是一个Car类。数据库表中的一行将映射到此类。

com/zetcode/CarService.java
package com.zetcode.service;

import com.zetcode.bean.Car;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class CarService {

    @Autowired
    public JdbcTemplate jdbcTemplate;

    public List<Car> getAllCars() {

        String sql = "SELECT * FROM Cars";

        List<Car> cars = jdbcTemplate.query(sql, 
                new BeanPropertyRowMapper(Car.class));
        return cars;
    }
}

CarService是一个服务类,其中包含一个从数据库检索所有汽车的方法。

@Autowired
public JdbcTemplate jdbcTemplate;

JdbcTemplate通过@Autowired注解注入。

List<Car> cars = jdbcTemplate.query(sql, 
        new BeanPropertyRowMapper(Car.class));

使用JdbcTemplate的query方法,我们执行SQL查询。使用BeanPropertyRowMapper将结果对象映射到Car对象。

com/zetcode/MyController.java
package com.zetcode.web;

import com.zetcode.bean.Car;
import com.zetcode.service.CarService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MyController {

    @Autowired
    private CarService carService;

    @RequestMapping("/index")
    public String index(Model model) {

        return "index";
    }

    @RequestMapping(value = "/all", method = RequestMethod.GET)
    public ModelAndView all() {

        List<Car> cars = carService.getAllCars();

        ModelAndView model = new ModelAndView("allCars");
        model.addObject("cars", cars);

        return model;
    }
}

MyController是一个控制器类。它有两个请求URL的映射:/index/all

@Autowired
private CarService carService;

CarService已注入。

@RequestMapping("/index")
public String index(Model model) {

    return "index";
}

此请求通过返回index.ftl文件来解析。视图位于WEB-INF/views目录中。

@RequestMapping(value = "/all", method = RequestMethod.GET)
public ModelAndView all() {

    List<Car> cars = carService.getAllCars();

    ModelAndView model = new ModelAndView("allCars");
    model.addObject("cars", cars);

    return model;
}

在这里,我们调用CarServicegetAllCars方法,并创建一个ModelAndView对象。检索到的数据将被发送到allCars.ftl模板。

index.ftl
<!DOCTYPE html>
<html>
    <head>
        <title>Home page</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <p>Showing <a href="all.html">all cars</a></p>
    </body>
</html>

这是index.ftl文件。

allCars.ftl
<!DOCTYPE html>
<html>
    <head>
        <title>Cars</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        </head>
    <body>
        
        <table>
            <tr>
                <th>Id</th>  
                <th>Name</th>  
                <th>Price</th>
            </tr>        

            <#list cars as car>
                <tr>
                    <td>${car.id}</td> 
                    <td>${car.name}</td> 
                    <td>${car.price}</td>
                </tr>
            </#list>        
        </table>                
    </body>
</html>

此模板文件处理从数据库发送的数据。

<#list cars as car>

#list指令列出数据集。

Showing all cars
图:显示所有汽车

来自MySQL数据库的数据显示在Opera浏览器中。

在本教程中,我们创建了一个经典的Spring应用程序,该应用程序使用JdbcTemplate对MySQL数据库执行SQL语句。我们使用了HikariCP连接池。Spring应用程序使用FreeMarker模板引擎,并部署在Tomcat服务器上。