Javanewb-Common
當(dāng)前版本:1.0-SNAPSHOT
集成工具:
ConfigServer(zookeeper),Mysql(MyBatis),Redis(規(guī)范化鍵名,分布式同步鎖),mongodb(基于springboot),lombok等
注意:請在使用時,在idea工具中安裝lombok插件支持
1.概述
本項目以spring-cloud、spring-boot為基礎(chǔ)骨架诅诱。利用spring微服務(wù)套件的快速搭建颖杏,規(guī)范化管理的優(yōu)勢,集成多種主流開源工具的二次封裝。以此達(dá)到矢门,業(yè)務(wù)開發(fā)人員可以在不用關(guān)心底層的情況下迅速開發(fā)膝迎,同時可以在本項目中進(jìn)行工具的擴(kuò)展和定制粥帚,能夠方便的對上層業(yè)務(wù)的開發(fā)方式進(jìn)行規(guī)范化。
2.集成方法:
2.2maven依賴添加:
在項目頂級pom.xml文件中加入如下內(nèi)容
<project>
<parent>
<groupId>com.javanewb.common</groupId>
<artifactId>common-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<repositories>
<repository>
<id>ali-nexus</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
<repository>
<id>ali-nexus-public-snapshots</id>
<url>http://maven.aliyun.com/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>javanewb-nexus</id>
<url>http://x.javanewb.com/nexus/content/repositories/releases/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
<repository>
<id>javanewb-nexus-snapshots</id>
<url>http://x.javanewb.com/nexus/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.javanewb.common</groupId>
<artifactId>starter-web</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
2.2ConfigServer(zookeeper)配置:
基礎(chǔ)模板地址
在module項目resources目錄中的bootstrap.yaml文件中加入如下配置:
spring:
profiles: dev
cloud:
zookeeper:
connectString: zk連接地址限次,多個時用逗號(芒涡,)分割
enabled: true
config:
enabled: true
root: /configurations/javanewb/${profile.active} //zk中配置路徑
defaultContext: apps //前綴
profileSeparator: ':' //前綴與profile的分隔符
3.嵌入式工具:
3.1Mysql:
3.1.1使用工具
mybatis:mybatis一直在業(yè)內(nèi)享有良好聲譽(yù)。對數(shù)據(jù)庫的操作可以有多種方式使用卖漫,目前主流的是XML方式费尽。XML的方式可以靈活的對SQL進(jìn)行編寫,同時還具有很大程度的可編碼性羊始,受到大家歡迎旱幼。但是,其XML+SQL的配置方式較為繁瑣突委,一些簡單的CURD都需要自己寫SQL進(jìn)行配置才能使用柏卤,雖然后面新版本引入了注解、接口等方式匀油。但是缘缚,由于xml配置的方式使SQL能集中存放,并便于管理所以很少會有項目會使用注解或接口的方式敌蚜。
tk.mapper:上面mybatis的介紹中提到桥滨,mybatis的XML方式雖然有很多優(yōu)點。但是钝侠,像最簡單的CURD都需要自己寫SQL進(jìn)行管理该园。無疑這造成了開發(fā)人員很大程度的重復(fù)無意義勞動。此時帅韧,開源的mybatis工具tk.mapper就派上了用場里初。它可以在mybatis在mapper進(jìn)行映射時幫助生成簡單的CRUD,極大程度減少了mybatis的使用時的無意義勞動忽舟。
依賴包:
<dependency>
<groupId>com.javanewb.common</groupId>
<artifactId>starter-mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3.1.1.1mysql數(shù)據(jù)庫配置:
數(shù)據(jù)庫使用阿里的Druid連接池双妨,默認(rèn)情況下只需要配置master就可以了。
datasource:
master:
driverClassName:com.mysql.jdbc.Driver
initialSize:1
maxIdle:5
maxTotal:5
maxWait:60000
minIdle:1
password:
removeAbandonedOnBorrow:true
removeAbandonedTimeout:180
testOnBorrow:false
testWhileIdle:true
timeBetweenEvictionRunsMillis:30000
url:jdbc:mysql://127.0.0.1:3306/demo_database?useUnicode:true&characterEncoding:utf8
username:root
validationQuery:select 1
slave:
driverClassName:com.mysql.jdbc.Driver
initialSize:1
maxIdle:5
maxTotal:5
maxWait:60000
minIdle:1
password:
removeAbandonedOnBorrow:true
removeAbandonedTimeout:180
testOnBorrow:false
testWhileIdle:true
timeBetweenEvictionRunsMillis:30000
url:jdbc:mysql://127.0.0.1:3306/demo_database?useUnicode:true&characterEncoding:utf8
username:root
validationQuery:select 1
3.1.1.2使用配置:
DAO接口需要繼承com.javanewb.common.configuration.mybatis.CommonsMapper<T> 類,并且放入com.javanewb.**.dao/mapper包下.如果,需要修改DAO接口的包地址.需要在yml配置中添加如下屬性:
common:
mapper-path: {com.xxx.dao,com.xxx.mapper...}
實體類地址,需要在application.yaml中加入如下配置
mybatis:
conf:
entityPath: com.javanewb.common.entity//實體類的地址
同時叮阅,不要忘記在zk中配置datasource刁品,和active這個profile
3.1.1.3讀寫分離配置:
如果,需要讀寫分離配置浩姥,需要配置上slave的數(shù)據(jù)源挑随。同時,需要在yaml配置文件中將common:r-w-split-enabled屬性設(shè)為true勒叠。
類中的方法需要將操作的動詞作為方法名開頭兜挨。默認(rèn)有如下的開頭做為讀操作:insert,update,modify,new,create,delete,remove膏孟。如果,還有其他前綴的方法需要使用寫庫拌汇∑馍#可以使用common:write-d-b-names:進(jìn)行添加,接受參數(shù)是一個string數(shù)組噪舀。
3.1.1.4 xml方法使用配置:
mapper.xml文件需要放在classpath根目錄下的mapper文件夾中魁淳。用法與傳統(tǒng)的mybatis xml文件一樣。其他使用方式與mybatis原有方式一樣.
3.1.2使用方法:
3.1.2.1實體類:
實體類配置中与倡,所有的數(shù)據(jù)庫相關(guān)配置使用java通用的jpa注解
@Data
public class User {
@Id
@Column(name = "Id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private String address;
private String gender;
private Integer age;
}
3.1.2.2tk.mybatis的使用:
由于tk.mybatis中已經(jīng)集成部分簡單的單表curd操作界逛,所以如果有特殊需求才需要在mapper.xml中進(jìn)行個性化配置
@Repository("user")
public interface UserMapper extends CommonsMapper<User>{//如果需要使用tk.mybatis必須繼承此接口
}
public class service{
@Autowired
private UserMapper userMapper;
public void userInsert() {
User user = new User();
user.setUsername("Crowhyc");
user.setPassword("123456");
user.setAddress("java");
user.setAge(25);
user.setGender("男");
userMapper.insertUseGeneratedKeys(user);//特別注意,使用自生成的主鍵方式insert需要在數(shù)據(jù)庫中蒸走,將表的主鍵定義為autoincrement仇奶。否則需要顯式的set主鍵
}
}
3.2redis:
3.2.1功能介紹:
redis是大家比較熟悉的nosql(K-V)內(nèi)存數(shù)據(jù)庫中的一種,由于他優(yōu)秀的速度和多種可直接使用的數(shù)據(jù)結(jié)構(gòu)可以在很多地方用到比驻。k-v的結(jié)構(gòu)雖然給redis的使用帶來了方便该溯。但是,很多時候每個項目開發(fā)者對k的設(shè)計有不同的想法别惦。
導(dǎo)致多項目在使用同一個redis庫的時候狈茉,key是雜亂無章,慘不忍睹掸掸÷惹欤基于這個問題,redis模塊在封裝時將key的格式做了強(qiáng)制限定扰付。大家在使用時就不會在看到五花八門的key格式了堤撵。目前,考慮到大家分布式結(jié)構(gòu)和集群使用的普遍性羽莺,模塊內(nèi)也集成了簡單的分布式鎖实昨。默認(rèn)10s過期,避免不當(dāng)使用時導(dǎo)致的死鎖產(chǎn)生盐固。
由于時間限制荒给。模塊目前只支持k-v和set數(shù)據(jù)結(jié)構(gòu)的操作,后面會逐步更新支持所有redis的數(shù)據(jù)結(jié)構(gòu)刁卜。
3.2.2依賴包:
<dependency>
<groupId>com.javanewb.common</groupId>
<artifactId>starter-redis</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
由于志电,redis的key被強(qiáng)制規(guī)范化。所以蛔趴,我們先要創(chuàng)建一個rediskey的生成類:
@Component
public class RedisConst {
/**
* RedisKey通過KeyFactory工廠生成
* getRedisKey方法通過接收的字符串?dāng)?shù)組挑辆,將每個字符串通過":"冒號連接,
* 也將app_name與active的profile加上在最前面,在使用redis工具的時候可以方便的分級查看之拨。
* 例如:portal:dev:shoppingcart:1
* getRedisKey(expireTime,String... keys)獲取有過期時間的key
* getRedisKey(String... keys)獲取永久的key
*/
@Autowired
private RedisKeyFactory keyFactory;
public static final int EXPIRE_TIME = 30 * 60;//秒
/**
* @param id keyid
* @param mainKey 主鍵
* @return
*/
public RedisKey getExpireTimeKey(Long id,String mainKey) {
return keyFactory.getRedisKey(EXPIRE_TIME, mainKey, id + "");
}
/**
* @param id
* @param mainKey
* @return
*/
public RedisKey getPermanentKey(Long id,String mainKey) {
return keyFactory.getRedisKey(EXPIRE_TIME, mainKey, id + "");
}
}
Operation的使用:
public class RedisTest extends BaseTest {
@Autowired
private CommonRedisTemplate<String> commonRedisTemplate;
@Autowired
private RedisConst redisConst;
@Test
public void insertValue() {
String val = "測試內(nèi)容";
commonRedisTemplate.opsCommonValue().set(redisConst.getExpireTimeKey(1L,"expireKey"),val);
commonRedisTemplate.opsCommonValue().set(redisConst.getPermanenstKey(2L,"permanentKey"),val);
}
}
3.3lombok:
3.3.1介紹:
Lombok是一個可以通過簡單的注解形式來幫助我們簡化消除一些必須有但顯得很臃腫的Java代碼的工具茉继,通過使用對應(yīng)的注解,可以在編譯源碼的時候生成對應(yīng)的方法蚀乔。
官方地址:https://projectlombok.org/
github地址:https://github.com/rzwitserloot/lombok。
3.3.2使用方法:
3.3.2.1插件安裝:
不管是IDEA還是Eclipse菲茬,在使用之前都需要安裝插件,IDE才能正常的理解lombok的注解吉挣,具體的插件安裝方法可以從去官網(wǎng)查看。
3.3.2.2注解介紹:
下面只是介紹了幾個常用的注解婉弹,更多的請參見https://projectlombok.org/features/index.html睬魂。
@Getter / @Setter
可以作用在類上和屬性上,放在類上镀赌,會對所有的非靜態(tài)(non-static)屬性生成Getter/Setter方法氯哮,放在屬性上,會對該屬性生成Getter/Setter方法商佛。并可以指定Getter/Setter方法的訪問級別喉钢。
@EqualsAndHashCode
默認(rèn)情況下,會使用所有非瞬態(tài)(non-transient)和非靜態(tài)(non-static)字段來生成equals和hascode方法良姆,也可以指定具體使用哪些屬性肠虽。
@ToString
生成toString方法,默認(rèn)情況下玛追,會輸出類名税课、所有屬性,屬性會按照順序輸出痊剖,以逗號分割韩玩。
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
無參構(gòu)造器、部分參數(shù)構(gòu)造器陆馁、全參構(gòu)造器找颓,當(dāng)我們需要重載多個構(gòu)造器的時候,Lombok就無能為力了氮惯。
@Data
@ToString, @EqualsAndHashCode, 所有屬性的@Getter, 所有non-final屬性的@Setter和@RequiredArgsConstructor的組合叮雳,通常情況下,我們使用這個注解就足夠了妇汗。
4Web相關(guān):
4.1http請求處理:
4.1.1消息返回格式:
{
"timestamp": "1511152931522",//時間
"code": 200,//結(jié)果碼
"msg": "status:200:message.isOk", //結(jié)果信息
"msgId": "20f173e22dae486cbbaee103142ef3a8@",//請求唯一編碼
"data": {//數(shù)據(jù)內(nèi)容
}
}
4.1.2異常處理方式:
異常信息格式:
{
"code": 1006,//異常碼
"msg": "發(fā)生異常請?zhí)幚鞽XX",//異常信息
"mdcTarget": "e1e734f78beb434589ac7b162b8e339d@",//請求唯一編碼
"timestamp": 1511153006734//請求時間
}
異常信息的開發(fā)示例:
public class DuplicationBizIdException extends BusinessException {//繼承javanewb common包中的businessException 異常父類
public DuplicationBizIdException() {
super(ManageErrorCode.DUPLICATION_BIZ_ID//異常碼, "重復(fù)的業(yè)務(wù)id"http://異常信息);
}
}
注意:如果遇到未捕獲的異常,返回會統(tǒng)一為系統(tǒng)錯誤
4.2Swagger:
4.2.1Swagger配置:
common:
swagger:
enabled: true //是否開啟
api-info:
title: 測試標(biāo)題
version: 1.0.0 //版本
description: Portal-Common測試項目 //描述
path-regex: /demo.* //需要mapping的url地址正則帘不,注意.*不能丟
swagger-codegen 介紹
swagger-codegen 支持 swagger的schema 生成不同語言的客戶端代碼。 在linux console 輸入:swagger-codegen杨箭,會列出支持的語法
Available languages: [android, aspnet5, async-scala, cwiki, csharp, cpprest, dart, flash, python-flask, go, groovy, java, jaxrs, jaxrs-cxf, jaxrs-resteasy, jaxrs-spec, inflector, javascript, javascript-closure-angular, jmeter, nancyfx, nodejs-server, objc, perl, php, python, qt5cpp, ruby, scala, scalatra, silex-PHP, sinatra, rails5, slim, spring, dynamic-html, html, html2, swagger, swagger-yaml, swift, tizen, typescript-angular2, typescript-angular, typescript-node, typescript-fetch, akka-scala, CsharpDotNet2, clojure, haskell, lumen, go-server]
具體命令查看:https://github.com/swagger-api/swagger-codegen#generators
官方地址:http://swagger.io/
github地址:https://github.com/swagger-api/swagger-codegen
4.3請求唯一編碼:
實現(xiàn)代碼:
public class LoggerMDCFilter implements Filter {
public static final String HEADER_KEY_KRY_GLOBAL_MSG_ID = "_kry_global_msg_id";
public static final String IDENTIFIER = "IDENTIFIER";
public static final String URI_KEY = "URI";
private String getId(String s) {
return String.format("%s@", s);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String kryGlobalMsgId = req.getHeader(HEADER_KEY_KRY_GLOBAL_MSG_ID);
if (StringUtils.isBlank(kryGlobalMsgId)) {
kryGlobalMsgId = getId(UUIDUtil.getUUID());
} else {
kryGlobalMsgId = getId(String.valueOf(kryGlobalMsgId));
}
// 唯一標(biāo)識埋點寞焙,設(shè)置線程唯一標(biāo)識,方便查找日志,組合方式 時間戳@請求埋點@線程號
MDC.put(IDENTIFIER, kryGlobalMsgId);
// uri_key
MDC.put(URI_KEY, req.getRequestURI());
chain.doFilter(request, response);
}
/**
* 銷毀MDC
*/
@Override
public void destroy() {
MDC.remove(IDENTIFIER);
MDC.remove(URI_KEY);
}
}
-
Java 代碼中使用:
MDC.get(LoggerMDCFilter.IDENTIFIER);
Logback.xml 中配置:
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<!--<withJansi>true</withJansi>-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %level %X{IDENTIFIER}%thread %X{URI} %logger[%method:%line] - %msg%n
</pattern>
<charset>utf8</charset>
</encoder>
</appender>
5.Spring-boot autoconfig工具:
4.1ActiveMq:
yaml配置:
spring:
activemq:
broker-url:failover:(tcp://XXX:61616,tcp://XXX:61616,tcp://XXX:61616)
user:admin
password:xxxx
pooled:true是否創(chuàng)建PooledConnectionFactory捣郊,而非ConnectionFactory辽狈,默認(rèn)false
in-memory:true是否是內(nèi)存模式,默認(rèn)為true
jms:
pub-sub-domain:true是否使用默認(rèn)的destination type來支持 publish/subscribe呛牲,默認(rèn): false
使用示例:
configuration配置:
@Configuration
@EnableJms
public class AMQConfig{
//配置通道
@Bean
public ActiveMQTopic clusterActiveMQTopic() {
return new ActiveMQTopic("com.keruyun." + activeProfile + ".shoppingcart");
}
//配置監(jiān)聽器容器刮萌,及包括的監(jiān)聽器
@Bean
public DefaultMessageListenerContainer clusterContainer(ConnectionFactory connectionFactory, ActiveMQTopic clusterActiveMQTopic, NoticeService noticeService) {
DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setDestination(clusterActiveMQTopic);
container.setMessageListener(new ClusterListener());
return container;
}
}
監(jiān)聽器實現(xiàn):(實現(xiàn)javax.jms.MessageListener接口)
@Service
@Slf4j
public class ClusterListener implements MessageListener {
@Override
public void onMessage(Message message) {
//收到MQ消息后的具體業(yè)務(wù)實現(xiàn)
}
}
發(fā)布器實現(xiàn):
@Service
public class MqService {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;//autoconfig根據(jù)配置默認(rèn)構(gòu)建的對象,如無特殊需求娘扩,不用自己構(gòu)造
@Autowired
private ActiveMQTopic clusterActiveMQTopic;//注意屬性名要與config中實例化Bean的方法名對應(yīng)
public void send(String msg) {
jmsMessagingTemplate.convertAndSend(clusterActiveMQTopic, msg);//發(fā)送消息
}
}
4.2Mongodb:
依賴包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>1.5.7.RELEASE</version>
</dependency>
yaml配置
spring:
# HTTP ENCODING
http:
encoding.charset: UTF-8
encoding.enable: true
encoding.force: true
data:
mongodb://配置方法1
host: 127.0.0.1
port: 27017
username:
password:
database: xx
authenticationDatabase:
mongodb://配置方法2
url: mongodb://用戶名:密碼@數(shù)據(jù)庫地址1,數(shù)據(jù)庫地址2/數(shù)據(jù)庫名
使用示例:
public interface PersonRepository extends MongoRepository<Person, String>{
//MongoRepository<實體,主鍵類型>
//MongoRepository中已經(jīng)默認(rèn)支持了簡單的CRUD方法可以直接使用
}
上述示例只是簡單的CRUD方法着茸,如果需要自定義復(fù)雜的方法,請參考網(wǎng)址琐旁。也可以直接使用Autowire注解獲取MongoTemplate使用熟悉的Query涮阔,Criteira模式進(jìn)行查詢
4.3Schedule定時工具:
配置:
只需要在任意Configuration文件上加入@EnableScheduling,保證在啟動時這個配置文件會被spring正常加載灰殴,便可以輕松開啟單服quart定時器敬特。
使用方法:
在需要進(jìn)行定時調(diào)用的方法頭上添加@Scheduled注解,@Scheduled注解有多種屬性用于方便配置執(zhí)行間隔:
屬性介紹:
屬性名 | 用處 | 示例 |
---|---|---|
fixedDelay | 按延遲執(zhí)行 | fixedDelay = 5000 |
cron | 按cron表達(dá)式執(zhí)行 | cron = "0/5 * * * * *" |
fixedRate | 按間隔執(zhí)行 | fixedRate = 5000 |
initialDelay | 首次執(zhí)行的延遲時間 | initialDelay = 5000 |
5.聯(lián)系方式:
E-Mail:crowhyc@163.com
博客:http://blog.csdn.net/crowhyc
希望和大家一起將這個工具越做越好牺陶,如在閱讀或使用中遇到問題伟阔,或更好的實現(xiàn)方案、工具义图。請聯(lián)系我减俏。
java.云逸