springcloud编写电影微服务

前言

1.springcloud Finchley.SR2版本
2.springboot 版本2.0.6.RELEASE
3.h2
4.jooq
5.consul
搭建一个电影微服务

目的

利用idea快速搭建一个springcloud集成上述功能的微服务,可以查询电影

正文

初始化工程

方法跟**springcloud编写用户微服务**中前期准备工程一般,勾选下列依赖

在resources文件夹下新增bootstrap.yml文件,写入以下内容

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
#tomcat启动启动端口
server:
port: 1018
spring:
application:
#项目名称
name: consul-movie
cloud:
consul:
#consul server的host或者ip
host: localhost
#consul server的端口
port: 18500
config:
#开启consul配置中心
enabled: true
#consul表示consul上面文件的格式 有四种 YAML PROPERTIES KEY-VALUE FILES
format: YAML
#表示consul上面的KEY值(或者说文件的名字) 默认是data
data-key: configuration
#prefix设置配置值的基本文件夹
prefix: config
#defaultContext设置所有应用程序使用的文件夹名
default-context: ${spring.application.name}
discovery:
#开启consul服务发现
enabled: true
#开启consul服务的名称
service-name: consul-movie
#服务检查的路径
health-check-path: /actuator/health
#服务检查的时间间隔
health-check-interval: 10s
#服务检查的完整路径
health-check-url: http://192.168.0.150:${server.port}${spring.cloud.consul.discovery.health-check-path}
tags: dev

初始化H2数据库

这时候决定手动初始化datasource,同时集成第三方数据库连接池进来,详情**springboot集成druid**
此时consul上的配置如下

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
spring:
datasource:
url: jdbc:h2:mem:test
#url: jdbc:h2:file:~/.h2/testdb
#url: jdbc:h2:~/testuser
driverClassName: org.h2.Driver
username: sa
password: 123456
platform: h2
schema: classpath:db/schema.sql
data: classpath:db/data.sql
initialization-mode: always #springboot2.0加上上述sql才会执行
# 下面为druid连接池的补充设置,应用到上面所有数据源中
# 初始化大小,最小,最大
initialSize: 1
minIdle: 3
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计
filters: stat
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
useGlobalDataSourceStat: true
h2:
console:
settings:
web-allow-others: true #进行该配置后,h2 web consloe就可以在远程访问了。否则只能在本机访问。
path: /h2-console #进行该配置,你就可以通过YOUR_URL/h2-console访问h2 web consloe。YOUR_URL是你程序的访问URl。
enabled: true #进行该配置,程序开启时就会启动h2 web consloe。当然这是默认的,如果你不想在启动程序时启动h2 web consloe,那么就设置为false。
#Actuator的健康检查开启所有包括health,info,metrics等
management:
endpoints:
web:
exposure:
include: "*"
#开启health端点详细检查
endpoint:
health:
show-details: always
logging:
level:
root: INFO
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE

根据配置在resources目录下,新增db文件夹,下面新增schema.sql和data.sql文件,内容分别如下

1
2
3
4
5
drop table movie if exists;
create table movie (id bigint generated by default as identity ,movie_name varchar(40),score decimal(10,2),primary key (id));

insert into movie (id,movie_name,score) values (1,'肖申克的救赎',100.00);
insert into movie (id,movie_name,score) values (2,'这个杀手不太冷',101.00);

在pom中添加依赖druid

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>

在主程序平级目录新增db目录,新增DataSourceBean.java和DatasourceConf.java

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
@Configuration
@Component
@Data
public class DataSourceBean {

private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceBean.class);

@Autowired
DatasourceConf datasourceConf;

@Bean
public DataSource getDataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(datasourceConf.getUrl());
datasource.setUsername(datasourceConf.getUsername());
datasource.setPassword(datasourceConf.getPassword());
datasource.setDriverClassName(datasourceConf.getDriverClassName());
//configuration
datasource.setInitialSize(datasourceConf.getInitialSize());
datasource.setMinIdle(datasourceConf.getMinIdle());
datasource.setMaxActive(datasourceConf.getMaxActive());
datasource.setMaxWait(datasourceConf.getMaxWait());
datasource.setTimeBetweenEvictionRunsMillis(datasourceConf.getTimeBetweenEvictionRunsMillis());
datasource.setMinEvictableIdleTimeMillis(datasourceConf.getMinEvictableIdleTimeMillis());
datasource.setValidationQuery(datasourceConf.getValidationQuery());
datasource.setTestWhileIdle(datasourceConf.getTestWhileIdle());
datasource.setTestOnBorrow(datasourceConf.getTestOnBorrow());
datasource.setTestOnReturn(datasourceConf.getTestOnReturn());
datasource.setPoolPreparedStatements(datasourceConf.getPoolPreparedStatements());
datasource.setMaxPoolPreparedStatementPerConnectionSize(datasourceConf.getMaxPoolPreparedStatementPerConnectionSize());
datasource.setUseGlobalDataSourceStat(datasourceConf.getUseGlobalDataSourceStat());
try {
datasource.setFilters(datasourceConf.getFilters());
} catch (SQLException e) {
LOGGER.error("druid configuration initialization filter: " + e);
}
datasource.setConnectionProperties(datasourceConf.getConnectionProperties());
return datasource;
}

