springboot系列之三-项目整合阿里Druid 与fastjson,实现数据库连接池优化及输出自动转JSON

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/firehadoop/article/details/84997372

一、项目目标

       假设上一个项目需要部署上线,你会存在很多现实的问题需要解决,比如:提高系统性能使用数据库连接池、监视数据库执行效率及sql语句执行效率还有一般的系统接口都只接受JSON或XML的输出,如果直接输出字符串对方接口还需要写代码适配,这些都是问题,所以本次的项目目标是通过整合阿里开源项目Druid实现Java下的数据库连接池,兼任各种数据库,效率高出错小,使用量大,并且Druid还提供强大的监控和扩展功能,整合阿里开源项目FASTJSON,实现系统直接输出实体类转JSON,极大的精简了系统的转换负担,快速实现业务功能。

二、Druid介绍

先上一个Druid自己测试的各种主要数据库连接池的功能对比表格

  Druid BoneCP DBCP C3PO Proxool JBoss

Tomcat-

jdbc

LRU ?
PSCache
PSCache-Oracle-Optimized
ExceptionSorter
更新维护 ?

 LRU是一个性能关键指标,特别Oracle,每个Connection对应数据库端的一个进程,如果数据库连接池遵从LRU,有助于数据库服务器优化,这是重要的指标。MySQL的InnoDB引擎设置有索引及数据缓存池,其中用到的LRU算法来维持缓存的命中率。

ExceptionSorter是一个很重要的容错特性,如果一个连接产生了一个不可恢复的错误,必须立刻从连接池中去掉,否则会连续产生大量错误。这个特性,目前只有JBossDataSource和Druid实现。Druid的实现参考自JBossDataSource,经过长期生产反馈补充。

总结来看,Druid由于是阿里自用的数据库连接池,充分参考了各家武林门派的长处,尤其针对oracle做了大量优化,实在是居家编程,数据库连接的大杀器,下面是实际测试通过的Druid支持的数据库列表。

数据库 支持状态
mysql 支持,大规模使用
oracle 支持,大规模使用
sqlserver 支持
postgres 支持
db2 支持
h2 支持
derby 支持
sqlite 支持
sybase 支持

针对springboot,阿里特地编写了与之更完美契合的druid,命名为:druid-spring-boot-starter 

Druid 的监控数据可以通过 DruidStatManagerFacade 进行获取,获取到监控数据之后你可以将其暴露给你的监控系统进行使用。Druid 默认的监控系统数据也来源于此。

三、fastjson介绍

fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。

fastjson优点:速度快、使用广泛(阿里自己用)、测试更新频繁、使用简便

fastjson的API十分简洁。

String text = JSON.toJSONString(obj); //序列化
VO vo = JSON.parseObject("{...}", VO.class); //反序列化

支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。 

四、整合具体步骤

1、项目的pom.xml中新增对Druid、fastjson的引用依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.54</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

2、修改项目属性文件application.properties,新增对Druid与fastjson的专属配置内容

a、Druid配置内容

#Druid连接池配置
spring.datasource.druid.initialSize=5
spring.datasource.druid.minIdle=5
spring.datasource.druid.maxActive=30
######Druid监控配置######
#是否启用StatFilter默认值true
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.filter.log4j2.statement-log-enabled=true
#IP 白名单
spring.datasource.druid.stat-view-servlet.allow=133.3.5.71
#IP 黑名单
#spring.datasource.druid.stat-view-servlet.deny=192.168.0.101
#监控地址,默认 /druid/*
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
#哪些资源配置监控:主要只静态资源和监控地址本身
spring.datasource.druid.WebStatFilter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
spring.datasource.druid.stat-view-servlet.login-username=wangli
spring.datasource.druid.stat-view-servlet.login-password=123456
# 配置StatFilter
spring.datasource.druid.filter.stat.db-type=mysql
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000
# 配置WallFilter
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.filter.wall.db-type=mysql
spring.datasource.druid.filter.wall.config.delete-allow=false
spring.datasource.druid.filter.wall.config.drop-table-allow=false

上面这些配置分别定义了连接池属性、Druid自身访问安全限制,监控资源类型及开通了状态监控及sql防火墙监控,用于使用Druid的扩展功能。netstat -nao | find "3306"

上面定义的连接池默认连接数为5,所以在应用服务器上与数据库服务器的连接也就是5个,如上图。 

b、fastjson配置内容

#fastjson配置
spring.http.converters.preferred-json-mapper=fastjson
#加入fastjson后需要配置否则json输出乱码
spring.http.encoding.force=true

3、通过Controller中增加入口加载Druid

