childrenNodeHandlerMap);
318 |
319 | /**
320 | * 下线本机节点
321 | */
322 | void offlineLocalMachineNode() throws KeeperException, InterruptedException;
323 |
324 | /**
325 | * 上线本机节点
326 | */
327 | void onlineLocalMachineNode() throws KeeperException, InterruptedException, IOException;
328 |
329 | /**
330 | * 判断本机节点是否已在zk上注册
331 | *
332 | * @return
333 | */
334 | boolean isLocalMachineOnline();
335 |
336 |
337 | }
338 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/service/zookeeper/impl/DomiZkManager.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.service.zookeeper.impl;
2 |
3 | import com.company.project.core.service.zookeeper.MachineNode;
4 | import com.company.project.core.service.zookeeper.ZkManager;
5 | import com.company.project.core.service.zookeeper.watcher.DomiChildrenNodeHandler;
6 | import com.company.project.core.service.zookeeper.watcher.DomiNodeHandler;
7 | import com.company.project.core.service.zookeeper.watcher.DomiZkEventWatcher;
8 | import com.company.project.core.service.dynProps4Files.DynProps4FilesService;
9 | import org.apache.commons.lang.StringUtils;
10 | import org.apache.zookeeper.*;
11 | import org.apache.zookeeper.data.Stat;
12 | import org.slf4j.Logger;
13 | import org.slf4j.LoggerFactory;
14 | import org.springframework.core.env.Environment;
15 | import org.springframework.stereotype.Service;
16 | import org.springframework.util.CollectionUtils;
17 |
18 | import javax.annotation.PostConstruct;
19 | import javax.annotation.Resource;
20 | import java.io.IOException;
21 | import java.io.UnsupportedEncodingException;
22 | import java.net.Inet4Address;
23 | import java.net.InetAddress;
24 | import java.net.NetworkInterface;
25 | import java.net.SocketException;
26 | import java.util.ArrayList;
27 | import java.util.Enumeration;
28 | import java.util.List;
29 | import java.util.Map;
30 | import java.util.concurrent.ConcurrentHashMap;
31 | import java.util.concurrent.CountDownLatch;
32 | import java.util.concurrent.LinkedBlockingQueue;
33 | import java.util.concurrent.TimeUnit;
34 | import java.util.concurrent.atomic.AtomicBoolean;
35 | import java.util.concurrent.locks.Lock;
36 | import java.util.concurrent.locks.ReentrantLock;
37 |
38 | /**
39 | * ZK 连接管理器
40 | *
41 | * 节点结构信息
42 | *
43 | * /domi_tc
44 | * |
45 | * +-machine_list
46 | * |
47 | * |-machine_name1: machine_info1
48 | * +-machine_name2: machine_info2
49 | *
50 | *
51 | * @author jimersylee
52 | * 2017-09-25 14:34:54
53 | */
54 | @Service
55 | public class DomiZkManager implements ZkManager {
56 | private static final String DEFAULT_CHARSET = "UTF-8";
57 | private static final Logger logger = LoggerFactory.getLogger(DomiZkManager.class);
58 | private static final int DEFAULT_SERVICE_PORT = 8080;
59 | private ZooKeeper zk = null;
60 | private static boolean inited = false;
61 | private static Lock LOCK = new ReentrantLock();
62 |
63 | private AtomicBoolean online = new AtomicBoolean(true);
64 |
65 |
66 | @Resource
67 | private DynProps4FilesService dynProps4FilesService;
68 |
69 | @Resource
70 | private Environment env;
71 |
72 | /**
73 | * 节点数据变化监听处理器
74 | */
75 | private static final ConcurrentHashMap nodeChangedHandlerHolder = new ConcurrentHashMap();
76 | /**
77 | * 子节点变化监听处理器
78 | */
79 | private static final ConcurrentHashMap childrenChangedHandlerHolder = new ConcurrentHashMap();
80 |
81 | /**
82 | * 需处理的ZK事件
83 | */
84 | private static volatile LinkedBlockingQueue zkEventQueue = new LinkedBlockingQueue(128);
85 |
86 |
87 | /**
88 | * ZK事件消费者
89 | */
90 | private List consumers = new ArrayList();
91 |
92 | /**
93 | * 事件消费者数量。同时该参数决定本机器最多可同时运行多少任务
94 | */
95 | private int eventConsumerNum = 2;
96 |
97 | /**
98 | * zk 连接字符串 ip:port,ip1:port1,...,ipn:portn
99 | */
100 | private String hostPort;
101 |
102 | /**
103 | * zk 会话超时时间(MS)
104 | */
105 | private int sessionTimeout = 3600000;
106 |
107 | /**
108 | * zk 全局事件处理器
109 | */
110 | private Watcher watcher = null;
111 |
112 | private CountDownLatch latch;
113 |
114 | /**
115 | * 自身节点监听器
116 | */
117 | private DomiNodeHandler localMachineHandler;
118 |
119 | /**
120 | * 自身节点对象
121 | */
122 | private MachineNode localMachine;
123 |
124 | /**
125 | * 本机节点zk路径
126 | */
127 | private String nodePath;
128 |
129 |
130 | public DomiZkManager() {
131 |
132 | }
133 |
134 |
135 | /**
136 | * 连接ZK 发布本机节点
137 | */
138 | @PostConstruct
139 | public void init() throws IOException {
140 |
141 | //构造本机节点
142 | if (localMachine == null) {
143 |
144 | localMachine = new MachineNode();
145 | String ip = "";
146 | ip = env.getProperty("LOCAL_HOST_NAME");
147 | if (StringUtils.isBlank(ip)) {
148 | ip = getLocalIpAddress();
149 | }
150 | localMachine.setHostname(ip);
151 | Integer port = null;
152 | port = env.getProperty("LOCAL_PORT", Integer.class);
153 |
154 | if (port == null) {
155 | port = DEFAULT_SERVICE_PORT;
156 | }
157 | localMachine.setPort(port);
158 | }
159 |
160 | if (watcher == null) {
161 | watcher = new DomiZkEventWatcher(this, localMachine);
162 | }
163 |
164 |
165 | boolean lockResult = LOCK.tryLock();
166 | //防止多个线程同时调本方法,若发现已有线程正在调此方法,则直接返回
167 | if (!lockResult) {
168 | return;
169 | }
170 |
171 |
172 | this.hostPort = env.getProperty("ZK_HOSTS");
173 | this.eventConsumerNum=env.getProperty("EVENT_CONSUMER_NUM",Integer.class);
174 | this.sessionTimeout=env.getProperty("SESSION_TIMEOUT",Integer.class);
175 |
176 |
177 | try {
178 | latch = new CountDownLatch(1);
179 | if (zk != null) {
180 | try {
181 | zk.close();
182 | } catch (InterruptedException e) {
183 | //do nothing
184 | }
185 | }
186 |
187 |
188 | if (!inited) {
189 | nodePath = TC_MACHINE_LIST_PATH + PATH_SPLITTER + localMachine.nodeName();
190 | Thread thread = null;
191 | EventConsumer ec = null;
192 | for (int i = 0; i < eventConsumerNum; i++) {
193 | ec = new EventConsumer();
194 | thread = new Thread(ec, "ZK-Event-Consumer-" + i);
195 | thread.start();
196 | //之所以把runnable加入LIST ,是为了在运行结束时,为EventConsumer 设置结束标志,让它正常结束线程
197 | consumers.add(ec);
198 | }
199 |
200 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
201 | @Override
202 | public void run() {
203 | if (zk != null) {
204 | try {
205 | zk.close();
206 | } catch (InterruptedException e) {
207 | //do nothing
208 | }
209 | }
210 | if (!CollectionUtils.isEmpty(consumers)) {
211 | //停止zk事件消费线程
212 | for (EventConsumer consumer : consumers) {
213 | consumer.shutdown = true;
214 | }
215 | }
216 |
217 | }
218 | }));
219 |
220 | //注册默认监听器
221 | if (localMachineHandler != null) {
222 | nodeChangedHandlerHolder
223 | .putIfAbsent(TC_MACHINE_LIST_PATH + PATH_SPLITTER + localMachine.nodeName(), localMachineHandler);
224 | }
225 |
226 | inited = true;
227 | }
228 |
229 | zk = new ZooKeeper(hostPort, sessionTimeout, watcher);
230 |
231 | if (StringUtils.equalsIgnoreCase(dynProps4FilesService.getProperty("CLOSE_ZK_CNN", "FALSE"), "TRUE")) {
232 | //仅在本地环境使用
233 | try {
234 | TimeUnit.SECONDS.sleep(1);
235 | } catch (InterruptedException e) {
236 | //do nothing
237 | }
238 | try {
239 | this.offlineLocalMachineNode();
240 | } catch (Exception e) {
241 | logger.error("Offline failed.", e);
242 | }
243 | }
244 |
245 |
246 | } finally {
247 | LOCK.unlock();
248 | }
249 | }
250 |
251 |
252 | /**
253 | * 等待建立连接
254 | */
255 | @Override
256 | public void waitForConnected() {
257 | try {
258 | latch.await();
259 | } catch (InterruptedException e) {
260 | logger.error("", e);
261 | }
262 | }
263 |
264 | @Override
265 | public void countDownWaitForConnectedLatch() {
266 | latch.countDown();
267 | }
268 |
269 | /**
270 | * 追加监视的ZK事件
271 | *
272 | * @param event
273 | */
274 | @Override
275 | public void addEvent(WatchedEvent event) {
276 | if (event == null) {
277 | logger.info("event is null");
278 | return;
279 | }
280 | //在这里过滤不需要处理的事件
281 | String path = event.getPath();
282 | if (!nodeChangedHandlerHolder.containsKey(path) && !childrenChangedHandlerHolder.containsKey(path)) {
283 | logger.info("No handler found.for path[{}]", path);
284 | return;
285 | }
286 |
287 |
288 | try {
289 | zkEventQueue.put(event);
290 | logger.info("event is add into zkEventQueue.EVENT[{}]", event);
291 | } catch (InterruptedException e) {
292 | logger.error("Adding zk event failed! [" + event + "]", e);
293 | }
294 | }
295 |
296 | public String getHostPort() {
297 | return hostPort;
298 | }
299 |
300 | public void setHostPort(String hostPort) {
301 | this.hostPort = hostPort;
302 | }
303 |
304 | public int getSessionTimeout() {
305 | return sessionTimeout;
306 | }
307 |
308 | public void setSessionTimeout(int sessionTimeout) {
309 | this.sessionTimeout = sessionTimeout;
310 | }
311 |
312 | public Watcher getWatcher() {
313 | return watcher;
314 | }
315 |
316 | public void setWatcher(Watcher watcher) {
317 | this.watcher = watcher;
318 | }
319 |
320 | /**
321 | * 发布非持久化节点
322 | *
323 | * @param path
324 | * @param value
325 | * @return 实际创建的节点路径
326 | * @throws KeeperException
327 | * @throws InterruptedException
328 | */
329 | @Override
330 | public String createEphemeralNode(String path, String value) throws KeeperException, InterruptedException {
331 |
332 | try {
333 | return zk.create(path, value.getBytes(DEFAULT_CHARSET), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
334 | } catch (UnsupportedEncodingException e) {
335 | //unreachable
336 | return null;
337 | }
338 | }
339 |
340 |
341 | /**
342 | * 发布持久化节点
343 | *
344 | * @param path
345 | * @param value
346 | * @return 实际创建的节点路径
347 | * @throws KeeperException
348 | * @throws InterruptedException
349 | */
350 | @Override
351 | public String createNode(String path, String value) throws KeeperException, InterruptedException {
352 | waitForConnected();
353 |
354 | try {
355 | return zk.create(path, value.getBytes(DEFAULT_CHARSET), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
356 | } catch (UnsupportedEncodingException e) {
357 | //unreachable
358 | return null;
359 | }
360 | }
361 |
362 | /**
363 | * 取当前节点路径的父路径。
364 | *
365 | * @param nodePath
366 | * @return 父路径。当前节点为"/"时,则返回null.
367 | */
368 | private static String getParentPath(String nodePath) {
369 | if (StringUtils.isBlank(nodePath)) {
370 | throw new IllegalArgumentException("Param nodePath should not be blank!");
371 | }
372 | if (StringUtils.equals(PATH_SPLITTER, StringUtils.trim(nodePath))) {
373 | return null;
374 | }
375 |
376 | return nodePath.substring(0, nodePath.lastIndexOf(PATH_SPLITTER));
377 | }
378 |
379 |
380 | /**
381 | * 创建节点。若父节点不存在则先创建父节点
382 | *
383 | * @param path
384 | * @param value
385 | * @return
386 | * @throws KeeperException
387 | * @throws InterruptedException
388 | */
389 | public String createNodeRecursively(String path, String value) throws KeeperException, InterruptedException {
390 | waitForConnected();
391 | String parentPath = getParentPath(path);
392 |
393 | if (!exists(parentPath)) {
394 | createNodeRecursively(parentPath, "");
395 | }
396 |
397 | return createNode(path, value);
398 | }
399 |
400 | /**
401 | * @param path
402 | * @param value
403 | * @return
404 | * @throws KeeperException
405 | * @throws InterruptedException
406 | */
407 | @Override
408 | public Stat updateNodeData(String path, String value) throws KeeperException, InterruptedException {
409 | return updateNodeData(path, value, -1);
410 | }
411 |
412 | /**
413 | * 创建节点信息,若该节点已存在则更新此节点数据
414 | *
415 | * @param path
416 | * @param value
417 | */
418 | @Override
419 | public void createOrUpdateNodeData(String path, String value) throws KeeperException, InterruptedException {
420 | if (exists(path)) {
421 | updateNodeData(path, value);
422 | } else {
423 | createNodeRecursively(path, value);
424 | }
425 | }
426 |
427 | /**
428 | * 判断节点是否存在
429 | *
430 | * @param path
431 | * @return
432 | * @throws KeeperException
433 | * @throws InterruptedException
434 | */
435 | @Override
436 | public boolean exists(String path) throws KeeperException, InterruptedException {
437 | return exists(path, false);
438 | }
439 |
440 | /**
441 | * 判断节点是否存在
442 | *
443 | * @param path
444 | * @param watch 监听此节点create 、delete事件
445 | * @return
446 | * @throws org.apache.zookeeper.KeeperException
447 | * @throws InterruptedException
448 | */
449 | @Override
450 | public boolean exists(String path, boolean watch) throws KeeperException, InterruptedException {
451 | waitForConnected();
452 | Stat stat = zk.exists(path, watch);
453 | return (stat != null);
454 | }
455 |
456 | /**
457 | * 删除节点
458 | *
459 | * @param path
460 | * @throws KeeperException
461 | * @throws InterruptedException
462 | */
463 | @Override
464 | public void deleteNode(String path) throws KeeperException, InterruptedException {
465 | waitForConnected();
466 | zk.delete(path, -1);
467 | }
468 |
469 |
470 | /**
471 | * 递归删除节点
472 | *
473 | * @param path
474 | */
475 | @Override
476 | public void deleteNodeRecursively(String path) throws KeeperException, InterruptedException {
477 | waitForConnected();
478 | if (StringUtils.equals(PATH_SPLITTER, StringUtils.trim(path))) {
479 | return;
480 | }
481 | List children = getChildren(path);
482 | if (children != null && !children.isEmpty()) {
483 | for (String child : children) {
484 | deleteNodeRecursively(path + PATH_SPLITTER + child);
485 | }
486 | }
487 |
488 | deleteNode(path);
489 | }
490 |
491 | /**
492 | * 为特定路径的节点 添加监听器(同时监听数据变化以及该节点存在性变化)
493 | *
494 | * @param path
495 | * @param handler
496 | */
497 | @Override
498 | public void addNodeDataChangedHandler(String path,
499 | DomiNodeHandler handler) throws KeeperException, InterruptedException {
500 | if (StringUtils.isBlank(path)) {
501 | throw new IllegalArgumentException("Handling path for node is BLANK!");
502 | }
503 | Object previous = nodeChangedHandlerHolder.put(path, handler);
504 | if (previous == null) {
505 | //注册监听
506 | getData(path, true);
507 | exists(path, true);
508 | }
509 | }
510 |
511 | /**
512 | * 为特定路径的节点 添加监听器(监听数子节点数量变化)
513 | *
514 | * @param path
515 | * @param handler
516 | */
517 | @Override
518 | public void addChildrenChangedHandler(String path,
519 | DomiChildrenNodeHandler handler) throws KeeperException, InterruptedException {
520 | if (StringUtils.isBlank(path)) {
521 | throw new IllegalArgumentException("Handling path for children is BLANK!");
522 | }
523 | Object previous = childrenChangedHandlerHolder.put(path, handler);
524 | if (previous == null) {
525 | //注册监听
526 | getChildren(path, true);
527 | }
528 | }
529 |
530 | /**
531 | * 追加子节点监听器(初始化前调用有效)
532 | *
533 | * @param childrenNodeHandlerMap
534 | */
535 | @Override
536 | public void setChildrenChangedHandlerBeforeInit(
537 | Map childrenNodeHandlerMap) {
538 |
539 | childrenChangedHandlerHolder.putAll(childrenNodeHandlerMap);
540 | }
541 |
542 |
543 | /**
544 | * 追加节点监听器(初始化前调用有效)
545 | *
546 | * @param nodeHandlerMap
547 | */
548 | @Override
549 | public void setNodeDataChangedHandlerBeforeInit(Map nodeHandlerMap) {
550 | nodeChangedHandlerHolder.putAll(nodeHandlerMap);
551 | }
552 |
553 | /**
554 | * 获取节点数据
555 | *
556 | * @param path
557 | * @return
558 | */
559 | @Override
560 | public String getData(String path) throws KeeperException, InterruptedException {
561 | waitForConnected();
562 | return getData(path, false);
563 | }
564 |
565 | /**
566 | * 更新node数据
567 | *
568 | * @param path
569 | * @param value
570 | * @param version
571 | * @return
572 | * @throws org.apache.zookeeper.KeeperException
573 | * @throws InterruptedException
574 | */
575 | @Override
576 | public Stat updateNodeData(String path, String value, int version) throws KeeperException, InterruptedException {
577 | waitForConnected();
578 | try {
579 | return zk.setData(path, value.getBytes(DEFAULT_CHARSET), version);
580 | } catch (UnsupportedEncodingException e) {
581 | //unreachable
582 | return null;
583 | }
584 | }
585 |
586 | /**
587 | * 获取节点数据
588 | *
589 | * @param path
590 | * @param stat
591 | * @return
592 | * @throws InterruptedException
593 | * @throws org.apache.zookeeper.KeeperException
594 | */
595 | @Override
596 | public String getData(String path, Stat stat) throws KeeperException, InterruptedException {
597 | return getData(path, false, stat);
598 | }
599 |
600 | /**
601 | * 获取节点数据
602 | *
603 | * @param path
604 | * @param watch true:监听此节点的数据变化
605 | * @return
606 | */
607 | @Override
608 | public String getData(String path, boolean watch) throws KeeperException, InterruptedException {
609 | return getData(path, watch, null);
610 | }
611 |
612 | /**
613 | * 获取节点数据
614 | *
615 | * @param path
616 | * @param watch true:监听此节点的数据变化
617 | * @param stat
618 | * @return
619 | * @throws org.apache.zookeeper.KeeperException
620 | * @throws InterruptedException
621 | */
622 | @Override
623 | public String getData(String path, boolean watch, Stat stat) throws KeeperException, InterruptedException {
624 | waitForConnected();
625 | byte[] data = new byte[0];
626 | try {
627 | data = zk.getData(path, watch, stat);
628 | } catch (KeeperException e) {
629 | if (e instanceof KeeperException.NoNodeException) {
630 | return null;
631 | }
632 | throw e;
633 | }
634 | try {
635 | return new String(data, DEFAULT_CHARSET);
636 | } catch (UnsupportedEncodingException e) {
637 | //unreachable
638 | return null;
639 | }
640 | }
641 |
642 | /**
643 | * 获取path节点的子节点名称列表
644 | *
645 | * @param path
646 | * @return
647 | */
648 | @Override
649 | public List getChildren(String path) throws KeeperException, InterruptedException {
650 | return getChildren(path, false);
651 | }
652 |
653 | /**
654 | * 获取path节点的子节点名称列表
655 | *
656 | * @param path
657 | * @param watch 监听节点个数变化的事件
658 | * @return
659 | */
660 | @Override
661 | public List getChildren(String path, boolean watch) throws KeeperException, InterruptedException {
662 | waitForConnected();
663 | try {
664 | return zk.getChildren(path, watch);
665 | } catch (KeeperException e) {
666 | if (e instanceof KeeperException.NoNodeException) {
667 | logger.warn("", e);
668 | return null;
669 | }
670 | throw e;
671 | }
672 | }
673 |
674 | /**
675 | * 移除特定路径节点的监听器
676 | *
677 | * @param path
678 | */
679 | @Override
680 | public void removeNodeDataChangedHandler(String path) {
681 | if (path == null) {
682 | return;
683 | }
684 |
685 | nodeChangedHandlerHolder.remove(path);
686 | }
687 |
688 | /**
689 | * 移除特定路径节点的子节点处理器
690 | *
691 | * @param path
692 | */
693 | @Override
694 | public void removeChildrenChangedHandler(String path) {
695 | if (path == null) {
696 | return;
697 | }
698 | childrenChangedHandlerHolder.remove(path);
699 | }
700 |
701 | /**
702 | * 移除特定路径节点的所有处理器
703 | *
704 | * @param path
705 | */
706 | @Override
707 | public void removeHandlerByPath(String path) {
708 | removeChildrenChangedHandler(path);
709 | removeNodeDataChangedHandler(path);
710 | }
711 |
712 | /**
713 | * 获取本机节点对象
714 | *
715 | * @return
716 | */
717 | @Override
718 | public MachineNode getLocalMachine() {
719 | return this.localMachine;
720 | }
721 |
722 |
723 | /**
724 | * 从ZK端获取本机节点对象
725 | *
726 | * @return
727 | */
728 | @Override
729 | public MachineNode getLocalMachineFromZk() {
730 |
731 | MachineNode zkNode = null;
732 | try {
733 | Stat stat = new Stat();
734 | String value = getData(ZkManager.TC_MACHINE_LIST_PATH + PATH_SPLITTER + localMachine.nodeName(), stat);
735 | zkNode = simpleObjectMapper.readValue(value, MachineNode.class);
736 |
737 | } catch (Exception e) {
738 | logger.error("Get local machine value from zk is failed! ", e);
739 | }
740 | return zkNode;
741 | }
742 |
743 | /**
744 | * 判断是否有 path 节点的子节点监听处理器
745 | *
746 | * @param path
747 | */
748 | @Override
749 | public boolean containChildrenChangedHandler(String path) {
750 | return childrenChangedHandlerHolder.containsKey(path);
751 | }
752 |
753 | /**
754 | * 判断是否有 path 节点的监听处理器
755 | *
756 | * @param path
757 | * @return
758 | */
759 | @Override
760 | public boolean containNodeDataChangedHandler(String path) {
761 | return nodeChangedHandlerHolder.containsKey(path);
762 | }
763 |
764 | /**
765 | * 重新注册所有节点监听器
766 | */
767 | @Override
768 | public void refreshAllNodeDataChangedHandlers() {
769 | waitForConnected();
770 | for (String path : nodeChangedHandlerHolder.keySet()) {
771 | try {
772 | exists(path, true);
773 | getData(path, true);
774 | } catch (Exception e) {
775 | logger.error("Watching node changed failed! path[{}]", path, e);
776 | }
777 | }
778 | logger.warn("Refreshing all data-changed handlers completed! {}", nodeChangedHandlerHolder);
779 | }
780 |
781 | /**
782 | * 重新注册所有子节点监听器
783 | */
784 | @Override
785 | public void refreshAllChildrenChangedHandlers() {
786 | waitForConnected();
787 | for (String path : childrenChangedHandlerHolder.keySet()) {
788 | try {
789 | getChildren(path, true);
790 | } catch (Exception e) {
791 | logger.error("Watching node children changed failed! path[{}]", path, e);
792 | }
793 | }
794 | logger.warn("Refreshing all children-changed handlers completed! {}", childrenChangedHandlerHolder);
795 | }
796 |
797 | public DomiNodeHandler getLocalMachineHandler() {
798 | return localMachineHandler;
799 | }
800 |
801 | public void setLocalMachineHandler(DomiNodeHandler localMachineHandler) {
802 | this.localMachineHandler = localMachineHandler;
803 | }
804 |
805 | public int getEventConsumerNum() {
806 | return eventConsumerNum;
807 | }
808 |
809 | public void setEventConsumerNum(int eventConsumerNum) {
810 | this.eventConsumerNum = eventConsumerNum;
811 | }
812 |
813 |
814 | /**
815 | * 下线本机节点
816 | */
817 | @Override
818 | public void offlineLocalMachineNode() throws KeeperException, InterruptedException {
819 | this.online.set(false);
820 | //仅根据本机节点是否在线上进行判断
821 | if (this.exists(nodePath)) {
822 | this.deleteNode(nodePath);
823 | }
824 | }
825 |
826 | /**
827 | * 上线本机节点
828 | */
829 | @Override
830 | public void onlineLocalMachineNode() throws KeeperException, InterruptedException, IOException {
831 | if (!this.exists(nodePath)) {
832 | this.createEphemeralNode(nodePath, simpleObjectMapper.writeValueAsString(localMachine));
833 | }
834 | this.online.set(true);
835 | }
836 |
837 | /**
838 | * 判断本机节点是否已在zk上注册
839 | *
840 | * @return
841 | */
842 | @Override
843 | public boolean isLocalMachineOnline() {
844 | return this.online.get();
845 | }
846 |
847 | /**
848 | * 事件处理器
849 | */
850 | class EventConsumer implements Runnable {
851 | private volatile boolean shutdown = false;
852 |
853 | @Override
854 | public void run() {
855 | String dataPath = null;//节点路径
856 | while (!shutdown) {
857 | WatchedEvent event = null;
858 | try {
859 | event = zkEventQueue.poll(2L, TimeUnit.SECONDS);
860 | } catch (InterruptedException e) {
861 | //do nothing
862 | }
863 | if (event == null) {
864 | continue;
865 | }
866 | String value = null;
867 | DomiNodeHandler handler = null;
868 | List childrenNameList = null;
869 | dataPath = event.getPath();
870 | if (StringUtils.isBlank(dataPath)) {
871 | continue;
872 | }
873 | try {
874 | switch (event.getType()) {
875 | case NodeDataChanged:
876 |
877 | handler = nodeChangedHandlerHolder.get(dataPath);
878 | if (handler != null) {
879 | value = DomiZkManager.this.getData(dataPath, true);
880 | handler.handleDataChanged(dataPath, value, DomiZkManager.this);
881 | }
882 | break;
883 | case NodeCreated:
884 | handler = nodeChangedHandlerHolder.get(dataPath);
885 | if (handler != null) {
886 | DomiZkManager.this.exists(dataPath, true);
887 | value = DomiZkManager.this.getData(dataPath, false);
888 | handler.handleNodeCreated(dataPath, value, DomiZkManager.this);
889 | }
890 | break;
891 | case NodeDeleted:
892 | handler = nodeChangedHandlerHolder.get(dataPath);
893 | if (handler != null) {
894 | DomiZkManager.this.exists(dataPath, true);
895 | handler.handleNodeDeleted(dataPath, DomiZkManager.this);
896 | }
897 | break;
898 | case NodeChildrenChanged:
899 | DomiChildrenNodeHandler childrenNodeHandler = childrenChangedHandlerHolder.get(
900 | dataPath);
901 | if (childrenNodeHandler != null) {
902 | childrenNameList = DomiZkManager.this.getChildren(dataPath, true);
903 | childrenNodeHandler
904 | .handleChildrenChanged(dataPath, childrenNameList, DomiZkManager.this);
905 | }
906 | break;
907 | default:
908 | break;
909 | }
910 | } catch (Exception e) {
911 | logger.error("执行处理器失败。ZK事件:", event.toString(), e);
912 | }
913 |
914 | }
915 | }
916 | }
917 |
918 | /**
919 | * 获取 本机非127.0.0.1 ipv4地址
920 | *
921 | * @return
922 | */
923 | private String getLocalIpAddress() {
924 | try {
925 | Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
926 | NetworkInterface element = null;
927 | InetAddress addr = null;
928 | while (allNetInterfaces.hasMoreElements()) {
929 | element = allNetInterfaces.nextElement();
930 | Enumeration addrs = element.getInetAddresses();
931 |
932 | while (addrs.hasMoreElements()) {
933 | addr = addrs.nextElement();
934 | if (addr == null) {
935 | continue;
936 | }
937 | if (addr instanceof Inet4Address && !(StringUtils.equals("127.0.0.1", addr.getHostAddress()) || StringUtils.equals("0.0.0.0", addr.getHostAddress()))) {
938 | return addr.getHostAddress();
939 | }
940 | }
941 | }
942 | } catch (SocketException e) {
943 | logger.error("Getting localhost ip failed.", e);
944 | return "";
945 | }
946 | return "";
947 | }
948 | }
949 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/service/zookeeper/watcher/DomiChildrenNodeHandler.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.service.zookeeper.watcher;
2 |
3 | import com.company.project.core.service.zookeeper.ZkManager;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * 子节点变化处理器
9 | *
10 | * @author liwei
11 | * 16-10-27 下午1:39
12 | */
13 | public interface DomiChildrenNodeHandler {
14 |
15 |
16 | /**
17 | * 节点变化(增加或删除节点)后的处理
18 | *
19 | * @param path
20 | * @param value
21 | */
22 | Object handleChildrenChanged(String path, List value, ZkManager zkManager);
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/service/zookeeper/watcher/DomiNodeHandler.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.service.zookeeper.watcher;
2 |
3 | import com.company.project.core.service.zookeeper.ZkManager;
4 |
5 | /**
6 | * zk数据节点处理器
7 | *
8 | * @author qingren.lw
9 | * 14-9-14 下午9:02
10 | */
11 | public interface DomiNodeHandler {
12 |
13 |
14 | /**
15 | * 增加节点后的处理
16 | *
17 | * @param path
18 | * @param value
19 | * @return
20 | */
21 | Object handleNodeCreated(String path, String value, ZkManager zkManager);
22 |
23 | /**
24 | * 节点数据变化(修改节点数据)后的处理
25 | *
26 | * @param path
27 | * @param value
28 | * @return
29 | */
30 | Object handleDataChanged(String path, String value, ZkManager zkManager);
31 |
32 | /**
33 | * 删除节点后的处理
34 | *
35 | * @param path
36 | * @return
37 | */
38 | Object handleNodeDeleted(String path, ZkManager zkManager);
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/service/zookeeper/watcher/DomiZkEventWatcher.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.service.zookeeper.watcher;
2 |
3 | import com.company.project.core.service.zookeeper.MachineNode;
4 | import com.company.project.core.service.zookeeper.ZkManager;
5 | import org.apache.zookeeper.KeeperException;
6 | import org.apache.zookeeper.WatchedEvent;
7 | import org.apache.zookeeper.Watcher;
8 | import org.codehaus.jackson.map.ObjectMapper;
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 |
12 | import java.io.IOException;
13 |
14 | /**
15 | * zk事件监视器
16 | *
17 | * @author qingren.lw
18 | * 14-9-12 下午5:29
19 | */
20 | public class DomiZkEventWatcher implements Watcher {
21 | private static final Logger logger = LoggerFactory.getLogger(DomiZkEventWatcher.class);
22 | private ZkManager manager;
23 | private static boolean rootCreated = false;
24 |
25 |
26 | /**
27 | * 本机节点
28 | */
29 | private MachineNode localMachine;
30 |
31 | public DomiZkEventWatcher(ZkManager manager, MachineNode localMachine) {
32 | this.localMachine = localMachine;
33 | this.manager = manager;
34 |
35 | }
36 |
37 | /**
38 | * zk 事件处理器
39 | *
40 | * @param event
41 | */
42 | @Override
43 | public void process(WatchedEvent event) {
44 | logger.info("Received event:{}", event);
45 |
46 | if (event.getState() == Event.KeeperState.Expired) {
47 | //若ZK出现超时,则需重新初始化ZK连接
48 | try {
49 | logger.warn("Zookeeper session expired.Reconnecting...");
50 | processSessionExpired();
51 |
52 | } catch (IOException e) {
53 | logger.error("Re-connect zookeeper failed.", e);
54 | throw new RuntimeException(e);//此处抛个异常,为阻止后续流程
55 | }
56 | }
57 | if (event.getType() == Event.EventType.None) {
58 | if (event.getState() == Event.KeeperState.SyncConnected) {
59 | processSyncConnected();
60 | logger.warn("Zookeeper connected.");
61 | //连接成功后,直接发起一个任务节点变化事件,以防止系统 down掉后,任务变成僵尸节点
62 | resumeEvent();
63 | }
64 | return;
65 | }
66 |
67 | manager.addEvent(event);
68 |
69 | }
70 |
71 |
72 | /**
73 | * 恢复节点监听事件
74 | */
75 | private void resumeEvent() {
76 | //此方法暂预留
77 |
78 |
79 | ////构造模型任务子节点变化事件
80 | //WatchedEvent event = new WatchedEvent(Event.EventType.NodeChildrenChanged, Event.KeeperState.SyncConnected,
81 | // ZkManager.EBAY_MODEL_TASKS_ROOT_PATH);
82 | //manager.addEvent(event);
83 | ////构造批处理任务子节点变化
84 | //event = new WatchedEvent(Event.EventType.NodeChildrenChanged, Event.KeeperState.SyncConnected,
85 | // ZkManager.EBAY_BATCH_TASKS_ROOT_PATH);
86 | //manager.addEvent(event);
87 |
88 |
89 | }
90 |
91 | /**
92 | * 会话超时处理:重新初始化zkManager
93 | */
94 | private void processSessionExpired() throws IOException {
95 | manager.init();
96 | }
97 |
98 | /**
99 | * 建立连接后的处理
100 | */
101 | private void processSyncConnected() {
102 | manager.countDownWaitForConnectedLatch();
103 | ObjectMapper om = new ObjectMapper();
104 | try {
105 | createRootNode();
106 | if (localMachine != null) {
107 | //若服务处于上线状态,则重新发布本机节点
108 |
109 | if(manager.isLocalMachineOnline()){
110 | manager.onlineLocalMachineNode();
111 | }
112 |
113 | //String machineNodeValue = om.writeValueAsString(localMachine);
114 | ////发布非持久结点(自身)
115 | //String selfNodePath = ZkManager.TC_MACHINE_LIST_PATH + ZkManager.PATH_SPLITTER + localMachine.nodeName();
116 | //if (!manager.exists(selfNodePath)) {
117 | // manager.createEphemeralNode(selfNodePath, machineNodeValue);
118 | //}
119 | }
120 | //刷新所有监听器
121 | manager.refreshAllChildrenChangedHandlers();
122 | manager.refreshAllNodeDataChangedHandlers();
123 |
124 | } catch (Exception e) {
125 | logger.error("Initializing node failed.", e);
126 | }
127 |
128 | }
129 |
130 |
131 | /**
132 | * 创建根节点
133 | *
134 | * @throws KeeperException
135 | * @throws InterruptedException
136 | */
137 | private void createRootNode() throws KeeperException, InterruptedException {
138 | if (rootCreated) {
139 | return;
140 | }
141 |
142 | synchronized (this.getClass()) {
143 | if (rootCreated) {
144 | return;
145 | }
146 |
147 | //发布各根结点
148 | if (!manager.exists(ZkManager.TC_ROOT_PATH)) {
149 | manager.createNode(ZkManager.TC_ROOT_PATH, "");
150 | }
151 | if (!manager.exists(ZkManager.TC_MACHINE_LIST_PATH)) {
152 | manager.createNode(ZkManager.TC_MACHINE_LIST_PATH, "");
153 | }
154 | rootCreated = true;
155 | }
156 | }
157 |
158 |
159 | public MachineNode getLocalMachine() {
160 | return localMachine;
161 | }
162 |
163 | public void setLocalMachine(MachineNode localMachine) {
164 | this.localMachine = localMachine;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/utils/ProjectByteUtils.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.utils;
2 |
3 | import java.io.UnsupportedEncodingException;
4 |
5 | /**
6 | * 字节数组相关工具类
7 | *
8 | */
9 | public class ProjectByteUtils {
10 | /**
11 | * 16进制单字节最大值
12 | */
13 | public static final int HEX_UNIT = 0xff;
14 | /**
15 | * 数字单字节所占的位数
16 | */
17 | private static final int NUM_BIT_UNIT = 8;
18 |
19 | private static final String DEFAULT_CHARSET = "UTF-8";
20 |
21 | /**
22 | * Hash 乘法因子
23 | */
24 | private static final int HASH_ELEMENT = 16777619;
25 |
26 | /**
27 | * int 数据转字节数组
28 | *
29 | * @param value
30 | *
31 | * @return
32 | */
33 | public static byte[] getBytes(int value) {
34 | int byteLength = 4;// int 4 字节
35 | byte[] data = new byte[byteLength];
36 | int index = 0;
37 | //处理 type
38 | for (int i = 0; i < byteLength; i++) {
39 | data[index++] = (byte) ((value >> (i * NUM_BIT_UNIT)) & HEX_UNIT);
40 | }
41 | return data;
42 | }
43 |
44 | // /**
45 | // * Integer 数据转字节数组
46 | // *
47 | // * @param value 不可为null
48 | // *
49 | // * @return
50 | // */
51 | // public static byte[] getBytesFromInt(Integer value) {
52 | // if (value == null) {
53 | // throw new IllegalArgumentException("Param value is null");
54 | // }
55 | // return getBytesFromInt(value.intValue());
56 | // }
57 |
58 | /**
59 | * long 数据转字节数组
60 | *
61 | * @param value
62 | *
63 | * @return
64 | */
65 | public static byte[] getBytes(long value) {
66 | int byteLength = 8;// long 8 字节
67 | byte[] data = new byte[byteLength];
68 | int index = 0;
69 | //处理 type
70 | for (int i = 0; i < byteLength; i++) {
71 | data[index++] = (byte) ((value >> (i * NUM_BIT_UNIT)) & HEX_UNIT);
72 | }
73 | return data;
74 | }
75 |
76 | /**
77 | * double 数据转字节数组
78 | *
79 | * @param value
80 | *
81 | * @return
82 | */
83 | public static byte[] getBytes(double value) {
84 | long lonValue = Double.doubleToLongBits(value);
85 | return getBytes(lonValue);
86 | }
87 |
88 | /**
89 | * float 数据转字节数组
90 | *
91 | * @param value
92 | *
93 | * @return
94 | */
95 | public static byte[] getBytes(float value) {
96 | int intValue = Float.floatToIntBits(value);
97 | return getBytes(intValue);
98 | }
99 |
100 | /**
101 | * String 数据转字节数组
102 | *
103 | * @param value
104 | * @param charset
105 | *
106 | * @return
107 | */
108 | public static byte[] getBytes(String value, String charset) throws UnsupportedEncodingException {
109 | if (value == null) {
110 | throw new IllegalArgumentException("Param value is null");
111 | }
112 | return value.getBytes(charset);
113 | }
114 |
115 | /**
116 | * String 数据转字节数组(使用UTF-8字符编码集)
117 | *
118 | * @param value
119 | *
120 | * @return
121 | */
122 | public static byte[] getBytes(String value) throws UnsupportedEncodingException {
123 | return getBytes(value, DEFAULT_CHARSET);
124 | }
125 |
126 |
127 | /**
128 | * 计算hash值
129 | *
130 | * @param data
131 | *
132 | * @return
133 | */
134 | public static int computeHash(byte[] data) {
135 | //基准值 随意质数
136 | int hash = (int) 2166136261L;
137 |
138 |
139 | for (byte b : data) {
140 | hash = (hash ^ b) * HASH_ELEMENT;
141 | }
142 | hash += hash << 13;
143 | hash ^= hash >> 7;
144 | hash += hash << 3;
145 | hash ^= hash >> 17;
146 | hash += hash << 5;
147 |
148 | return hash;
149 | }
150 |
151 |
152 | /**
153 | * 计算hash值
154 | *
155 | * @param sourceDataArrays
156 | *
157 | * @return
158 | */
159 | public static int computeHash(byte[]... sourceDataArrays) {
160 | int totalLength = 0;
161 | for (byte[] source : sourceDataArrays) {
162 | totalLength += source.length;
163 | }
164 | if (totalLength == 0) {
165 | return 0;
166 | }
167 |
168 | byte[] data = new byte[totalLength];
169 |
170 | int index = 0;
171 | for (byte[] source : sourceDataArrays) {
172 | for (byte b : source) {
173 | data[index++] = b;
174 | }
175 |
176 | }
177 | return computeHash(data);
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/utils/ProjectDateUtils.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.utils;
2 |
3 | import org.apache.commons.lang.StringUtils;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.text.ParseException;
8 | import java.text.SimpleDateFormat;
9 | import java.util.Calendar;
10 | import java.util.Date;
11 |
12 | /**
13 | * 日期相关工具类
14 | */
15 | public class ProjectDateUtils {
16 | private static final Logger logger = LoggerFactory.getLogger(ProjectDateUtils.class);
17 |
18 | public static final String DF_YYYYMMDD = "yyyyMMdd";
19 | public static final String DF_YYYY_MM_DD = "yyyy-MM-dd";
20 | public static final String DF_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
21 | public static final String DF_YYYY_MM_DDHHMMSS = "yyyy-MM-dd HH:mm:ss";
22 | public static final String DF_HHMMSS = "HHmmss";
23 |
24 |
25 | /**
26 | * 将日期转换成字符串
27 | *
28 | * @param date
29 | * @param format
30 | *
31 | * @return
32 | */
33 | public static String format(Date date, String format) {
34 | if (date == null) {
35 | throw new IllegalArgumentException("Param date is null!");
36 | }
37 | if (StringUtils.isBlank(format)) {
38 | throw new IllegalArgumentException("Param format is blank!");
39 | }
40 | SimpleDateFormat sdf = new SimpleDateFormat(format);
41 | return sdf.format(date);
42 | }
43 |
44 | /**
45 | * 将日期转换成yyyyMMddHHmmss字符串
46 | *
47 | * @param date
48 | *
49 | * @return
50 | */
51 | public static String format14(Date date) {
52 | return format(date, DF_YYYYMMDDHHMMSS);
53 | }
54 |
55 | public static String format8(Date date) {
56 | return format(date, DF_YYYYMMDD);
57 | }
58 |
59 | public static String format10(Date date) {
60 | return format(date, DF_YYYY_MM_DD);
61 | }
62 |
63 | public static Date parse8(String dateStr) throws ParseException {
64 | return parse(dateStr, DF_YYYYMMDD);
65 | }
66 |
67 | public static Date parse10(String dateStr) throws ParseException {
68 | return parse(dateStr, DF_YYYY_MM_DD);
69 | }
70 |
71 | /**
72 | * 返回当前日期 yyyyMMdd格式 字符串
73 | *
74 | * @return
75 | */
76 | public static String getNow8() {
77 | return format8(new Date());
78 | }
79 |
80 | /**
81 | * 返回当前日期 yyyyMMdd格式 字符串
82 | *
83 | * @return
84 | */
85 | public static String getNow10() {
86 | return format10(new Date());
87 | }
88 |
89 | /**
90 | * 获取当天0点 date对象
91 | * @return
92 | */
93 | public static Date getToday(){
94 | Date today=null;
95 | try {
96 | today =parse(getNow8(),DF_YYYYMMDD);
97 | } catch (ParseException e) {
98 | //unreachable
99 | logger.error("Parsing / Getting today's date failed.",e);
100 | today = new Date();
101 | }
102 | return today;
103 | }
104 |
105 | /**
106 | * 获取当年1月1日0点 date对象
107 | * @return
108 | */
109 | public static Date getNowYear(){
110 | Date year=null;
111 | try {
112 | String format = "yyyy";
113 | year =parse(format(new Date(),format),format);
114 | } catch (ParseException e) {
115 | //unreachable
116 | logger.error("Parsing / Getting year's date failed.",e);
117 | year = new Date();
118 | }
119 | return year;
120 | }
121 |
122 | /**
123 | * 获取当月1号0点 date对象
124 | * @return
125 | */
126 | public static Date getNowMonth(){
127 | Date month=null;
128 | try {
129 | String format = "yyyy-MM";
130 | month =parse(format(new Date(),format),format);
131 | } catch (ParseException e) {
132 | //unreachable
133 | logger.error("Parsing / Getting month's date failed.",e);
134 | month = new Date();
135 | }
136 | return month;
137 | }
138 |
139 | public static int getMonthSpace(Date date1, Date date2) {
140 | Calendar c1 = Calendar.getInstance();
141 | Calendar c2 = Calendar.getInstance();
142 | c1.setTime(date1);
143 | c2.setTime(date2);
144 | int result = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
145 | return result == 0 ? 1 : Math.abs(result);
146 | }
147 |
148 | public static int getYearSpace4Now(String date) throws ParseException {
149 | Calendar c1 = Calendar.getInstance();
150 | Calendar c2 = Calendar.getInstance();
151 | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
152 | c1.setTime(new Date());
153 | c2.setTime(sdf.parse(date));
154 | int result = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
155 | return result == 0 ? 1 : Math.abs(result);
156 | }
157 |
158 | public static Date parse(String dateStr, String format) throws ParseException {
159 | SimpleDateFormat sdf = new SimpleDateFormat(format);
160 | return sdf.parse(dateStr);
161 | }
162 |
163 | /**
164 | * @return 获取当前月第一天:
165 | */
166 | public static Date getFirstDateOfCurrentMonth() {
167 | Calendar c = Calendar.getInstance();
168 | c.add(Calendar.MONTH, 0);
169 | c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
170 | try {
171 | return parse(format8(c.getTime()),DF_YYYYMMDD);
172 | } catch (ParseException e) {
173 | logger.error("Parsing first day of current month is faile.",e);
174 | return null;
175 | }
176 |
177 | }
178 |
179 | /**
180 | * @return 获取下月第一天:
181 | */
182 | public static Date getFirstDateOfNextMonth() {
183 | Calendar c = Calendar.getInstance();
184 | c.add(Calendar.MONTH, 1);
185 | c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
186 | try {
187 | return parse(format8(c.getTime()),DF_YYYYMMDD);
188 | } catch (ParseException e) {
189 | logger.error("Parsing first day of current month is faile.",e);
190 | return null;
191 | }
192 |
193 | }
194 |
195 | /**
196 | * @return 获取当前月最后一天
197 | */
198 | public static Date getListDateOfCurrentMonth() {
199 | Calendar c = Calendar.getInstance();
200 | c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
201 | try {
202 | return parse(format8(c.getTime()),DF_YYYYMMDD);
203 | } catch (ParseException e) {
204 | logger.error("Parsing first day of current month is faile.",e);
205 | return null;
206 | }
207 | }
208 |
209 | /**
210 | * @return 当月的总天数
211 | */
212 | public static int getCurrentMonthDay() {
213 | Calendar a = Calendar.getInstance();
214 | a.set(Calendar.DATE, 1);
215 | a.roll(Calendar.DATE, -1);
216 | int maxDate = a.get(Calendar.DATE);
217 | return maxDate;
218 | }
219 |
220 | /**
221 | * 计算时间间隔
222 | *
223 | * @param fDate 上次时间
224 | * @param oDate 本次时间
225 | * @return 精确到天
226 | */
227 | public static int getIntervalDays(Date fDate, Date oDate) {
228 | if (fDate == null || oDate == null) {
229 | return -1;
230 | }
231 | try {
232 | fDate = parse(format8(fDate),DF_YYYYMMDD);
233 | oDate = parse(format8(oDate), DF_YYYYMMDD);
234 | } catch (ParseException e) {
235 | logger.error("Parsing interval days is faile.", e);
236 | }
237 | long nd = 1000*24*60*60;//一天的毫秒数
238 | //获得两个时间的毫秒时间差异
239 | long diff = oDate.getTime() - fDate.getTime();
240 | Long day = diff/nd;//计算差多少天
241 | return day.intValue();
242 |
243 | }
244 |
245 | /**
246 | *
247 | * @param date
248 | * @return
249 | * @throws ParseException
250 | */
251 | public static Date getDate8(Date date){
252 | try {
253 | return parse8(format8(date));
254 | } catch (ParseException e) {
255 | //unreachable
256 | }
257 | return null;
258 | }
259 |
260 | /**
261 | * 时间加days天
262 | * @param date
263 | * @param days
264 | * @return
265 | */
266 | public static Date addDate(Date date, int days){
267 | Calendar calendar = Calendar.getInstance();
268 | calendar.setTime(date);
269 | calendar.add(Calendar.DATE, days);
270 | return calendar.getTime();
271 | }
272 |
273 | /**
274 | * 日期加法运算
275 | *
276 | * @param sourceDate
277 | * @param months 增加的月数,可为负数
278 | * @return
279 | */
280 | public static Date addMonths(Date sourceDate, int months) {
281 | Calendar calendar = Calendar.getInstance();
282 | calendar.setTime(sourceDate);
283 | calendar.add(Calendar.MONTH, months);
284 | return calendar.getTime();
285 | }
286 | }
287 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/utils/ProjectMD5Utils.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.utils;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | import java.security.MessageDigest;
6 | import java.security.NoSuchAlgorithmException;
7 |
8 | /**
9 | *md5工具类
10 | */
11 | @Component
12 | public class ProjectMD5Utils {
13 | private static final char[] hexDigits = {'0', '1', '2', '3', '4',
14 | '5', '6', '7', '8', '9',
15 | 'a', 'b', 'c', 'd', 'e', 'f'};
16 |
17 | public final static String getMD5String(String s) {
18 |
19 | byte[] btInput = s.getBytes();
20 | //获得MD5摘要算法的 MessageDigest 对象
21 | MessageDigest mdInst = null;
22 | try {
23 | mdInst = MessageDigest.getInstance("MD5");
24 | } catch (NoSuchAlgorithmException e) {
25 | //unreachable
26 | }
27 | //使用指定的字节更新摘要
28 | mdInst.update(btInput);
29 | //获得密文
30 | byte[] md = mdInst.digest();
31 | //把密文转换成十六进制的字符串形式
32 | int j = md.length;
33 | char str[] = new char[j * 2];
34 | int k = 0;
35 | for (int i = 0; i < j; i++) {
36 | byte byte0 = md[i];
37 | str[k++] = hexDigits[byte0 >>> 4 & 0xf];
38 | str[k++] = hexDigits[byte0 & 0xf];
39 | }
40 | return new String(str);
41 |
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/utils/ProjectPlatTraceUtils.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.utils;
2 |
3 | import org.apache.commons.lang.StringUtils;
4 |
5 | import java.text.SimpleDateFormat;
6 | import java.util.Date;
7 |
8 | /**
9 | * 平台流水生成器(单机)
10 | *
11 | */
12 | public class ProjectPlatTraceUtils {
13 | /**
14 | * 默认完整时间格式 yyyyMMddHHmmssS 17位
15 | */
16 | public static String DEFAULT_FULL_DATE_FMT = "yyyyMMddHHmmssS";
17 |
18 | private static final int LIMIT = 1000000;
19 | private static final int START = 1;
20 | private static int seqHouse = START;
21 |
22 | /**
23 | * 生成平台流水
24 | *
25 | * @param dateFormat 日期格式
26 | * @param busiFlag 业务标识
27 | * @param totalLength 流水字符串长度,若该长度小于dateFormat.length()+busiFlag.lenght(),则从左到右依次截取
28 | *
29 | * @return
30 | */
31 | public static String genTrace(String dateFormat, String busiFlag, int totalLength) {
32 | if (StringUtils.isBlank(dateFormat)) {
33 | throw new IllegalArgumentException("Param dateFormat should not be null.");
34 | }
35 | if (totalLength < 1) {
36 | throw new IllegalArgumentException("Param total length should be greater than 0.");
37 | }
38 | if (StringUtils.isBlank(busiFlag)) {
39 | busiFlag = "";
40 | }
41 |
42 | Date date = new Date();
43 | SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
44 |
45 | StringBuilder builder = new StringBuilder(sdf.format(date)).append(busiFlag);
46 | if (totalLength == builder.length()) {
47 | return builder.toString();
48 | }
49 |
50 | if (totalLength < builder.length()) {
51 | return builder.substring(0, totalLength);
52 | }
53 |
54 | //拼接流水
55 | String currentSeq = "";
56 | synchronized (ProjectPlatTraceUtils.class) {
57 | if (seqHouse >= LIMIT) {
58 | seqHouse = START;
59 | }
60 | currentSeq = "" + seqHouse;
61 | seqHouse++;
62 | }
63 |
64 | return builder.append(formatNum(currentSeq, totalLength - builder.length())).toString();
65 | }
66 |
67 |
68 | /**
69 | * 生成平台流水
70 | *
71 | * @param dateFormat 日期格式
72 | * @param busiFlag 业务标识
73 | * @param seqSuffix 末尾流水号
74 | * @param totalLength 流水字符串长度,若该长度小于dateFormat.length()+busiFlag.lenght(),则从左到右依次截取
75 | * @param totalLength
76 | * @return
77 | */
78 | public static String genTrace(String dateFormat, String busiFlag, String seqSuffix, int totalLength) {
79 | if (StringUtils.isBlank(dateFormat)) {
80 | throw new IllegalArgumentException("Param dateFormat should not be null.");
81 | }
82 | if (totalLength < 1) {
83 | throw new IllegalArgumentException("Param total length should be greater than 0.");
84 | }
85 | if (StringUtils.isBlank(busiFlag)) {
86 | busiFlag = "";
87 | }
88 |
89 | Date date = new Date();
90 | SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
91 |
92 | StringBuilder builder = new StringBuilder(busiFlag).append(sdf.format(date));
93 | if (totalLength == builder.length()) {
94 | return builder.toString();
95 | }
96 |
97 | if (totalLength < builder.length()) {
98 | return builder.substring(0, totalLength);
99 | }
100 |
101 |
102 | return builder.append(formatNum(seqSuffix, totalLength - builder.length())).toString();
103 | }
104 |
105 |
106 | /**
107 | * 生成平台流水
108 | *
109 | * @param dateFormat 日期格式
110 | * @param totalLength 流水字符串长度,若该长度小于dateFormat.length()+busiFlag.lenght(),则从左到右依次截取
111 | *
112 | * @return
113 | */
114 | public static String genTrace(String dateFormat, int totalLength) {
115 | return genTrace(dateFormat, "", totalLength);
116 | }
117 |
118 | /**
119 | * 生成平台流水30位 含busiFlag长度
120 | *
121 | * @param busiFlag 业务标识
122 | *
123 | * @return
124 | */
125 | public static String genTrace30(String busiFlag) {
126 | return genTrace(DEFAULT_FULL_DATE_FMT, busiFlag, 30);
127 | }
128 |
129 | /**
130 | * 生成平台流水27位 含busiFlag长度
131 | *
132 | * @param busiFlag 业务标识
133 | *
134 | * @return
135 | */
136 | public static String genTrace27(String busiFlag) {
137 | return genTrace(DEFAULT_FULL_DATE_FMT, busiFlag, 27);
138 | }
139 |
140 |
141 | /**
142 | * 格式化数字到指定长度。若length>numStr.lenght(), 则前补0;否则从右到左截取
143 | *
144 | * @param numStr
145 | * @param length
146 | *
147 | * @return
148 | */
149 | public static String formatNum(String numStr, int length) {
150 | if (numStr.length() == length) {
151 | return numStr;
152 | }
153 | if (numStr.length() > length) {
154 | return numStr.substring(numStr.length() - length, numStr.length());
155 | }
156 | int delta = length - numStr.length();
157 |
158 | StringBuilder builder = new StringBuilder();
159 | for (int i = 0; i < delta; i++) {
160 | builder.append(0);
161 | }
162 |
163 | return builder.append(numStr).toString();
164 | }
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/core/utils/ProjectVerifyUtils.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.utils;
2 |
3 | import com.company.project.core.result.ResultCode;
4 | import com.company.project.core.exception.ServiceException;
5 | import org.apache.commons.lang.ArrayUtils;
6 | import org.apache.commons.lang.StringUtils;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.text.ParseException;
11 | import java.text.SimpleDateFormat;
12 | import java.util.Date;
13 |
14 | /**
15 | * 参数格式校验工具类
16 | * Created by Jimersy Lee
17 | */
18 | public class ProjectVerifyUtils {
19 | private static final Logger logger = LoggerFactory.getLogger(ProjectVerifyUtils.class);
20 |
21 | /**
22 | * 正则表达式 数字+英文字母
23 | */
24 | public static final String REGX_ALPHABETA_NUM = "^[a-zA-Z0-9]$";
25 |
26 | /**
27 | * 中国大陆手机号
28 | */
29 | public static final String REGX_CN_MOBILE = "^(0086|[+]86)?1\\d{10}";
30 |
31 | /**
32 | * 邮编
33 | */
34 | public static final String REGEX_POSTCODE = "^[0-9]{6}$";
35 |
36 | /**
37 | * 用于校验 0, 1
38 | */
39 | public static final String PEGEX_YES_OR_NO = "^[0-1]{1}$";
40 |
41 |
42 | public static boolean verifyPhoneNo(String phoneNo, boolean throwException, String fieldName) throws ServiceException {
43 | notNull(phoneNo, fieldName, true);
44 | if (phoneNo.matches("^1[0-9]{10}")) {
45 | return true;
46 | }
47 | if (throwException) {
48 | throw new ServiceException(ResultCode.INVALID_PARAM, fieldName);
49 | }
50 | return false;
51 | }
52 |
53 |
54 | public static boolean notBlank(String value, boolean throwException) throws ServiceException {
55 | return notBlank(value, "", throwException);
56 | }
57 |
58 | /**
59 | * 非空白判断
60 | *
61 | * @param value
62 | * @param paramName
63 | * @param throwException
64 | * @return
65 | * @throws ServiceException
66 | */
67 | public static boolean notBlank(String value, String paramName, boolean throwException) throws ServiceException {
68 | boolean result = StringUtils.isNotBlank(value);
69 | if (result) {
70 | return true;
71 | }
72 | if (throwException) {
73 | throw new ServiceException(ResultCode.INVALID_PARAM, paramName);
74 | } else {
75 | return false;
76 | }
77 | }
78 |
79 | public static boolean greaterThan(int value, int compareValue, String paramName, boolean throwException)
80 | throws ServiceException {
81 | boolean result = value > compareValue;
82 | if (result) {
83 | return true;
84 | }
85 | if (throwException) {
86 | throw new ServiceException(ResultCode.INVALID_PARAM, paramName + "=" + value);
87 | }
88 | return false;
89 | }
90 |
91 | public static boolean greaterThan(long value, long compareValue, String paramName, boolean throwException)
92 | throws ServiceException {
93 | boolean result = value > compareValue;
94 | if (result) {
95 | return true;
96 | }
97 | if (throwException) {
98 | throw new ServiceException(ResultCode.INVALID_PARAM, paramName + "=" + value);
99 | }
100 | return false;
101 | }
102 |
103 | public static boolean greaterThan(double value, double compareValue, String paramName, boolean throwException)
104 | throws ServiceException {
105 | boolean result = value > compareValue;
106 | if (result) {
107 | return true;
108 | }
109 | if (throwException) {
110 | throw new ServiceException(ResultCode.INVALID_PARAM, paramName + "=" + value);
111 | }
112 | return false;
113 | }
114 |
115 | public static boolean maxStringLength(String value, int maxLength, String paramName, boolean allowBlank,
116 | boolean throwException) throws ServiceException {
117 | //非空校验
118 | boolean isNotBlank = notBlank(value, false);
119 | if (!isNotBlank) {
120 | if (allowBlank) {
121 | return true;
122 | }
123 | if (throwException) {
124 | throw new ServiceException(paramName + "=" + value);
125 | }
126 | return false;
127 | }
128 | //字符串长度校验
129 | if (value.length() > maxLength) {
130 | if (throwException) {
131 | throw new ServiceException(paramName + "=" + value);
132 | }
133 | return false;
134 | }
135 | return true;
136 | }
137 |
138 | /**
139 | * 检查数据最小字符串长度
140 | *
141 | * @param value
142 | * @param minLength
143 | * @param paramName
144 | * @param allowBlank
145 | * @param throwException
146 | * @return
147 | * @throws ServiceException
148 | */
149 | public static boolean minStringLength(String value, int minLength, String paramName, boolean allowBlank,
150 | boolean throwException) throws ServiceException {
151 | //非空校验
152 | if (!notBlank(value, false)) {
153 | if (allowBlank) {
154 | return true;
155 | }
156 | if (throwException) {
157 | throw new ServiceException(paramName + "=" + value);
158 | }
159 | return false;
160 | }
161 |
162 | //字符串长度校验
163 | if (value.length() < minLength) {
164 | if (throwException) {
165 | throw new ServiceException(paramName + "=" + value);
166 | }
167 | return false;
168 | }
169 | return true;
170 | }
171 |
172 |
173 | public static boolean contains(int value, int[] container, String paramName, boolean throwException)
174 | throws ServiceException {
175 | if (container == null) {
176 | logger.error("Param container is null");
177 | throw new ServiceException("container");
178 | }
179 |
180 | boolean result = ArrayUtils.contains(container, value);
181 | if (result) {
182 | return true;
183 | }
184 | if (throwException) {
185 | throw new ServiceException(paramName + "=" + value);
186 | }
187 | return false;
188 | }
189 |
190 | /**
191 | * 非空判断
192 | *
193 | * @param obj
194 | * @param throwException
195 | * @return
196 | * @throws ServiceException
197 | */
198 | public static boolean notNull(Object obj, String paramName, boolean throwException) throws ServiceException {
199 | if (obj == null) {
200 | if (throwException) {
201 | throw new ServiceException(paramName + " is null");
202 | }
203 | return false;
204 | }
205 | return true;
206 | }
207 |
208 |
209 | /**
210 | * 非空白判断
211 | *
212 | * @param field
213 | * @param throwException
214 | * @param fieldName
215 | * @return
216 | * @throws ServiceException
217 | */
218 | public static boolean notBlank(String field, boolean throwException, String fieldName) throws ServiceException {
219 | if (StringUtils.isNotBlank(field)) {
220 | return true;
221 | }
222 | if (throwException) {
223 | throw new ServiceException(ResultCode.INVALID_PARAM, fieldName + " 不能为空白");
224 | }
225 | return false;
226 | }
227 |
228 | /**
229 | * 根据正则表达式判断参数合法性
230 | *
231 | * @param field
232 | * @param regex
233 | * @param throwException
234 | * @param fieldName
235 | * @return
236 | * @throws ServiceException
237 | */
238 | public static boolean verifyByRegex(String field, String regex, boolean throwException, String fieldName)
239 | throws ServiceException {
240 | notNull(field, fieldName, true);
241 | if (field.matches(regex)) {
242 | return true;
243 | }
244 | if (throwException) {
245 | // logger.warn(fieldName + " is not match regex[" + regex + "]");
246 | throw new ServiceException(fieldName + "=" + field);
247 | }
248 | return false;
249 | }
250 |
251 | /**
252 | * 日期字符串校验
253 | *
254 | * @param value
255 | * @param format
256 | * @param fieldName
257 | * @param throwException
258 | * @return
259 | * @throws ServiceException
260 | */
261 | public static boolean verifyDate(String value, String format, String fieldName, boolean throwException)
262 | throws ServiceException {
263 | boolean result = notNull(value, fieldName, throwException);
264 | if (!result) {
265 | return result;
266 | }
267 | SimpleDateFormat sdf = new SimpleDateFormat(format);
268 | Date date = null;
269 | try {
270 | date = sdf.parse(value);
271 | } catch (ParseException e) {
272 | if (throwException) {
273 | throw new ServiceException(ResultCode.INVALID_PARAM, fieldName + "=" + value);
274 | } else {
275 | return false;
276 | }
277 | }
278 | String actValue = sdf.format(date);
279 | if (StringUtils.equals(value, actValue)) {
280 | return true;
281 | }
282 | if (throwException) {
283 | // logger.warn(fieldName + " is not match regex[" + regex + "]");
284 | throw new ServiceException(ResultCode.INVALID_PARAM, fieldName + "=" + value);
285 | }
286 | return false;
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/dao/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.company.project.dao;
2 |
3 | import com.company.project.core.mapper.Mapper;
4 | import com.company.project.model.User;
5 | import org.springframework.stereotype.Component;
6 |
7 | @Component
8 | public interface UserMapper extends Mapper {
9 | }
--------------------------------------------------------------------------------
/src/main/java/com/company/project/model/BaseDO.java:
--------------------------------------------------------------------------------
1 | package com.company.project.model;
2 |
3 | import org.apache.commons.lang.builder.ToStringBuilder;
4 | import org.apache.commons.lang.builder.ToStringStyle;
5 |
6 | import java.io.Serializable;
7 |
8 | /**
9 | * 基础DO类,提供toString快方法
10 | * Created by liwei on 2015/6/16.
11 | */
12 | public class BaseDO implements Serializable {
13 |
14 | private static final long serialVersionUID = -1394589131426860408L;
15 |
16 | public String toString() {
17 | return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
18 | }
19 |
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/model/User.java:
--------------------------------------------------------------------------------
1 | package com.company.project.model;
2 |
3 | import java.util.Date;
4 | import javax.persistence.*;
5 |
6 | public class User extends BaseDO{
7 | @Id
8 | @GeneratedValue(strategy = GenerationType.IDENTITY)
9 | private Integer id;
10 |
11 | private String username;
12 |
13 | private String password;
14 |
15 | @Column(name = "nick_name")
16 | private String nickName;
17 |
18 | private Integer sex;
19 |
20 | @Column(name = "register_date")
21 | private Date registerDate;
22 |
23 | /**
24 | * @return id
25 | */
26 | public Integer getId() {
27 | return id;
28 | }
29 |
30 | /**
31 | * @param id
32 | */
33 | public void setId(Integer id) {
34 | this.id = id;
35 | }
36 |
37 | /**
38 | * @return username
39 | */
40 | public String getUsername() {
41 | return username;
42 | }
43 |
44 | /**
45 | * @param username
46 | */
47 | public void setUsername(String username) {
48 | this.username = username;
49 | }
50 |
51 | /**
52 | * @return password
53 | */
54 | public String getPassword() {
55 | return password;
56 | }
57 |
58 | /**
59 | * @param password
60 | */
61 | public void setPassword(String password) {
62 | this.password = password;
63 | }
64 |
65 | /**
66 | * @return nick_name
67 | */
68 | public String getNickName() {
69 | return nickName;
70 | }
71 |
72 | /**
73 | * @param nickName
74 | */
75 | public void setNickName(String nickName) {
76 | this.nickName = nickName;
77 | }
78 |
79 | /**
80 | * @return sex
81 | */
82 | public Integer getSex() {
83 | return sex;
84 | }
85 |
86 | /**
87 | * @param sex
88 | */
89 | public void setSex(Integer sex) {
90 | this.sex = sex;
91 | }
92 |
93 | /**
94 | * @return register_date
95 | */
96 | public Date getRegisterDate() {
97 | return registerDate;
98 | }
99 |
100 | /**
101 | * @param registerDate
102 | */
103 | public void setRegisterDate(Date registerDate) {
104 | this.registerDate = registerDate;
105 | }
106 | }
--------------------------------------------------------------------------------
/src/main/java/com/company/project/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.company.project.service;
2 | import com.company.project.model.User;
3 | import com.company.project.core.service.Service;
4 |
5 |
6 | /**
7 | * Created by CodeGenerator on 2017/08/21.
8 | */
9 | public interface UserService extends Service {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/service/impl/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.company.project.service.impl;
2 |
3 | import com.company.project.dao.UserMapper;
4 | import com.company.project.model.User;
5 | import com.company.project.service.UserService;
6 | import com.company.project.core.service.AbstractService;
7 | import org.springframework.stereotype.Service;
8 | import org.springframework.transaction.annotation.Transactional;
9 |
10 | import javax.annotation.Resource;
11 |
12 |
13 | /**
14 | * Created by CodeGenerator on 2017/08/21.
15 | */
16 | @Service
17 | @Transactional
18 | public class UserServiceImpl extends AbstractService implements UserService {
19 | @Resource
20 | private UserMapper userMapper;
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/company/project/web/UserController.java:
--------------------------------------------------------------------------------
1 | package com.company.project.web;
2 | import com.company.project.core.exception.ServiceException;
3 | import com.company.project.core.result.Result;
4 | import com.company.project.core.result.ResultCode;
5 | import com.company.project.core.result.ResultGenerator;
6 | import com.company.project.model.User;
7 | import com.company.project.service.UserService;
8 | import com.github.pagehelper.PageHelper;
9 | import com.github.pagehelper.PageInfo;
10 | import org.springframework.web.bind.annotation.PostMapping;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.RequestParam;
13 | import org.springframework.web.bind.annotation.RestController;
14 |
15 | import javax.annotation.Resource;
16 | import java.util.List;
17 |
18 | /**
19 | * Created by CodeGenerator on 2017/08/21.
20 | */
21 | @RestController
22 | @RequestMapping(value="/user",produces="application/json;charset=UTF-8")
23 | public class UserController {
24 | @Resource
25 | private UserService userService;
26 |
27 | @PostMapping("/add")
28 | public Result add(User user) {
29 | userService.save(user);
30 | return ResultGenerator.genSuccessResult();
31 | }
32 |
33 | @PostMapping("/delete")
34 | public Result delete(@RequestParam Integer id) {
35 | userService.deleteById(id);
36 | return ResultGenerator.genSuccessResult();
37 | }
38 |
39 | @PostMapping("/update")
40 | public Result update(User user) {
41 | userService.update(user);
42 | return ResultGenerator.genSuccessResult();
43 | }
44 |
45 | @RequestMapping("/detail")
46 | public Result detail(@RequestParam Integer id) {
47 | User user = userService.findById(id);
48 | return ResultGenerator.genSuccessResult(user);
49 | }
50 |
51 | @RequestMapping("/list")
52 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) {
53 | PageHelper.startPage(page, size);
54 | List list = userService.findAll();
55 | PageInfo pageInfo = new PageInfo<>(list);
56 | return ResultGenerator.genSuccessResult(pageInfo);
57 | }
58 |
59 | @RequestMapping("/test")
60 | public Result test(){
61 | return new Result(ResultCode.FAIL);
62 | }
63 |
64 | @RequestMapping("/e")
65 | public Result e() throws ServiceException {
66 | throw new ServiceException(ResultCode.INVALID_PARAM);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/resources/application-dev.properties:
--------------------------------------------------------------------------------
1 | # \u5F00\u53D1\u73AF\u5883\u914D\u7F6E
2 | # \u6570\u636E\u6E90\u914D\u7F6E\uFF0C\u8BF7\u4FEE\u6539\u4E3A\u4F60\u9879\u76EE\u7684\u5B9E\u9645\u914D\u7F6E
3 |
4 | #mysql数据库连接配置
5 | spring.datasource.url=jdbc:mysql://192.168.0.174:3306/test
6 | spring.datasource.username=user
7 | spring.datasource.password=password
8 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
9 |
10 |
11 | #rabbitMQ配置
12 | #服务器地址
13 | spring.rabbitmq.host=192.168.0.174
14 | #服务器端口
15 | spring.rabbitmq.port=5672
16 | #登录名,rabbitMQ默认账号为guest
17 | spring.rabbitmq.username=jimersylee
18 | #密码,默认密码为guest
19 | spring.rabbitmq.password=jimersylee
20 |
21 |
22 | #redis配置
23 | spring.redis.host=192.168.0.174
24 | spring.redis.port=6379
25 | spring.redis.password=
26 | spring.redis.database=1
27 | spring.redis.pool.max-active=8
28 | spring.redis.pool.max-wait=-1
29 | spring.redis.pool.max-idle=500
30 | spring.redis.pool.min-idle=0
31 | spring.redis.timeout=0
32 |
33 | #日志级别配置
34 | debug=false
35 | logging.level.root=INFO
36 | logging.level.org.springframework.web=INFO
37 | logging.path=/home/jimersylee/projects/java/spring-boot-api-project-seed/log/
38 |
39 |
40 |
41 | ########################################################
42 | ###FREEMARKER (FreeMarkerAutoConfiguration)
43 | ########################################################
44 | #spring.freemarker.enabled=true
45 | #spring.freemarker.allow-request-override=false
46 | #spring.freemarker.cache=true
47 | #spring.freemarker.check-template-location=true
48 | #spring.freemarker.charset=UTF-8
49 | #spring.freemarker.content-type=text/html
50 | #spring.freemarker.expose-request-attributes=false
51 | #spring.freemarker.expose-session-attributes=false
52 | #spring.freemarker.expose-spring-macro-helpers=false
53 | #spring.freemarker.prefix=
54 | #spring.freemarker.request-context-attribute=
55 | #spring.freemarker.settings.*=
56 | #spring.freemarker.suffix=.ftl
57 | #comma-separated list
58 | #spring.freemarker.template-loader-path=classpath:/templates/
59 | #spring.freemarker.view-names= # whitelist of view names that can be resolved
60 |
61 |
62 | #java mail配置,使用此配置发送邮件
63 | #spring.mail.host=smtp.163.com
64 | #spring.mail.username=请输入用户名
65 | #spring.mail.password=请输入密码
66 | #spring.mail.port=25
67 | #spring.mail.protocol=smtp
68 | #spring.mail.default-encoding=UTF-8
69 |
70 |
71 |
72 | #应用监控配置
73 | #访问敏感接口是否启动鉴权
74 | management.security.enabled=false
75 |
76 |
77 | #log4j配置
78 | #spring.datasource.druid.filter.log4j.connection-log-enabled=true
79 |
80 |
81 |
82 | ## Dubbo 服务提供者配置
83 | spring.dubbo.application.name=provider
84 | spring.dubbo.registry.address=zookeeper://192.168.0.174:2181
85 | spring.dubbo.protocol.name=dubbo
86 | spring.dubbo.protocol.port=20880
87 | spring.dubbo.scan=com.company.project.core.service.dubbo
88 |
89 |
90 |
91 |
92 |
93 | ##zookeeper配置
94 | ZK_HOSTS=192.168.0.174:2181
95 | EVENT_CONSUMER_NUM=2
96 | SESSION_TIMEOUT=3600000
97 |
98 | #将本机服务注册到zookeeper上的配置
99 | #本机ip地址,可以不填,自动获取
100 | #LOCAL_HOST_NAME=192.168.0.174
101 | #本机对外服务端口,默认8080
102 | LOCAL_PORT=8080
103 |
104 |
105 |
--------------------------------------------------------------------------------
/src/main/resources/application-pro.properties:
--------------------------------------------------------------------------------
1 | # \u751F\u4EA7\u73AF\u5883\u914D\u7F6E
--------------------------------------------------------------------------------
/src/main/resources/application-test.properties:
--------------------------------------------------------------------------------
1 | # \u6D4B\u8BD5\u73AF\u5883\u914D\u7F6E
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.profiles.active=dev
2 | # \u6240\u6709\u73AF\u5883\u901A\u7528\u7684\u914D\u7F6E\uFF0C\u653E\u5728\u8FD9\u91CC
3 |
4 | # 404 \u4EA4\u7ED9\u5F02\u5E38\u5904\u7406\u5668\u5904\u7406
5 | spring.mvc.throw-exception-if-no-handler-found=true
6 | spring.resources.add-mappings=false
--------------------------------------------------------------------------------
/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////
2 | // _ooOoo_ //
3 | // o8888888o //
4 | // 88" . "88 //
5 | // (| ^_^ |) //
6 | // O\ = /O //
7 | // ____/`---'\____ //
8 | // .' \\| |// `. //
9 | // / \\||| : |||// \ //
10 | // / _||||| -:- |||||- \ //
11 | // | | \\\ - /// | | //
12 | // | \_| ''\---/'' | | //
13 | // \ .-\__ `-` ___/-. / //
14 | // ___`. .' /--.--\ `. . ___ //
15 | // ."" '< `.___\_<|>_/___.' >'"". //
16 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | //
17 | // \ \ `-. \_ __\ /__ _/ .-` / / //
18 | // ========`-.____`-.___\_____/___.-`____.-'======== //
19 | // `=---=' //
20 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
21 | // 佛祖保佑 永不宕机 永无BUG //
22 | ////////////////////////////////////////////////////////////////////
--------------------------------------------------------------------------------
/src/main/resources/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/resources/mapper/UserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/resources/templates/welcome.ftl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Date: ${time?date}
5 | Message: ${message}
6 |
7 |
--------------------------------------------------------------------------------
/src/test/java/CodeGenerator.java:
--------------------------------------------------------------------------------
1 | import com.google.common.base.CaseFormat;
2 | import freemarker.template.TemplateExceptionHandler;
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.mybatis.generator.api.MyBatisGenerator;
5 | import org.mybatis.generator.config.*;
6 | import org.mybatis.generator.internal.DefaultShellCallback;
7 |
8 | import java.io.File;
9 | import java.io.FileWriter;
10 | import java.io.IOException;
11 | import java.text.SimpleDateFormat;
12 | import java.util.*;
13 |
14 | import static com.company.project.core.constant.ProjectConstant.*;
15 |
16 | /**
17 | * 代码生成器,根据数据表名称生成对应的Model、Mapper、Service、Controller简化开发。
18 | */
19 | public class CodeGenerator {
20 | //JDBC配置,请修改为你项目的实际配置
21 | private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test";
22 | private static final String JDBC_USERNAME = "root";
23 | private static final String JDBC_PASSWORD = "";
24 | private static final String JDBC_DIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
25 |
26 | private static final String PROJECT_PATH = System.getProperty("user.dir");//项目在硬盘上的基础路径
27 | private static final String TEMPLATE_FILE_PATH = PROJECT_PATH + "/src/test/resources/generator/template";//模板位置
28 |
29 | private static final String JAVA_PATH = "/src/main/java"; //java文件路径
30 | private static final String RESOURCES_PATH = "/src/main/resources";//资源文件路径
31 |
32 | private static final String PACKAGE_PATH_SERVICE = packageConvertPath(SERVICE_PACKAGE);//生成的Service存放路径
33 | private static final String PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);//生成的Service实现存放路径
34 | private static final String PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);//生成的Controller存放路径
35 |
36 | private static final String AUTHOR = "CodeGenerator";//@author
37 | private static final String DATE = new SimpleDateFormat("yyyy/MM/dd").format(new Date());//@date
38 |
39 | public static void main(String[] args) {
40 | genCode("trans_const_deal_order");
41 | //genCode("输入表名","输入自定义Model名称");
42 | }
43 |
44 | /**
45 | * 通过数据表名称生成代码,Model 名称通过解析数据表名称获得,下划线转大驼峰的形式。
46 | * 如输入表名称 "t_user_detail" 将生成 TUserDetail、TUserDetailMapper、TUserDetailService ...
47 | * @param tableNames 数据表名称...
48 | */
49 | public static void genCode(String... tableNames) {
50 | for (String tableName : tableNames) {
51 | genCode(tableName, null);
52 | }
53 | }
54 |
55 | /**
56 | * 通过数据表名称,和自定义的 Model 名称生成代码
57 | * 如输入表名称 "t_user_detail" 和自定义的 Model 名称 "User" 将生成 User、UserMapper、UserService ...
58 | * @param tableName 数据表名称
59 | * @param modelName 自定义的 Model 名称
60 | */
61 | public static void genCode(String tableName, String modelName) {
62 | genModelAndMapper(tableName, modelName);
63 | genService(tableName, modelName);
64 | genController(tableName, modelName);
65 | }
66 |
67 |
68 | public static void genModelAndMapper(String tableName, String modelName) {
69 | Context context = new Context(ModelType.FLAT);
70 | context.setId("Potato");
71 | context.setTargetRuntime("MyBatis3Simple");
72 | context.addProperty(PropertyRegistry.CONTEXT_BEGINNING_DELIMITER, "`");
73 | context.addProperty(PropertyRegistry.CONTEXT_ENDING_DELIMITER, "`");
74 |
75 | JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
76 | jdbcConnectionConfiguration.setConnectionURL(JDBC_URL);
77 | jdbcConnectionConfiguration.setUserId(JDBC_USERNAME);
78 | jdbcConnectionConfiguration.setPassword(JDBC_PASSWORD);
79 | jdbcConnectionConfiguration.setDriverClass(JDBC_DIVER_CLASS_NAME);
80 | context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);
81 |
82 | PluginConfiguration pluginConfiguration = new PluginConfiguration();
83 | pluginConfiguration.setConfigurationType("tk.mybatis.mapper.generator.MapperPlugin");
84 | pluginConfiguration.addProperty("mappers", MAPPER_INTERFACE_REFERENCE);
85 | context.addPluginConfiguration(pluginConfiguration);
86 |
87 | JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
88 | javaModelGeneratorConfiguration.setTargetProject(PROJECT_PATH + JAVA_PATH);
89 | javaModelGeneratorConfiguration.setTargetPackage(MODEL_PACKAGE);
90 | context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);
91 |
92 | SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
93 | sqlMapGeneratorConfiguration.setTargetProject(PROJECT_PATH + RESOURCES_PATH);
94 | sqlMapGeneratorConfiguration.setTargetPackage("mapper");
95 | context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);
96 |
97 | JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
98 | javaClientGeneratorConfiguration.setTargetProject(PROJECT_PATH + JAVA_PATH);
99 | javaClientGeneratorConfiguration.setTargetPackage(MAPPER_PACKAGE);
100 | javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
101 | context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);
102 |
103 | TableConfiguration tableConfiguration = new TableConfiguration(context);
104 | tableConfiguration.setTableName(tableName);
105 | tableConfiguration.setDomainObjectName(modelName);
106 | tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null));
107 | context.addTableConfiguration(tableConfiguration);
108 |
109 | List warnings;
110 | MyBatisGenerator generator;
111 | try {
112 | Configuration config = new Configuration();
113 | config.addContext(context);
114 | config.validate();
115 |
116 | boolean overwrite = true;
117 | DefaultShellCallback callback = new DefaultShellCallback(overwrite);
118 | warnings = new ArrayList();
119 | generator = new MyBatisGenerator(config, callback, warnings);
120 | generator.generate(null);
121 | } catch (Exception e) {
122 | throw new RuntimeException("生成Model和Mapper失败", e);
123 | }
124 |
125 | if (generator.getGeneratedJavaFiles().isEmpty() || generator.getGeneratedXmlFiles().isEmpty()) {
126 | throw new RuntimeException("生成Model和Mapper失败:" + warnings);
127 | }
128 | if (StringUtils.isEmpty(modelName)) modelName = tableNameConvertUpperCamel(tableName);
129 | System.out.println(modelName + ".java 生成成功");
130 | System.out.println(modelName + "Mapper.java 生成成功");
131 | System.out.println(modelName + "Mapper.xml 生成成功");
132 | }
133 |
134 | public static void genService(String tableName, String modelName) {
135 | try {
136 | freemarker.template.Configuration cfg = getConfiguration();
137 |
138 | Map data = new HashMap<>();
139 | data.put("date", DATE);
140 | data.put("author", AUTHOR);
141 | String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
142 | data.put("modelNameUpperCamel", modelNameUpperCamel);
143 | data.put("modelNameLowerCamel", tableNameConvertLowerCamel(tableName));
144 | data.put("basePackage", BASE_PACKAGE);
145 |
146 | File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE + modelNameUpperCamel + "Service.java");
147 | if (!file.getParentFile().exists()) {
148 | file.getParentFile().mkdirs();
149 | }
150 | cfg.getTemplate("service.ftl").process(data,
151 | new FileWriter(file));
152 | System.out.println(modelNameUpperCamel + "Service.java 生成成功");
153 |
154 | File file1 = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE_IMPL + modelNameUpperCamel + "ServiceImpl.java");
155 | if (!file1.getParentFile().exists()) {
156 | file1.getParentFile().mkdirs();
157 | }
158 | cfg.getTemplate("service-impl.ftl").process(data,
159 | new FileWriter(file1));
160 | System.out.println(modelNameUpperCamel + "ServiceImpl.java 生成成功");
161 | } catch (Exception e) {
162 | throw new RuntimeException("生成Service失败", e);
163 | }
164 | }
165 |
166 | public static void genController(String tableName, String modelName) {
167 | try {
168 | freemarker.template.Configuration cfg = getConfiguration();
169 |
170 | Map data = new HashMap<>();
171 | data.put("date", DATE);
172 | data.put("author", AUTHOR);
173 | String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName;
174 | data.put("baseRequestMapping", modelNameConvertMappingPath(modelNameUpperCamel));
175 | data.put("modelNameUpperCamel", modelNameUpperCamel);
176 | data.put("modelNameLowerCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, modelNameUpperCamel));
177 | data.put("basePackage", BASE_PACKAGE);
178 |
179 | File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_CONTROLLER + modelNameUpperCamel + "Controller.java");
180 | if (!file.getParentFile().exists()) {
181 | file.getParentFile().mkdirs();
182 | }
183 | //cfg.getTemplate("controller-restful.ftl").process(data, new FileWriter(file));
184 | cfg.getTemplate("controller.ftl").process(data, new FileWriter(file));
185 |
186 | System.out.println(modelNameUpperCamel + "Controller.java 生成成功");
187 | } catch (Exception e) {
188 | throw new RuntimeException("生成Controller失败", e);
189 | }
190 |
191 | }
192 |
193 | private static freemarker.template.Configuration getConfiguration() throws IOException {
194 | freemarker.template.Configuration cfg = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_23);
195 | cfg.setDirectoryForTemplateLoading(new File(TEMPLATE_FILE_PATH));
196 | cfg.setDefaultEncoding("UTF-8");
197 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
198 | return cfg;
199 | }
200 |
201 | private static String tableNameConvertLowerCamel(String tableName) {
202 | return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName.toLowerCase());
203 | }
204 |
205 | private static String tableNameConvertUpperCamel(String tableName) {
206 | return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase());
207 |
208 | }
209 |
210 | private static String tableNameConvertMappingPath(String tableName) {
211 | tableName = tableName.toLowerCase();//兼容使用大写的表名
212 | return "/" + (tableName.contains("_") ? tableName.replaceAll("_", "/") : tableName);
213 | }
214 |
215 | private static String modelNameConvertMappingPath(String modelName) {
216 | String tableName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, modelName);
217 | return tableNameConvertMappingPath(tableName);
218 | }
219 |
220 | private static String packageConvertPath(String packageName) {
221 | return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
222 | }
223 |
224 | }
225 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/Tester.java:
--------------------------------------------------------------------------------
1 | package com.company.project;
2 |
3 | import org.junit.runner.RunWith;
4 | import org.springframework.boot.context.properties.ConfigurationProperties;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | /**
9 | * 单元测试继承该类即可
10 | */
11 | @RunWith(SpringRunner.class)
12 | @SpringBootTest(classes = Application.class)
13 | @ConfigurationProperties
14 | public abstract class Tester {
15 | }
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/amqp/amqpTest.java:
--------------------------------------------------------------------------------
1 | package com.company.project.amqp;
2 |
3 | import com.company.project.core.service.amqp.Sender;
4 | import com.company.project.Tester;
5 | import org.junit.Test;
6 | import javax.annotation.Resource;
7 |
8 | public class amqpTest extends Tester {
9 | @Resource
10 | private Sender sender;
11 | @Test
12 | public void test(){
13 | sender.send();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/async/asyncNeedResponseTest.java:
--------------------------------------------------------------------------------
1 | package com.company.project.async;
2 |
3 | import com.company.project.Tester;
4 | import com.company.project.core.service.AsyncService.AsyncNeedResponseService;
5 | import org.junit.Test;
6 |
7 | import javax.annotation.Resource;
8 | import java.util.concurrent.Future;
9 |
10 | public class asyncNeedResponseTest extends Tester{
11 |
12 | @Resource
13 | private AsyncNeedResponseService asyncNeedResponseService;
14 |
15 |
16 | @Test
17 | public void test() throws Exception{
18 | long startTime=System.currentTimeMillis();
19 |
20 | Future task1=asyncNeedResponseService.sendA();
21 | Future task2=asyncNeedResponseService.sendB();
22 |
23 | while(true){
24 | if(task1.isDone() && task2.isDone()){
25 | break;
26 | }
27 | }
28 |
29 | long endTime=System.currentTimeMillis();
30 | System.out.println("总耗时:"+(endTime-startTime));
31 |
32 | /*输出
33 | send B
34 | send A
35 | 耗时:2000
36 | 耗时:2000
37 | 总耗时:2019
38 | * */
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/async/asyncNoResponseTest.java:
--------------------------------------------------------------------------------
1 | package com.company.project.async;
2 |
3 | import com.company.project.Tester;
4 | import com.company.project.core.service.AsyncService.AsyncNoResponseService;
5 | import org.junit.Test;
6 |
7 | import javax.annotation.Resource;
8 | import java.io.IOException;
9 |
10 | public class asyncNoResponseTest extends Tester {
11 | @Resource
12 | private AsyncNoResponseService asyncNoResponseService;
13 | @Test
14 | public void test() throws InterruptedException, IOException {
15 | asyncNoResponseService.sendA();
16 | asyncNoResponseService.sendB();
17 | System.in.read();//防止程序结束
18 |
19 |
20 | /*
21 | 输出
22 | send A============================
23 | send B============================
24 | B 耗时:2000
25 | A 耗时:5000
26 | * */
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/core/service/dubbo/City.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.service.dubbo;
2 |
3 | import com.company.project.model.BaseDO;
4 |
5 |
6 |
7 | /**
8 | * 城市实体类
9 | *
10 | * Created by bysocket on 07/02/2017.
11 | */
12 | public class City extends BaseDO {
13 |
14 |
15 | /**
16 | * 城市编号
17 | */
18 | private Long id;
19 |
20 | /**
21 | * 省份编号
22 | */
23 | private Long provinceId;
24 |
25 | /**
26 | * 城市名称
27 | */
28 | private String cityName;
29 |
30 | /**
31 | * 描述
32 | */
33 | private String description;
34 |
35 | public City() {
36 | }
37 |
38 | public City(Long id, Long provinceId, String cityName, String description) {
39 | this.id = id;
40 | this.provinceId = provinceId;
41 | this.cityName = cityName;
42 | this.description = description;
43 | }
44 |
45 | public Long getId() {
46 | return id;
47 | }
48 |
49 | public void setId(Long id) {
50 | this.id = id;
51 | }
52 |
53 | public Long getProvinceId() {
54 | return provinceId;
55 | }
56 |
57 | public void setProvinceId(Long provinceId) {
58 | this.provinceId = provinceId;
59 | }
60 |
61 | public String getCityName() {
62 | return cityName;
63 | }
64 |
65 | public void setCityName(String cityName) {
66 | this.cityName = cityName;
67 | }
68 |
69 | public String getDescription() {
70 | return description;
71 | }
72 |
73 | public void setDescription(String description) {
74 | this.description = description;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/core/service/dubbo/CityDubboService.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.service.dubbo;
2 |
3 |
4 | /**
5 | * 必须保证此接口所在的包与provider一致
6 | * 城市业务 Dubbo 服务层
7 | *
8 | * Created by bysocket on 28/02/2017.
9 | */
10 | public interface CityDubboService {
11 |
12 | /**
13 | * 根据城市名称,查询城市信息
14 | * @param cityName
15 | */
16 | City findCityByName(String cityName);
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/core/service/dubbo/DubboConsumerTest.java:
--------------------------------------------------------------------------------
1 | package com.company.project.core.service.dubbo;
2 |
3 | import com.alibaba.dubbo.config.annotation.Reference;
4 |
5 |
6 | import com.company.project.Tester;
7 | import org.junit.Test;
8 |
9 |
10 | /**
11 | *
12 | */
13 | public class DubboConsumerTest extends Tester{
14 |
15 |
16 | @Reference(version = "1.0.0")
17 | CityDubboService consumerService;
18 |
19 | @Test
20 | public void test(){
21 | City result=consumerService.findCityByName("杭州");
22 | System.out.println("==================================="+result.toString());
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/mail/code.txt:
--------------------------------------------------------------------------------
1 | package com.conpany.project.mail;
2 |
3 | import Tester;
4 | import org.junit.Test;
5 | import org.springframework.mail.SimpleMailMessage;
6 | import org.springframework.mail.javamail.JavaMailSender;
7 | import org.springframework.mail.javamail.MimeMessageHelper;
8 |
9 | import javax.annotation.Resource;
10 | import javax.mail.MessagingException;
11 | import javax.mail.internet.MimeMessage;
12 |
13 |
14 |
15 | public class mailTest extends Tester {
16 | @Resource
17 | private JavaMailSender mailSender;
18 |
19 | /**
20 | * 发送包含简单文本的邮件
21 | */
22 | @Test
23 | public void sendTxtMail() {
24 | SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
25 | //设置收件人,寄件人
26 | simpleMailMessage.setTo(new String[]{"jimersylee@gmail.com", "305008389@qq.com"});
27 | simpleMailMessage.setFrom("305008389@qq.com");
28 | simpleMailMessage.setSubject("Spring Boot Mail 邮件标题");
29 | simpleMailMessage.setText("这里是一段简单文本");
30 | //发送
31 | mailSender.send(simpleMailMessage);
32 | System.out.println("++++++++++++++++++++++邮件已发送");
33 | }
34 |
35 | /**
36 | * 发送包含html的邮件
37 | */
38 | @Test
39 | public void sendHtmlMail() throws MessagingException {
40 | MimeMessage mimeMessage = mailSender.createMimeMessage();
41 | MimeMessageHelper mimeMessageHelper=new MimeMessageHelper(mimeMessage);
42 | mimeMessageHelper.setTo("305008389@qq.com");
43 | mimeMessageHelper.setFrom("305008389@qq.com");
44 | mimeMessageHelper.setSubject("Spring Boot Mail 邮件测试[html]");
45 | StringBuilder stringBuilder=new StringBuilder();
46 | stringBuilder.append("");
47 | stringBuilder.append("spring 邮件测试
hello!this is spring mail test。
");
48 | stringBuilder.append("");
49 |
50 | //启用html
51 | mimeMessageHelper.setText(stringBuilder.toString(),true);
52 | //发送邮件
53 | mailSender.send(mimeMessage);
54 | System.out.println("++++++++++++++++++++++邮件已发送");
55 |
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/java/com/company/project/redis/redisTest.java:
--------------------------------------------------------------------------------
1 | package com.company.project.redis;
2 |
3 | import com.company.project.Tester;
4 | import com.company.project.core.service.redis.RedisService;
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 |
8 | import javax.annotation.Resource;
9 |
10 | public class redisTest extends Tester {
11 | @Resource
12 | private RedisService redisService;
13 |
14 | private static final String KEY = "KEY";
15 | private static final String VALUE = "VALUE";
16 |
17 | @Test
18 | public void set() {
19 | String result = redisService.set(KEY, VALUE);
20 | Assert.assertEquals("OK", result);
21 | }
22 |
23 | @Test
24 | public void get() {
25 | redisService.set(KEY, VALUE);
26 | String result;
27 | result = redisService.get(KEY);
28 | Assert.assertEquals(VALUE, result);
29 | }
30 |
31 | @Test
32 | public void del() {
33 |
34 | long effectCount = redisService.delete(KEY);
35 | Assert.assertEquals(1, effectCount);
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/resources/application-dev.properties:
--------------------------------------------------------------------------------
1 | spring.dubbo.application.name=consumer
2 | spring.dubbo.registry.address=zookeeper://192.168.0.174:2181
3 | spring.dubbo.protocol.name=dubbo
4 | spring.dubbo.protocol.port=20881
5 | spring.dubbo.scan=com.company.project.core.service.dubbo
6 |
7 |
8 | ##zookeeper配置
9 | ZK_HOSTS=192.168.0.174:2181
10 | EVENT_CONSUMER_NUM=2
11 | SESSION_TIMEOUT=3600000
12 |
13 | #将本机服务注册到zookeeper上的配置
14 | #本机ip地址,可以不填,自动获取
15 | #LOCAL_HOST_NAME=192.168.0.174
16 | #本机对外服务端口,默认8080
17 | LOCAL_PORT=8080
--------------------------------------------------------------------------------
/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.profiles.active=dev
2 | # \u6240\u6709\u73AF\u5883\u901A\u7528\u7684\u914D\u7F6E\uFF0C\u653E\u5728\u8FD9\u91CC
3 |
4 |
--------------------------------------------------------------------------------
/src/test/resources/demo-user.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat MySQL Data Transfer
3 |
4 | Source Server : Localhost
5 | Source Server Version : 50713
6 | Source Host : localhost:3306
7 | Source Database : test
8 |
9 | Target Server Type : MYSQL
10 | Target Server Version : 50713
11 | File Encoding : 65001
12 |
13 | Date: 2017-06-23 14:25:27
14 | */
15 |
16 | SET FOREIGN_KEY_CHECKS=0;
17 |
18 | -- ----------------------------
19 | -- Table structure for user
20 | -- ----------------------------
21 | DROP TABLE IF EXISTS `user`;
22 | CREATE TABLE `user` (
23 | `id` int(11) NOT NULL AUTO_INCREMENT,
24 | `username` varchar(255) NOT NULL,
25 | `password` varchar(255) NOT NULL,
26 | `nick_name` varchar(255) DEFAULT NULL,
27 | `sex` int(1) DEFAULT NULL,
28 | `register_date` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
29 | PRIMARY KEY (`id`)
30 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
31 |
32 | -- ----------------------------
33 | -- Records of user
34 | -- ----------------------------
35 | INSERT INTO `user` VALUES ('1', '89921218@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆', '1', '2017-06-23 14:24:23');
36 | INSERT INTO `user` VALUES ('2', '2@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-2', '1', '2017-06-23 14:24:23');
37 | INSERT INTO `user` VALUES ('3', '3@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-3', '1', '2017-06-23 14:24:23');
38 | INSERT INTO `user` VALUES ('4', '4@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-4', '1', '2017-06-23 14:24:23');
39 | INSERT INTO `user` VALUES ('5', '5@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-5', '1', '2017-06-23 14:24:23');
40 | INSERT INTO `user` VALUES ('6', '6@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-6', '1', '2017-06-23 14:24:23');
41 | INSERT INTO `user` VALUES ('7', '7@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-7', '1', '2017-06-23 14:24:23');
42 | INSERT INTO `user` VALUES ('8', '8@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-8', '1', '2017-06-23 14:24:23');
43 | INSERT INTO `user` VALUES ('9', '9@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-9', '1', '2017-06-23 14:24:23');
44 | INSERT INTO `user` VALUES ('10', '10@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-10', '1', '2017-06-23 14:24:23');
45 | SET FOREIGN_KEY_CHECKS=1;
46 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/controller-restful.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.web;
2 |
3 | import ${basePackage}.core.Result;
4 | import ${basePackage}.core.ResultGenerator;
5 | import ${basePackage}.model.${modelNameUpperCamel};
6 | import ${basePackage}.service.${modelNameUpperCamel}Service;
7 | import com.github.pagehelper.PageHelper;
8 | import com.github.pagehelper.PageInfo;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | import javax.annotation.Resource;
12 | import java.util.List;
13 |
14 | /**
15 | * Created by ${author} on ${date}.
16 | */
17 | @RestController
18 | @RequestMapping("${baseRequestMapping}")
19 | public class ${modelNameUpperCamel}Controller {
20 | @Resource
21 | private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service;
22 |
23 | @PostMapping
24 | public Result add(@RequestBody ${modelNameUpperCamel} ${modelNameLowerCamel}) {
25 | ${modelNameLowerCamel}Service.save(${modelNameLowerCamel});
26 | return ResultGenerator.genSuccessResult();
27 | }
28 |
29 | @DeleteMapping("/{id}")
30 | public Result delete(@PathVariable Integer id) {
31 | ${modelNameLowerCamel}Service.deleteById(id);
32 | return ResultGenerator.genSuccessResult();
33 | }
34 |
35 | @PutMapping
36 | public Result update(@RequestBody ${modelNameUpperCamel} ${modelNameLowerCamel}) {
37 | ${modelNameLowerCamel}Service.update(${modelNameLowerCamel});
38 | return ResultGenerator.genSuccessResult();
39 | }
40 |
41 | @GetMapping("/{id}")
42 | public Result detail(@PathVariable Integer id) {
43 | ${modelNameUpperCamel} ${modelNameLowerCamel} = ${modelNameLowerCamel}Service.findById(id);
44 | return ResultGenerator.genSuccessResult(${modelNameLowerCamel});
45 | }
46 |
47 | @GetMapping
48 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) {
49 | PageHelper.startPage(page, size);
50 | List<${modelNameUpperCamel}> list = ${modelNameLowerCamel}Service.findAll();
51 | PageInfo pageInfo = new PageInfo(list);
52 | return ResultGenerator.genSuccessResult(pageInfo);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/controller.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.web;
2 | import ${basePackage}.core.Result;
3 | import ${basePackage}.core.ResultGenerator;
4 | import ${basePackage}.model.${modelNameUpperCamel};
5 | import ${basePackage}.service.${modelNameUpperCamel}Service;
6 | import com.github.pagehelper.PageHelper;
7 | import com.github.pagehelper.PageInfo;
8 | import org.springframework.web.bind.annotation.PostMapping;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RequestParam;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import javax.annotation.Resource;
14 | import java.util.List;
15 |
16 | /**
17 | * Created by ${author} on ${date}.
18 | */
19 | @RestController
20 | @RequestMapping("${baseRequestMapping}")
21 | public class ${modelNameUpperCamel}Controller {
22 | @Resource
23 | private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service;
24 |
25 | @PostMapping("/add")
26 | public Result add(${modelNameUpperCamel} ${modelNameLowerCamel}) {
27 | ${modelNameLowerCamel}Service.save(${modelNameLowerCamel});
28 | return ResultGenerator.genSuccessResult();
29 | }
30 |
31 | @PostMapping("/delete")
32 | public Result delete(@RequestParam Integer id) {
33 | ${modelNameLowerCamel}Service.deleteById(id);
34 | return ResultGenerator.genSuccessResult();
35 | }
36 |
37 | @PostMapping("/update")
38 | public Result update(${modelNameUpperCamel} ${modelNameLowerCamel}) {
39 | ${modelNameLowerCamel}Service.update(${modelNameLowerCamel});
40 | return ResultGenerator.genSuccessResult();
41 | }
42 |
43 | @RequestMapping("/detail")
44 | public Result detail(@RequestParam Integer id) {
45 | ${modelNameUpperCamel} ${modelNameLowerCamel} = ${modelNameLowerCamel}Service.findById(id);
46 | return ResultGenerator.genSuccessResult(${modelNameLowerCamel});
47 | }
48 |
49 | @RequestMapping("/list")
50 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) {
51 | PageHelper.startPage(page, size);
52 | List<${modelNameUpperCamel}> list = ${modelNameLowerCamel}Service.findAll();
53 | PageInfo pageInfo = new PageInfo(list);
54 | return ResultGenerator.genSuccessResult(pageInfo);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/service-impl.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.service.impl;
2 |
3 | import ${basePackage}.dao.${modelNameUpperCamel}Mapper;
4 | import ${basePackage}.model.${modelNameUpperCamel};
5 | import ${basePackage}.service.${modelNameUpperCamel}Service;
6 | import ${basePackage}.core.AbstractService;
7 | import org.springframework.stereotype.Service;
8 | import org.springframework.transaction.annotation.Transactional;
9 |
10 | import javax.annotation.Resource;
11 |
12 |
13 | /**
14 | * Created by ${author} on ${date}.
15 | */
16 | @Service
17 | @Transactional
18 | public class ${modelNameUpperCamel}ServiceImpl extends AbstractService<${modelNameUpperCamel}> implements ${modelNameUpperCamel}Service {
19 | @Resource
20 | private ${modelNameUpperCamel}Mapper ${modelNameLowerCamel}Mapper;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/resources/generator/template/service.ftl:
--------------------------------------------------------------------------------
1 | package ${basePackage}.service;
2 | import ${basePackage}.model.${modelNameUpperCamel};
3 | import ${basePackage}.core.Service;
4 |
5 |
6 | /**
7 | * Created by ${author} on ${date}.
8 | */
9 | public interface ${modelNameUpperCamel}Service extends Service<${modelNameUpperCamel}> {
10 |
11 | }
12 |
--------------------------------------------------------------------------------