Spring Boot(2.0) Maven多模块项目搭建简介
版本号 | 说明 | 创建时间 | 创建人 |
---|---|---|---|
1.0 | 创建 | 2018-05-15 | 吴桂镇 |
一、搭建环境
-编译器:Eclipse Oxygen.1a (4.7.1a)
-jdk:1.8
-Maven : 3.0
-操作系统:win10
二、项目创建
1.parent
新建一个maven project 如下图
点击next
填写相关信息,点击finish。注意Packaging 应选择pom
创建之后效果如下图
删除 src文件夹,并修改pom.xml。修改后修过如下图,
其中<parent></parent>中是对spring boot的集成
<modules></modules>是对maven子模块项目的引用,正常情况下创建子模块后才在parent的pom.xml中添加一条对应的module,此处预先添加好。
2.core
创建maven项目
点击finish 创建完毕。
修改pom.xml
添加<parent>对父模块的依赖,修改后如下图
3.api
创建过程类似于core 但是在pom.xml中添加对core的依赖
4.service
Service 为springboot项目,使用eclipse创建时应先添加spring sts插件,或者去 http://start.下载完成后导入进来,下面介绍使用sts插件创建的。
创建完毕之后修pom.xml,修改<parent>里的引用,从spring-boot-starter-parent 到 demo-parent,再引用api和core。
因为service不是一个web应用,可以不依赖spring-boot-starter-web
5.web
Web也是一个springboot的项目,创建过程与service类似,只是在pom.xml中增加了下面的依赖。
三、集成dubbo
1.在api中添加接口和对应的实体类
demo以themis数据库intf_fee表为例
实体类:
@SuppressWarnings("serial")
public** class IntfFee implements** Serializable{
**private** String intfId;
**private** String plateCde;
**private** String intfName;
**private** BigDecimal intfCost;
**private** BigDecimal intfPrice;
**private** String classType;
**private** String intfStatus;
**private** String remark;
**private** BigDecimal feeRowBegin;
**private** BigDecimal feeRowEnd;
**public** String getIntfId() {
**return** intfId;
}
**public**** void** setIntfId(String intfId) {
**this**.intfId = intfId;
}
**public** String getPlateCde() {
**return** plateCde;
}
**public**** void** setPlateCde(String plateCde) {
**this**.plateCde = plateCde;
}
**public** String getIntfName() {
**return** intfName;
}
**public**** void** setIntfName(String intfName) {
**this**.intfName = intfName;
}
**public** BigDecimal getIntfCost() {
**return** intfCost;
}
**public**** void** setIntfCost(BigDecimal intfCost) {
**this**.intfCost = intfCost;
}
**public** BigDecimal getIntfPrice() {
**return** intfPrice;
}
**public**** void** setIntfPrice(BigDecimal intfPrice) {
**this**.intfPrice = intfPrice;
}
**public** String getClassType() {
**return** classType;
}
**public**** void** setClassType(String classType) {
**this**.classType = classType;
}
**public** String getIntfStatus() {
**return** classType;
}
**public**** void** setIntfStatus(String intfStatus) {
**this**.intfStatus = intfStatus;
}
**public** String getRemark() {
**return** remark;
}
**public**** void** setRemark(String remark) {
**this**.remark = remark;
}
**public** BigDecimal getFeeRowBegin() {
**return** feeRowBegin;
}
**public**** void** setFeeRowBegin(BigDecimal feeRowBegin) {
**this**.feeRowBegin = feeRowBegin;
}
**public** BigDecimal getFeeRowEnd() {
**return** feeRowEnd;
}
**public**** void** setFeeRowEnd(BigDecimal feeRowEnd) {
**this**.feeRowEnd = feeRowEnd;
}
- 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
接口
public** interface** IDemoService {
String sayHello(String message);
- 1
- 2
}
2.配置服务端
在demo-service pom.xml中增加dubbo的依赖,如下
<!–dubbo-springBoot依赖–>
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.2</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
在application.properties中添加dubbo的相关配置,如下
dubbospringboot 配置
spring.dubbo.application.id=provider
spring.dubbo.application.name=provider
spring.dubbo.registry.address=zookeeper://127.0.0.1:2181
spring.dubbo.server=true
spring.dubbo.protocol.name=dubbo
spring.dubbo.protocol.port=20880
在启动类中添加@EnableDubboConfiguration注解
编写service
3.配置消费端
在demo-web的pom.xml添加依赖
<!--dubbo-springBoot依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zk-client.version}</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
在application.properties中添加dubbo的配置
Dubbo 服务消费者配置
spring.dubbo.application.name=consumer
spring.dubbo.application.id=consumer
spring.dubbo.protocol.port=20800
spring.dubbo.protocol.name=dubbo
spring.dubbo.registry.address=zookeeper://127.0.0.1:2181
注册中心请求超时时间
设置操作设置消费者超时时间(通过DubboConfig去读取,配置),默认使用服务端的超时时间,客户端配置时间则需要读取配置
然后新增dubboContext.xml 其中配置<dubbo:consumer timeout="${spring.dubbo.consumer.timeout}" cluster="failfast"/>
此项目使用服务端配置超时时间,故没有新增dubboContext.xml文件
spring.dubbo.consumer.timeout=300006
包路径也可以单独配置出dubbo包,将与dubbo交互的内容都存放在此处,分层明确
spring.dubbo.scan=com.caxs
在启动类中添加 @EnableDubboConfiguration 注解
编写测试controller
@RestController
public** class** TestController {
@Reference
**private** IDemoService demoService;
@RequestMapping("/")
**public** String sayHello(String msg) {
**return** demoService.sayHello(msg);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
}
注:使用@Reference来引用服务端提供的服务
四、集成mybatis
使用mysql 数据库
在demo-service中添加相应的依赖(mybatis,mysql,连接池)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
- 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
在配置文件中添加配置,采用yml格式的如下
spring:
application:
name: demo-service
#DATABASE CONFIG
- 1
- 2
- 3
- 4
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: your url
username: your username
password: your password
type: com.alibaba.druid.pool.DruidDataSource #这里是配置druid连接池,以下都是druid的配置信息
filters: stat,wall,log4j
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: **true**
testOnBorrow: **false**
testOnReturn: **false**
poolPreparedStatements: **true**
maxOpenPreparedStatements: 20
connection-properties: druid.stat.merggSql=ture;druid.stat.slowSqlMillis=5000
- 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
mybatis
mybatis:
mapper-locations: classpath*:/daos/**Dao.xml #把xml文件放在com.XX.mapper.*中可能会出现找到的问题,这里把他放在resource下的mapper中
#实体扫描,多个package用逗号或者分号分隔
#typeAliasesPackage: com.tdx.account_service.entity #这里是实体类的位置
configuration:
map-underscore-to-camel-case: **true**
cache-enabled: **false**
- 1
- 2
- 3
- 4
logging 不同的目录不同的日志输出级别
logging:
level:
root: info
- 1
- 2
com.wugz.demo: debug
添加dao层的接口和xml文件(此处示例使用注解的方式代替xml)
接口:
@Mapper
public interface IntfFeeDao {
/\*\*
\* 方式1:使用注解编写SQL。
\*/
//@Select("select \* from intf\_fee")
List<Map<String,Object>> list();
/\*\*
\*
\* PS:如果符合下划线转驼峰的匹配项可以直接省略不写。
\* 不匹配的例子 比如数据库字段为 PHONE\_NUM 实体类字段为mobileNum
\* 即可以做一个强行映射
\*
\*/
@Results({ @Result(property = "id", column = "ID"), @Result(property = "name", column = "Name"),
@Result(property = "countryCode", column = "CountryCode"),
@Result(property = "district", column = "District"),
@Result(property = "population", column = "Population")})
@Select("select \* from intf\_fee")
List<City> listSample();
- 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
}
在对应的service中注入dao层(使用@Autowired自动注入)
五、集成activeMQ
在demo-web中添加对应的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在配置文件中添加mq的配置
spring.activemq.broker-url=tcp://127.0.0.1:61616
spring.activemq.user=admin
spring.activemq.password=admin
spring.activemq.in-memory=false
mq生产者类:
@Component("queueSender")
public** class** QueueSender {
@Autowired
**private** JmsMessagingTemplate jmsMessagingTemplate;
/\*\*\*
\*
\* **@Description** (功能描述) : 发送消息
\* **@author** (作者) : 吴桂镇
\* **@date** (开发日期) : 2018年5月9日 下午5:11:46
\* **@exception** :
\* **@param** queueName
\* **@param** message void
\*/
**public**** void**sendString(String queueName,**final** String message){
jmsMessagingTemplate.convertAndSend(queueName, message);
}
- 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
}
mq消费者:
// 使用JmsListener配置消费者监听的队列,其中text是接收到的消息
@JmsListener(destination = "test.queue")
**public**** void** receiveQueue(String text) {
**LOGGER**.info("Consumer收到的报文为:"+text);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
}
六、集成redis
Windows本地redis创建参考
https://www.cnblogs.com/sxdcgaq8080/p/7204878.html
在service中添加相应的依赖
<!-- Spring Boot Reids 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring2.0集成redis所需common-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
在配置文件中添加相应配置
spring:
redis:
#数据库索引
database: 0
host: 127.0.0.1
port: 6379
password:
jedis:
pool:
#最大连接数
max-active: 8
#最大阻塞等待时间(负数表示没限制)
max-wait: -1
#最大空闲
max-idle: 8
#最小空闲
min-idle: 0
#连接超时时间
timeout: 10000
- 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
添加redis的配置类和自定义序列化类
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<Object>(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
- 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
}
public** class FastJsonRedisSerializer<T> implements** RedisSerializer<T> {
**public**** static ****final** Charset **DEFAULT\_CHARSET** = Charset._forName_("UTF-8");
**private** Class<T> clazz;
**public** FastJsonRedisSerializer(Class<T> clazz) {
**super** ();
**this**.clazz = clazz;
}
@Override
**public**** byte**[] serialize(T t)**throws** SerializationException {
**if** ( **null** == t) {
**return**** new ****byte** [0];
}
**return** JSON._toJSONString_(t, SerializerFeature. **WriteClassName** ).getBytes( **DEFAULT\_CHARSET** );
}
@Override
**public** T deserialize( **byte** [] bytes) **throws** SerializationException {
**if** ( **null** == bytes || bytes.length <= 0) {
**return**** null**;
}
String str = **new** String(bytes, **DEFAULT\_CHARSET** );
**return** (T) JSON._parseObject_(str, clazz);
}
- 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
}
编写操作redis的类
@Service
@org.springframework.stereotype.Service
public class RedisService implements IRedisService{
@Autowired
private RedisTemplate redisTemplate;
/\*\*
\* 写入缓存
\* @param key
\* @param value
\* @return
\*/
@Override
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/\*\*
\* 写入缓存设置时效时间
\* @param key
\* @param value
\* @return
\*/
@Override
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/\*\*
\* 批量删除对应的value
\* @param keys
\*/
@Override
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/\*\*
\* 批量删除key
\* @param pattern
\*/
@Override
public void removePattern(final String pattern) {
Set<Serializable> keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/\*\*
\* 删除对应的value
\* @param key
\*/
@Override
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/\*\*
\* 判断缓存中是否有对应的value
\* @param key
\* @return
\*/
@Override
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/\*\*
\* 读取缓存
\* @param key
\* @return
\*/
@Override
public Object get(final String key) {
Object result = null;
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/\*\*
\* 哈希 添加
\* @param key
\* @param hashKey
\* @param value
\*/
@Override
public void hmSet(String key, Object hashKey, Object value){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
hash.put(key,hashKey,value);
}
/\*\*
\* 哈希获取数据
\* @param key
\* @param hashKey
\* @return
\*/
@Override
public Object hmGet(String key, Object hashKey){
HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
return hash.get(key,hashKey);
}
/\*\*
\* 列表添加
\* @param k
\* @param v
\*/
@Override
public void listPush(String k,Object v){
ListOperations<String, Object> list = redisTemplate.opsForList();
list.rightPush(k,v);
}
/\*\*
\* 列表获取
\* @param k
\* @param l
\* @param l1
\* @return
\*/
@Override
public List<Object> lRange(String k, long l, long l1){
ListOperations<String, Object> list = redisTemplate.opsForList();
return list.range(k,l,l1);
}
/\*\*
\* 集合添加
\* @param key
\* @param value
\*/
@Override
public void add(String key,Object value){
SetOperations<String, Object> set = redisTemplate.opsForSet();
set.add(key,value);
}
/\*\*
\* 集合获取
\* @param key
\* @return
\*/
@Override
public Set<Object> setMembers(String key){
SetOperations<String, Object> set = redisTemplate.opsForSet();
return set.members(key);
}
/\*\*
\* 有序集合添加
\* @param key
\* @param value
\* @param scoure
\*/
@Override
public void zAdd(String key,Object value,double scoure){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
zset.add(key,value,scoure);
}
/\*\*
\* 有序集合获取
\* @param key
\* @param scoure
\* @param scoure1
\* @return
\*/
@Override
public Set<Object> rangeByScore(String key,double scoure,double scoure1){
ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
return zset.rangeByScore(key, scoure, scoure1);
}
- 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