/**
* 配置监控服务器
*
* @return 返回监控注册的servlet对象
*/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
// 添加IP白名单
servletRegistrationBean.addInitParameter("allow", "192.168.14.32,127.0.0.1");
// 添加IP黑名单,当白名单和黑名单重复时,黑名单优先级更高
servletRegistrationBean.addInitParameter("deny", "192.168.14.32");
// 添加控制台管理用户
servletRegistrationBean.addInitParameter("loginUsername", "druid");
servletRegistrationBean.addInitParameter("loginPassword", "123456");
// 是否能够重置数据
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}

/**
* 配置服务过滤器
*
* @return 返回过滤器配置对象
*/
@Bean
public FilterRegistrationBean statFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
// 添加过滤规则
filterRegistrationBean.addUrlPatterns("/*");
// 忽略过滤格式
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,");
return filterRegistrationBean;
}
}

@ConfigurationProperties(prefix = "spring.datasource")
@Component
@Data
public class DatasourceConf {

private String url;
private String username;
private String password;
private String driverClassName;
private int initialSize;
private int minIdle;
private int maxActive;
private int maxWait;
private int timeBetweenEvictionRunsMillis;
private int minEvictableIdleTimeMillis;
private String validationQuery;
private Boolean testWhileIdle;
private Boolean testOnBorrow;
private Boolean testOnReturn;
private Boolean poolPreparedStatements;
private int maxPoolPreparedStatementPerConnectionSize;
private String filters;
private String connectionProperties;
private Boolean useGlobalDataSourceStat;
}

重新启动主程序,此时会报一个小错,具体原因是由于druid开启了如下配置,当数据库为h2并且需要执
行新增表操作时,sql统计分析会合并异常,具体看github上面的issue

1
2
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计
filters: stat

检查
1.查看h2 ui,是否user表和数据是否写入 http://localhost:1016/h2-console/
2.查看druid监控页面 http://127.0.0.1:1016/druid/sql.html

集成jooq generate工具

具体教程可见**springboot集成jooq**
扩展
这里和user有一些不同的是,我将h2的数据库类型改成了内存,结果jooq-codegen-maven无法生成

1
2
3
4
5
6
7
<!-- JDBC connection parameters -->
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:mem:test</url>
<user>sa</user>
<password>123456</password>
</jdbc>

需要改成文件类型

1
2
3
4
5
6
7
<!-- JDBC connection parameters -->
<jdbc>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:~/testmovie</url>
<user>sa</user>
<password>123456</password>
</jdbc>

因为h2选择的是内存数据库,不管我是否将h2数据库开启(程序运行或不运行),然后执行jooq generate,都无法生成

如果我将h2类型改为file,那么这个时候不能运行源程序,才能执行jooq generate,否则执行jooq generate的时候会报错数据库使用中

扩展
在maven package时,由于集成了jooq generate工具,会执行一遍,这样如果自己修改了相关类会被还原,所以在打包时希望不执行相关驱动可以加如下配置
放在pom驱动配置的configuration标签内
20181030更新:注意这个标签添加之后,无论编译打包甚至直接运行这个插件都不再生成相关东西,如果你现在需要重新运行一遍,请先提交或者保存你做过的修改,然后注释掉这个,运行完之后再加上,然后再将你做的修改重新添加回来

1
2
<!-- install 跳过 -->
<skip>true</skip>

在打包的过程中,执行了springboot中的一些test,当从consul上远程读取yml配置时爆了如下错,忽略测试打包成功后,启动工程仍然报错,然而idea中自己run的时候却没有报错
对比了相关命令

远程yml配置中含有中文,务必在使用java -Dfile.encoding=UTF-8 -jar .\consul-movie-0.0.1-SNAPSHOT.jar指定utf8编码
不然打包会失败,启动失败,会报上面的错
https://github.com/jOOQ/jOOQ/blob/master/jOOQ-examples/jOOQ-spring-example/pom.xml

Cream Bing wechat
subscribe to my blog by scanning my public wechat account