import com.alibaba.druid.stat.DruidStatManagerFacade;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DruidStatController {
    @GetMapping("/druid/stat")
    public Object druidStat(){
        // DruidStatManagerFacade#getDataSourceStatDataList 
        // 该方法可以获取所有数据源的监控数据,除此之外 DruidStatManagerFacade 还提供了一些其他方法,你可以按需选择使用。
        return DruidStatManagerFacade.getInstance().getDataSourceStatDataList();
    }
}

4、将fastjson的加载代码注入项目启动文件中

@SpringBootApplication
public class InfoApplication {

    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters() {
        //1.需要定义一个Convert转换消息的对象
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        //2.添加fastjson的配置信息,比如是否要格式化返回的json数据
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
//        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty);
        fastJsonConfig.setSerializerFeatures(SerializerFeature.QuoteFieldNames,
                SerializerFeature.WriteEnumUsingToString,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat,
                SerializerFeature.DisableCircularReferenceDetect);
        //3.在convert中添加配置信息
        fastConverter.setFastJsonConfig(fastJsonConfig);
        HttpMessageConverter<?> converter = fastConverter;
        return new HttpMessageConverters(converter);
    }

    public static void main(String[] args) {
        SpringApplication.run(InfoApplication.class, args);
    }

}

5、修改IpbaseDao接口,将原来返回String的findbyipadd接口的返回类型修改为实体类,实现通过IP地址查询时返回为实体类后被fastjson拦截后转为JSON代码

import javax.transaction.Transactional;
import java.util.List;

@Transactional
public interface IpbaseDao extends CrudRepository<Ipbase, Long> {
    public Ipbase findByIpadd(String ipadd);

    @Override
    List<Ipbase> findAll();
}

6、修改ipcontroller文件,将原来的findip方法进行修改,配合第五步的成果

@RequestMapping(value = "/getipinfo", produces = "text/html;charset=UTF-8", method = RequestMethod.GET)
public Ipbase findip(String ip, HttpServletRequest request) {
    if (ip != null) {
        return ipbaseDao.findByIpadd(ip);
    } else {
        return ipbaseDao.findByIpadd(request.getRemoteAddr());
    }
}

@RequestMapping(value = "/getall")
public List<Ipbase> getall() {
    return ipbaseDao.findAll();
}

五、整合效果

1、输入指定ip地址查询返回JSON结果

http://133.3.5.71:8080/getipinfo?ip=202.103.44.150

{"city":"武汉","country":"中国","id":2,"ipadd":"202.103.44.150","isp":"电信","privince":"湖北"}

2、无输入参数返回JSON结果

http://133.3.5.71:8080/getipinfo

{"city":"武汉","country":"中国","id":1,"ipadd":"133.3.5.71","isp":"电信","privince":"湖北"}

3、返回全部ip列表JSON格式

http://133.3.5.71:8080/getall

[{"city":"武汉","country":"中国","id":1,"ipadd":"133.3.5.71","isp":"电信","privince":"湖北"},{"city":"武汉","country":"中国","id":2,"ipadd":"202.103.44.150","isp":"电信","privince":"湖北"}]

4、访问Druid监控界面必须要输入前面在application属性文件中定义的用户名密码,且ip地址是133.3.5.71才能登录

http://133.3.5.71:8080/druid/login.html

 5、查看Druid-JSON-API的版本情况

 

6、查看Druid数据源详细信息

 7、查看Druid的sql监控信息,之前我执行了两次查询,这里的监控马上更新自动显示

8、sql防火墙功能展示,自动识别业务系统操作的数据表,对sql语句进行识别

9、URI监控统计分析,通过观察URI的详细统计数据找出业务中存在问题的短板

 六、总结回顾

      使用阿里制作的成熟轮子可以迅速将我们不成熟的业务推向应用,互联网时代的业务很多都是尝试性的进入,没有那么多的时间和成本去试错,学习了解这些成熟的轮子,把自己有限的精力放在业务逻辑的实现上是最好的选择。       

 mysql每个连接是会创建一个线程的,可以登录mysql输入show status查看Threads_connected和Threads_created的大小,那么我们每连接一次mysql就会创建一个线程,每次断开又会销毁一个线程。创建线程和销毁线程的资源消耗是非常大的,不然也不会有线程池这个东西。

连接池避免了频繁的创建连接和销毁连接,内部避免了频繁的创建线程和销毁线程,其次mysql数据库会为每个连接分配连接缓冲区和结果缓冲区,也是要消耗时间的。

数据库连接池技术的思想非常简单,将数据库连接作为对象存储在一个Vector对象中,一旦数据库连接建立后,不同的数据库访问请求就可以共享这些连接,这样,通过复用这些已经建立的数据库连接,可以克服上述缺点,极大地节省系统资源和时间。

猜你喜欢

转载自blog.csdn.net/firehadoop/article/details/84997372