Compare commits
42 Commits
ab8c68d90f
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| cc5cbc1ebb | |||
| e76d89f774 | |||
| ee6f67a6ab | |||
| b3dbc9f668 | |||
| 163882bb4d | |||
| 3947896a04 | |||
| d3b548c8b4 | |||
| cc013f3b86 | |||
| e106affde0 | |||
| 7aca97aa2e | |||
| 2f74ee2c8c | |||
| 0b5acb84ab | |||
| dccb21493b | |||
| 7cfdaab3d0 | |||
| bf4d8c5fb9 | |||
| 5865722a7d | |||
| 165f099240 | |||
| f581b143dc | |||
| 8d2f0d57b5 | |||
| 1fb0c52138 | |||
| 3b5b3b50a9 | |||
| f5ff83737c | |||
| 59c2bd2e3c | |||
| 367798c0dc | |||
| d194341936 | |||
|
|
3ee99909b8 | ||
| 2584e13e20 | |||
| 612feb1e9e | |||
| 6c8b22b204 | |||
| fa4748c57c | |||
|
|
16dad8f7b6 | ||
|
|
d8a328c472 | ||
|
|
b83d324c54 | ||
|
|
522969e077 | ||
|
|
19161217b7 | ||
|
|
2953e48009 | ||
|
|
69d714f19a | ||
| de91226dba | |||
| 7403cea6a7 | |||
|
|
6a59bac8b9 | ||
| 7697a84edf | |||
|
|
9f737f1a45 |
21
SECURITY.md
Normal file
21
SECURITY.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 5.1.x | :white_check_mark: |
|
||||
| 5.0.x | :x: |
|
||||
| 4.0.x | :white_check_mark: |
|
||||
| < 4.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Use this section to tell people how to report a vulnerability.
|
||||
|
||||
Tell them where to go, how often they can expect to get an update on a
|
||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
||||
declined, etc.
|
||||
136
pom.xml
136
pom.xml
@@ -5,6 +5,18 @@
|
||||
<artifactId>budd</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<!--<build>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <source>11</source>-->
|
||||
<!-- <target>11</target>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- </plugins>-->
|
||||
<!--</build>-->
|
||||
|
||||
<name>budd</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
@@ -18,16 +30,40 @@
|
||||
|
||||
<spring.version>5.2.6.RELEASE</spring.version>
|
||||
<servlet.version>2.5</servlet.version>
|
||||
<mybatis.version>3.2.7</mybatis.version>
|
||||
<mybatis.version>3.5.6</mybatis.version>
|
||||
<mybatis.spring.version>1.1.1</mybatis.spring.version>
|
||||
<mybatis.generator.core.version>1.4.0</mybatis.generator.core.version>
|
||||
<file_encoding>utf-8</file_encoding>
|
||||
<jdk.verion>1.8</jdk.verion>
|
||||
<powermock.version>1.7.1</powermock.version>
|
||||
<kotlin.version>1.3.61</kotlin.version>
|
||||
</properties>
|
||||
|
||||
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
@@ -57,6 +93,12 @@
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- spring begin-->
|
||||
@@ -161,7 +203,13 @@
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>2.8.0</version>
|
||||
<version>3.4.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -170,11 +218,11 @@
|
||||
<version>8.0.16</version>
|
||||
</dependency>
|
||||
|
||||
<!-- servlet -->
|
||||
<!-- Servlet -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>${servlet.version}</version>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -222,10 +270,32 @@
|
||||
<version>3.1.6</version>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>org.apache.activemq</groupId>-->
|
||||
<!-- <artifactId>activemq-all</artifactId>-->
|
||||
<!-- <version>5.13.3</version>-->
|
||||
<!--</dependency>-->
|
||||
<!-- activemq依赖包 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-all</artifactId>
|
||||
<version>5.13.3</version>
|
||||
<artifactId>activemq-broker</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-pool</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-spring</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.jms</groupId>
|
||||
<artifactId>javax.jms-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -262,7 +332,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>28.2-jre</version>
|
||||
<version>29.0-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jodd</groupId>
|
||||
@@ -284,12 +354,32 @@
|
||||
<groupId>com.rabbitmq</groupId>
|
||||
<artifactId>amqp-client</artifactId>
|
||||
<version>4.8.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hbase</groupId>
|
||||
<artifactId>hbase-client</artifactId>
|
||||
<version>1.3.5</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>log4j</artifactId>
|
||||
<groupId>log4j</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -301,7 +391,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<version>2.10.5.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -359,4 +449,30 @@
|
||||
<!-- </snapshots>-->
|
||||
<!-- </repository>-->
|
||||
<!--</repositories>-->
|
||||
|
||||
<build>
|
||||
<!--单元测试时引用src/main/resources下的资源文件-->
|
||||
<testResources>
|
||||
<testResource>
|
||||
<directory>src/test/resources</directory>
|
||||
</testResource>
|
||||
<testResource>
|
||||
<directory>src/main/resources</directory>
|
||||
</testResource>
|
||||
</testResources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
39
src/main/java/io/github/ehlxr/BuddApplication.java
Normal file
39
src/main/java/io/github/ehlxr/BuddApplication.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 09:35.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class BuddApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BuddApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,16 +22,14 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.test;
|
||||
|
||||
import io.github.ehlxr.redis.JedisUtil;
|
||||
package io.github.ehlxr;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2016/6/14.
|
||||
* @author ehlxr
|
||||
* @since 2021-07-07 22:54.
|
||||
*/
|
||||
public class Main {
|
||||
public class ClassLoaderTest {
|
||||
public static void main(String[] args) {
|
||||
JedisUtil.set("test_20160614", "20160614");
|
||||
System.out.println(JedisUtil.getStr("test_20160614"));
|
||||
System.out.println(ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.redis;
|
||||
package io.github.ehlxr;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.linkedlist;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-04 14:19.
|
||||
*/
|
||||
public class DoubleLinkedListDemo {
|
||||
public static void main(String[] args) {
|
||||
HeroNode2 hero1 = new HeroNode2(1, "宋江", "及时雨");
|
||||
HeroNode2 hero2 = new HeroNode2(3, "卢俊义", "玉麒麟");
|
||||
HeroNode2 hero3 = new HeroNode2(5, "吴用", "智多星");
|
||||
HeroNode2 hero4 = new HeroNode2(8, "林冲", "豹子头");
|
||||
|
||||
DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
|
||||
doubleLinkedList.addByOrder(hero1);
|
||||
doubleLinkedList.addByOrder(hero2);
|
||||
doubleLinkedList.addByOrder(hero3);
|
||||
doubleLinkedList.addByOrder(hero4);
|
||||
|
||||
doubleLinkedList.list();
|
||||
|
||||
doubleLinkedList.update(new HeroNode2(3, "小卢", "玉麒麟--"));
|
||||
System.out.println("修改后的结果");
|
||||
doubleLinkedList.list();
|
||||
|
||||
doubleLinkedList.del(3);
|
||||
System.out.println("删除后的结果");
|
||||
doubleLinkedList.list();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 双向链表
|
||||
*/
|
||||
class DoubleLinkedList {
|
||||
private final HeroNode2 head = new HeroNode2(0, "", "");
|
||||
|
||||
public HeroNode2 getHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public void list() {
|
||||
HeroNode2 temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(HeroNode2 heroNode) {
|
||||
HeroNode2 temp = head;
|
||||
while (temp.next != null) {
|
||||
temp = temp.next;
|
||||
}
|
||||
temp.next = heroNode;
|
||||
heroNode.pre = temp;
|
||||
}
|
||||
|
||||
public void addByOrder(HeroNode2 heroNode) {
|
||||
HeroNode2 temp = head;
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到需要插入位置的前一个节点
|
||||
if (temp.next.no > heroNode.no) {
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
|
||||
heroNode.next = temp.next;
|
||||
heroNode.pre = temp;
|
||||
|
||||
if (temp.next != null) {
|
||||
temp.next.pre = heroNode;
|
||||
}
|
||||
temp.next = heroNode;
|
||||
}
|
||||
|
||||
public void update(HeroNode2 newHeroNode) {
|
||||
HeroNode2 temp = head.next;
|
||||
if (temp == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp == null) {
|
||||
System.out.printf("没找到 %d 的节点\n", newHeroNode.no);
|
||||
break;
|
||||
}
|
||||
|
||||
if (temp.no == newHeroNode.no) {
|
||||
temp.name = newHeroNode.name;
|
||||
temp.nickname = newHeroNode.nickname;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void del(int no) {
|
||||
HeroNode2 temp = head.next;
|
||||
if (temp == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp == null) {
|
||||
System.out.printf("没找到要删除的 %d 节点\n", no);
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到待删除节点
|
||||
if (temp.no == no) {
|
||||
temp.pre.next = temp.next;
|
||||
if (temp.next != null) {
|
||||
temp.next.pre = temp.pre;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义HeroNode , 每个HeroNode 对象就是一个节点
|
||||
*/
|
||||
class HeroNode2 {
|
||||
public int no;
|
||||
public String name;
|
||||
public String nickname;
|
||||
public HeroNode2 next; //指向下一个节点
|
||||
public HeroNode2 pre;// 指向上一个节点
|
||||
|
||||
public HeroNode2(int no, String name, String nickname) {
|
||||
this.no = no;
|
||||
this.name = name;
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为了显示方法,我们重新 toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HeroNode2 [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.linkedlist;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-09 21:14.
|
||||
*/
|
||||
public class Josephu {
|
||||
public static void main(String[] args) {
|
||||
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
|
||||
circleSingleLinkedList.addBoy(5);
|
||||
circleSingleLinkedList.show();
|
||||
|
||||
circleSingleLinkedList.countBoy(1, 2, 5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环单向链表
|
||||
*/
|
||||
class CircleSingleLinkedList {
|
||||
private Boy first = null;
|
||||
|
||||
public void addBoy(int nums) {
|
||||
if (nums < 1) {
|
||||
return;
|
||||
}
|
||||
Boy curBoy = null;
|
||||
for (int i = 1; i <= nums; i++) {
|
||||
Boy boy = new Boy(i);
|
||||
if (i == 1) {
|
||||
first = boy;
|
||||
curBoy = first;
|
||||
first.setNext(first);
|
||||
} else {
|
||||
curBoy.setNext(boy);
|
||||
boy.setNext(first);
|
||||
curBoy = boy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (first == null) {
|
||||
System.out.println("没有boy");
|
||||
return;
|
||||
}
|
||||
|
||||
Boy curBoy = first;
|
||||
while (true) {
|
||||
System.out.printf("boy no %d\n", curBoy.getNo());
|
||||
if (curBoy.getNext() == first) {
|
||||
break;
|
||||
}
|
||||
|
||||
curBoy = curBoy.getNext();
|
||||
}
|
||||
}
|
||||
|
||||
public void countBoy(int startNo, int countNum, int size) {
|
||||
if (first == null || startNo > size || startNo < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 找到最后一个节点
|
||||
Boy helper = first;
|
||||
while (true) {
|
||||
if (helper.getNext() == first) {
|
||||
break;
|
||||
}
|
||||
helper = helper.getNext();
|
||||
}
|
||||
|
||||
// 找到开始报数的位置
|
||||
for (int i = 0; i < startNo - 1; i++) {
|
||||
helper = helper.getNext();
|
||||
first = first.getNext();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (helper == first) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < countNum - 1; i++) {
|
||||
helper = helper.getNext();
|
||||
first = first.getNext();
|
||||
}
|
||||
System.out.printf("出圈的小孩 %d\n", first.getNo());
|
||||
|
||||
first = first.getNext();
|
||||
helper.setNext(first);
|
||||
}
|
||||
System.out.printf("最后出圈的小孩 %d\n", first.getNo());
|
||||
}
|
||||
}
|
||||
|
||||
class Boy {
|
||||
private int no;
|
||||
private Boy next;
|
||||
|
||||
public Boy(int no) {
|
||||
this.no = no;
|
||||
}
|
||||
|
||||
public int getNo() {
|
||||
return no;
|
||||
}
|
||||
|
||||
public void setNo(int no) {
|
||||
this.no = no;
|
||||
}
|
||||
|
||||
public Boy getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public void setNext(Boy next) {
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.linkedlist;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-04 14:19.
|
||||
*/
|
||||
public class SingleLinkedListDemo {
|
||||
public static void main(String[] args) {
|
||||
HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
|
||||
HeroNode hero2 = new HeroNode(3, "卢俊义", "玉麒麟");
|
||||
HeroNode hero3 = new HeroNode(5, "吴用", "智多星");
|
||||
HeroNode hero4 = new HeroNode(8, "林冲", "豹子头");
|
||||
|
||||
SingleLinkedList singleLinkedList = new SingleLinkedList();
|
||||
|
||||
// 加入
|
||||
// singleLinkedList.add(hero1);
|
||||
// singleLinkedList.add(hero4);
|
||||
// singleLinkedList.add(hero2);
|
||||
// singleLinkedList.add(hero3);
|
||||
|
||||
singleLinkedList.addByOrder(hero1);
|
||||
singleLinkedList.addByOrder(hero4);
|
||||
singleLinkedList.addByOrder(hero2);
|
||||
singleLinkedList.addByOrder(hero3);
|
||||
singleLinkedList.list();
|
||||
|
||||
// 反转链表
|
||||
// reverseList(singleLinkedList.getHead());
|
||||
// System.out.println("反转之后的链表");
|
||||
// singleLinkedList.list();
|
||||
//
|
||||
// HeroNode newHeroNode = new HeroNode(3, "小吴", "智多星..");
|
||||
// singleLinkedList.update(newHeroNode);
|
||||
// System.out.println("修改后的链表");
|
||||
// singleLinkedList.list();
|
||||
//
|
||||
// singleLinkedList.del(3);
|
||||
// System.out.println("删除 no 为 3 的节点");
|
||||
// singleLinkedList.list();
|
||||
|
||||
SingleLinkedList singleLinkedList2 = new SingleLinkedList();
|
||||
singleLinkedList2.addByOrder(new HeroNode(2, "2", "2"));
|
||||
singleLinkedList2.addByOrder(new HeroNode(3, "3", "3"));
|
||||
singleLinkedList2.addByOrder(new HeroNode(8, "8", "8"));
|
||||
singleLinkedList2.addByOrder(new HeroNode(9, "9", "9"));
|
||||
singleLinkedList2.list();
|
||||
|
||||
bind2(singleLinkedList.getHead(), singleLinkedList2.getHead());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 反转链表
|
||||
*/
|
||||
public static void reverseList(HeroNode head) {
|
||||
HeroNode pre = null;
|
||||
HeroNode cur = head.next;
|
||||
while (cur != null) {
|
||||
HeroNode next = cur.next;
|
||||
|
||||
cur.next = pre;
|
||||
|
||||
pre = cur;
|
||||
|
||||
cur = next;
|
||||
}
|
||||
|
||||
head.next = pre;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并有序链表
|
||||
*/
|
||||
public static void bind2(HeroNode node1, HeroNode node2) {
|
||||
Stack<HeroNode> stack = new Stack<>();
|
||||
|
||||
HeroNode cur = node1.next;
|
||||
while (cur != null) {
|
||||
stack.push(cur);
|
||||
cur = cur.next;
|
||||
}
|
||||
|
||||
cur = node2.next;
|
||||
while (cur != null) {
|
||||
stack.push(cur);
|
||||
cur = cur.next;
|
||||
}
|
||||
|
||||
SingleLinkedList result = new SingleLinkedList();
|
||||
for (HeroNode node : stack) {
|
||||
result.addByOrder(node);
|
||||
}
|
||||
|
||||
// 打印结果
|
||||
System.out.println("合并结果");
|
||||
result.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并有序链表
|
||||
*/
|
||||
public static void bind(HeroNode node1, HeroNode node2) {
|
||||
SingleLinkedList result = new SingleLinkedList();
|
||||
|
||||
if (node1.next == null) {
|
||||
result.add(node2.next);
|
||||
return;
|
||||
}
|
||||
if (node2.next == null) {
|
||||
result.add(node1.next);
|
||||
return;
|
||||
}
|
||||
while (node1.next != null || node2.next != null) {
|
||||
HeroNode temp = null;
|
||||
if (node1.next == null) {
|
||||
result.add(node2.next);
|
||||
break;
|
||||
}
|
||||
if (node2.next == null) {
|
||||
result.add(node1.next);
|
||||
break;
|
||||
}
|
||||
|
||||
if (node1.next.no < node2.next.no) {
|
||||
temp = node1.next;
|
||||
node1.next = node1.next.next;
|
||||
} else {
|
||||
temp = node2.next;
|
||||
node2.next = node2.next.next;
|
||||
}
|
||||
|
||||
temp.next = null;
|
||||
result.add(temp);
|
||||
}
|
||||
|
||||
// 打印结果
|
||||
System.out.println("合并结果");
|
||||
result.list();
|
||||
}
|
||||
}
|
||||
|
||||
class SingleLinkedList {
|
||||
private final HeroNode head = new HeroNode(0, "", "");
|
||||
|
||||
public HeroNode getHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public void list() {
|
||||
HeroNode temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(HeroNode heroNode) {
|
||||
HeroNode temp = head;
|
||||
while (temp.next != null) {
|
||||
temp = temp.next;
|
||||
}
|
||||
temp.next = heroNode;
|
||||
}
|
||||
|
||||
public void addByOrder(HeroNode heroNode) {
|
||||
HeroNode temp = head;
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到需要插入位置的前一个节点
|
||||
if (temp.next.no > heroNode.no) {
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
|
||||
heroNode.next = temp.next;
|
||||
temp.next = heroNode;
|
||||
}
|
||||
|
||||
public void update(HeroNode newHeroNode) {
|
||||
HeroNode temp = head.next;
|
||||
if (temp == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp == null) {
|
||||
System.out.printf("没找到 %d 的节点\n", newHeroNode.no);
|
||||
break;
|
||||
}
|
||||
|
||||
if (temp.no == newHeroNode.no) {
|
||||
temp.name = newHeroNode.name;
|
||||
temp.nickname = newHeroNode.nickname;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void del(int no) {
|
||||
HeroNode temp = head;
|
||||
if (temp.next == null) {
|
||||
System.out.println("链表为空!");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
System.out.printf("没找到要删除的 %d 节点\n", no);
|
||||
break;
|
||||
}
|
||||
|
||||
// 找到待删除节点的前一个节点
|
||||
if (temp.next.no == no) {
|
||||
temp.next = temp.next.next;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义HeroNode , 每个HeroNode 对象就是一个节点
|
||||
*/
|
||||
class HeroNode {
|
||||
public int no;
|
||||
public String name;
|
||||
public String nickname;
|
||||
public HeroNode next; //指向下一个节点
|
||||
|
||||
// 构造器
|
||||
public HeroNode(int no, String name, String nickname) {
|
||||
this.no = no;
|
||||
this.name = name;
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为了显示方法,我们重新 toString
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* 使用数组模拟队列
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-03-30 22:26.
|
||||
*/
|
||||
public class ArrayQueueDemo {
|
||||
public static void main(String[] args) {
|
||||
//测试一把
|
||||
//创建一个队列
|
||||
ArrayQueue queue = new ArrayQueue(3);
|
||||
char key; //接收用户输入
|
||||
Scanner scanner = new Scanner(System.in);//
|
||||
boolean loop = true;
|
||||
//输出一个菜单
|
||||
while (loop) {
|
||||
System.out.println("s(show): 显示队列");
|
||||
System.out.println("e(exit): 退出程序");
|
||||
System.out.println("a(add): 添加数据到队列");
|
||||
System.out.println("g(get): 从队列取出数据");
|
||||
System.out.println("h(head): 查看队列头的数据");
|
||||
key = scanner.next().charAt(0);//接收一个字符
|
||||
switch (key) {
|
||||
case 's':
|
||||
queue.showQueue();
|
||||
break;
|
||||
case 'a':
|
||||
System.out.println("输出一个数");
|
||||
int value = scanner.nextInt();
|
||||
queue.addQueue(value);
|
||||
break;
|
||||
case 'g': //取出数据
|
||||
try {
|
||||
int res = queue.getQueue();
|
||||
System.out.printf("取出的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'h': //查看队列头的数据
|
||||
try {
|
||||
int res = queue.headQueue();
|
||||
System.out.printf("队列头的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'e': //退出
|
||||
scanner.close();
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("程序退出~~");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ArrayQueue {
|
||||
private final int maxSize; // 表示数组的最大容量
|
||||
private int front; // 队列头
|
||||
private int rear; // 队列尾
|
||||
private final int[] arr; // 该数据用于存放数据, 模拟队列
|
||||
|
||||
// 创建队列的构造器
|
||||
public ArrayQueue(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
this.arr = new int[maxSize];
|
||||
}
|
||||
|
||||
// 判断队列是否满
|
||||
public boolean isFull() {
|
||||
return rear == maxSize;
|
||||
}
|
||||
|
||||
// 判断队列是否为空
|
||||
public boolean isEmpty() {
|
||||
return rear == front;
|
||||
}
|
||||
|
||||
// 添加数据到队列
|
||||
public void addQueue(int n) {
|
||||
if (isFull()) {
|
||||
System.out.println("队列已满,无法添加数据!");
|
||||
return;
|
||||
}
|
||||
|
||||
arr[rear++] = n;
|
||||
}
|
||||
|
||||
// 获取队列的数据, 出队列
|
||||
public int getQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
|
||||
return arr[front++];
|
||||
}
|
||||
|
||||
// 显示队列的所有数据
|
||||
public void showQueue() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("队列为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = front; i < rear; i++) {
|
||||
System.out.printf("arr[%d]=%d\n", i, arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示队列的头数据, 注意不是取出数据
|
||||
public int headQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
|
||||
return arr[front];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.queue;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-03-30 22:52.
|
||||
*/
|
||||
public class CircleArrayQueueDemo {
|
||||
public static void main(String[] args) {
|
||||
//创建一个环形队列
|
||||
CircleArrayQueue queue = new CircleArrayQueue(3);
|
||||
char key; //接收用户输入
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
boolean loop = true;
|
||||
//输出一个菜单
|
||||
while (loop) {
|
||||
System.out.println("s(show): 显示队列");
|
||||
System.out.println("e(exit): 退出程序");
|
||||
System.out.println("a(add): 添加数据到队列");
|
||||
System.out.println("g(get): 从队列取出数据");
|
||||
System.out.println("h(head): 查看队列头的数据");
|
||||
key = scanner.next().charAt(0);//接收一个字符
|
||||
switch (key) {
|
||||
case 's':
|
||||
queue.showQueue();
|
||||
break;
|
||||
case 'a':
|
||||
System.out.println("输出一个数");
|
||||
int value = scanner.nextInt();
|
||||
queue.addQueue(value);
|
||||
break;
|
||||
case 'g': //取出数据
|
||||
try {
|
||||
int res = queue.getQueue();
|
||||
System.out.printf("取出的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'h': //查看队列头的数据
|
||||
try {
|
||||
int res = queue.headQueue();
|
||||
System.out.printf("队列头的数据是%d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case 'e': //退出
|
||||
scanner.close();
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("程序退出~~");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class CircleArrayQueue {
|
||||
private final int maxSize; // 表示数组的最大容量
|
||||
private int front; // 队列头
|
||||
private int rear; // 队列尾
|
||||
private final int[] arr; // 该数据用于存放数据, 模拟队列
|
||||
|
||||
// 创建队列的构造器
|
||||
public CircleArrayQueue(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
this.arr = new int[maxSize];
|
||||
}
|
||||
|
||||
// 判断队列是否满
|
||||
public boolean isFull() {
|
||||
return rear - front == maxSize;
|
||||
// return (rear + 1) % maxSize == front;
|
||||
}
|
||||
|
||||
// 判断队列是否为空
|
||||
public boolean isEmpty() {
|
||||
return rear == front;
|
||||
}
|
||||
|
||||
// 添加数据到队列
|
||||
public void addQueue(int n) {
|
||||
if (isFull()) {
|
||||
System.out.println("队列已满,无法添加数据!");
|
||||
return;
|
||||
}
|
||||
|
||||
arr[(rear++) % maxSize] = n;
|
||||
}
|
||||
|
||||
// 获取队列的数据, 出队列
|
||||
public int getQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
int tem = arr[front % maxSize];
|
||||
front++;
|
||||
return tem;
|
||||
}
|
||||
|
||||
// 显示队列的所有数据
|
||||
public void showQueue() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("队列为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = front; i < rear; i++) {
|
||||
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示队列的头数据, 注意不是取出数据
|
||||
public int headQueue() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("队列为空,无法获取数据!");
|
||||
}
|
||||
|
||||
return arr[front];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.datastructure.stack;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-04-15 22:18.
|
||||
*/
|
||||
public class LinkedListStackDemo {
|
||||
public static void main(String[] args) {
|
||||
LinkedListStack2 stack = new LinkedListStack2(4);
|
||||
String key;
|
||||
boolean loop = true; //控制是否退出菜单
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
|
||||
while (loop) {
|
||||
System.out.println("show: 表示显示栈");
|
||||
System.out.println("exit: 退出程序");
|
||||
System.out.println("push: 表示添加数据到栈(入栈)");
|
||||
System.out.println("pop: 表示从栈取出数据(出栈)");
|
||||
System.out.println("请输入你的选择");
|
||||
key = scanner.next();
|
||||
switch (key) {
|
||||
case "show":
|
||||
stack.list();
|
||||
break;
|
||||
case "push":
|
||||
System.out.println("请输入一个数");
|
||||
int value = scanner.nextInt();
|
||||
stack.push(value);
|
||||
break;
|
||||
case "pop":
|
||||
try {
|
||||
int res = stack.pop();
|
||||
System.out.printf("出栈的数据是 %d\n", res);
|
||||
} catch (Exception e) {
|
||||
// TODO: handle exception
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
break;
|
||||
case "exit":
|
||||
scanner.close();
|
||||
loop = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("程序退出~~~");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 栈顶是链表的最后一个节点
|
||||
*/
|
||||
class LinkedListStack {
|
||||
private final int maxSize;
|
||||
private int top = -1;
|
||||
private final Node head = new Node(0);
|
||||
|
||||
public LinkedListStack(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return maxSize == top + 1;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return top == -1;
|
||||
}
|
||||
|
||||
public void push(int value) {
|
||||
if (isFull()) {
|
||||
System.out.println("栈满");
|
||||
return;
|
||||
}
|
||||
Node temp = head;
|
||||
while (true) {
|
||||
if (temp.next == null) {
|
||||
temp.next = new Node(value);
|
||||
top++;
|
||||
break;
|
||||
}
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public int pop() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("栈空");
|
||||
}
|
||||
|
||||
Node temp = head;
|
||||
while (true) {
|
||||
// if (temp.next == null) {
|
||||
// throw new RuntimeException("栈空~~~");
|
||||
// }
|
||||
if (temp.next.next == null) {
|
||||
top--;
|
||||
int id = temp.next.id;
|
||||
temp.next = null;
|
||||
return id;
|
||||
}
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
|
||||
public void list() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("栈空");
|
||||
return;
|
||||
}
|
||||
|
||||
revert();
|
||||
|
||||
Node temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
|
||||
revert();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 反转单向链表
|
||||
*/
|
||||
private void revert() {
|
||||
Node pre = null;
|
||||
Node cur = head.next;
|
||||
while (cur != null) {
|
||||
Node next = cur.next;
|
||||
cur.next = pre;
|
||||
pre = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
head.next = pre;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 栈底是链表的最后一个节点
|
||||
*/
|
||||
class LinkedListStack2 {
|
||||
private final Node head = new Node(0);
|
||||
private final int maxSize;
|
||||
private int top = -1;
|
||||
|
||||
public LinkedListStack2(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return top == -1;
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return top == maxSize - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 入栈:插入新元素到链表第一个节点
|
||||
*/
|
||||
public void push(int id) {
|
||||
if (isFull()) {
|
||||
System.out.println("栈满");
|
||||
return;
|
||||
}
|
||||
Node newNode = new Node(id);
|
||||
|
||||
Node temp = head.next;
|
||||
head.next = newNode;
|
||||
newNode.next = temp;
|
||||
top++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 出栈:取出链表第一个元素
|
||||
*/
|
||||
public int pop() {
|
||||
if (isEmpty()) {
|
||||
throw new RuntimeException("栈空,无法取出数据");
|
||||
}
|
||||
|
||||
Node temp = head.next;
|
||||
|
||||
head.next = temp.next;
|
||||
top--;
|
||||
|
||||
return temp.id;
|
||||
}
|
||||
|
||||
public void list() {
|
||||
if (isEmpty()) {
|
||||
System.out.println("栈空,无数据");
|
||||
}
|
||||
|
||||
Node temp = head.next;
|
||||
while (temp != null) {
|
||||
System.out.println(temp);
|
||||
|
||||
temp = temp.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Node {
|
||||
public int id;
|
||||
public Node next;
|
||||
|
||||
public Node(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node{" + id + "}";
|
||||
}
|
||||
}
|
||||
@@ -24,17 +24,15 @@
|
||||
|
||||
package io.github.ehlxr;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* Created by ehlxr on 2016/12/23.
|
||||
*/
|
||||
public class dfd {
|
||||
|
||||
public static void main(String[] args) {
|
||||
var map = Maps.newHashMap();
|
||||
map.put("d", 1);
|
||||
System.out.println(map);
|
||||
// var map = Maps.newHashMap();
|
||||
// map.put("d", 1);
|
||||
// System.out.println(map);
|
||||
}
|
||||
|
||||
public void printCircle(int[][] matrix, int startX, int startY, int endX, int endY) {
|
||||
|
||||
@@ -24,18 +24,12 @@
|
||||
|
||||
package io.github.ehlxr.http;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.file.Paths;
|
||||
// import java.net.http.HttpClient;
|
||||
// import java.net.http.HttpRequest;
|
||||
// import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
@@ -44,34 +38,34 @@ import java.util.concurrent.CompletableFuture;
|
||||
public class Main {
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
|
||||
HttpClient client = HttpClient.newBuilder()
|
||||
.version(HttpClient.Version.HTTP_1_1)
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.connectTimeout(Duration.ofSeconds(20))
|
||||
// .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
|
||||
// .authenticator(Authenticator.getDefault())
|
||||
.build();
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create("https://ehlxr.me/"))
|
||||
.timeout(Duration.ofMinutes(2))
|
||||
.header("Content-Type", "application/json")
|
||||
.GET()
|
||||
// .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("file.json")))
|
||||
.build();
|
||||
|
||||
// Synchronous Example
|
||||
// HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
// System.out.println(response.statusCode());
|
||||
// System.out.println(response.body());
|
||||
|
||||
|
||||
// Asynchronous Example
|
||||
|
||||
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
|
||||
.thenApply(HttpResponse::body)
|
||||
.thenAccept(body -> System.out.println("response body is:\n" + body))
|
||||
.join();
|
||||
// HttpClient client = HttpClient.newBuilder()
|
||||
// .version(HttpClient.Version.HTTP_1_1)
|
||||
// .followRedirects(HttpClient.Redirect.NORMAL)
|
||||
// .connectTimeout(Duration.ofSeconds(20))
|
||||
// // .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
|
||||
// // .authenticator(Authenticator.getDefault())
|
||||
// .build();
|
||||
//
|
||||
// HttpRequest request = HttpRequest.newBuilder()
|
||||
// .uri(URI.create("https://ehlxr.me/"))
|
||||
// .timeout(Duration.ofMinutes(2))
|
||||
// .header("Content-Type", "application/json")
|
||||
// .GET()
|
||||
// // .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("file.json")))
|
||||
// .build();
|
||||
//
|
||||
// // Synchronous Example
|
||||
// // HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
// // System.out.println(response.statusCode());
|
||||
// // System.out.println(response.body());
|
||||
//
|
||||
//
|
||||
// // Asynchronous Example
|
||||
//
|
||||
// client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
|
||||
// .thenApply(HttpResponse::body)
|
||||
// .thenAccept(body -> System.out.println("response body is:\n" + body))
|
||||
// .join();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.jvm.stack;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-07-11 15:19.
|
||||
*/
|
||||
public class ReturnAddressTest {
|
||||
|
||||
public void methodA() {
|
||||
int k = 10;
|
||||
int l = 20;
|
||||
|
||||
methodB();
|
||||
}
|
||||
|
||||
public void methodB() {
|
||||
int i = 10;
|
||||
int j = 20;
|
||||
|
||||
int a = i + j;
|
||||
}
|
||||
|
||||
}
|
||||
127
src/main/java/io/github/ehlxr/rate/SlideWindow.java
Normal file
127
src/main/java/io/github/ehlxr/rate/SlideWindow.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.rate;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* 滑动时间窗口限流工具
|
||||
* 参考:https://www.cnblogs.com/dijia478/p/13807826.html#!comments
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-07-15 22:04.
|
||||
*/
|
||||
public class SlideWindow {
|
||||
/**
|
||||
* 限制次数
|
||||
*/
|
||||
private final int count;
|
||||
|
||||
/**
|
||||
* 时间窗口大小(毫秒)
|
||||
*/
|
||||
private final long timeWindow;
|
||||
|
||||
/**
|
||||
* 限流队列
|
||||
*/
|
||||
private final List<Long> list;
|
||||
|
||||
public SlideWindow(int count, long timeWindow) {
|
||||
this.count = count;
|
||||
this.timeWindow = timeWindow;
|
||||
|
||||
list = new LinkedList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 滑动时间窗口限流算法
|
||||
* 在指定时间窗口,指定限制次数内,是否允许通过
|
||||
*
|
||||
* @return 是否允许通过
|
||||
*/
|
||||
public synchronized boolean acquire() {
|
||||
// 获取当前时间
|
||||
long nowTime = System.currentTimeMillis();
|
||||
// 如果队列还没满,则允许通过,并添加当前时间戳到队列开始位置
|
||||
if (list.size() < count) {
|
||||
// 把之前这个位置的数据给依次向后移动
|
||||
list.add(0, nowTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 队列已满(达到限制次数),则获取队列中最早添加的时间戳
|
||||
// 用当前时间戳 减去 最早添加的时间戳
|
||||
if (nowTime - list.get(count - 1) <= timeWindow) {
|
||||
// 若结果小于等于timeWindow,则说明在timeWindow内,通过的次数大于count
|
||||
// 不允许通过
|
||||
return false;
|
||||
} else {
|
||||
// 若结果大于timeWindow,则说明在timeWindow内,通过的次数小于等于count
|
||||
// 允许通过,并删除最早添加的时间戳,将当前时间添加到队列开始位置
|
||||
list.remove(count - 1);
|
||||
list.add(0, nowTime);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 等待直到获得允许
|
||||
*/
|
||||
public synchronized void tryAcquire(long timeout, TimeUnit unit) throws Exception {
|
||||
if (!acquire()) {
|
||||
long microsToWait = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis() - list.get(count - 1));
|
||||
if (unit.toMicros(timeout) < microsToWait) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
// 等待
|
||||
TimeUnit.MICROSECONDS.sleep(microsToWait);
|
||||
acquire();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SlideWindow slideWindow = new SlideWindow(5, 1000);
|
||||
|
||||
while (true) {
|
||||
// 任意1秒内,只允许5次通过
|
||||
// if (slideWindow.acquire()) {
|
||||
// System.out.println(System.currentTimeMillis());
|
||||
// }
|
||||
slideWindow.tryAcquire(2, TimeUnit.SECONDS);
|
||||
|
||||
System.out.println(System.currentTimeMillis());
|
||||
|
||||
// 睡眠0-10ms
|
||||
Thread.sleep(new Random().nextInt(10));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
package io.github.ehlxr.redis;
|
||||
|
||||
import io.github.ehlxr.SerializeUtil;
|
||||
import org.springframework.util.StringUtils;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
@@ -83,8 +84,8 @@ public class JedisUtil {
|
||||
* 回收jedis
|
||||
*/
|
||||
public static void returnJedis(Jedis jedis) {
|
||||
if (jedis != null)
|
||||
jedisPool.returnResource(jedis);
|
||||
// if (jedis != null)
|
||||
// jedisPool.returnResource(jedis);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
72
src/main/java/io/github/ehlxr/redis/Main.java
Normal file
72
src/main/java/io/github/ehlxr/redis/Main.java
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.redis;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-08-29 12:18.
|
||||
*/
|
||||
@Component
|
||||
public class Main implements ApplicationListener<ContextRefreshedEvent> {
|
||||
private static final Logger log = LoggerFactory.getLogger(Main.class);
|
||||
@Autowired
|
||||
@Qualifier("lettuceDAOImpl")
|
||||
private RedisDAO redisDAO;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
Runnable runnable = () -> {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
log.info("{} retry lock...", Thread.currentThread().getName());
|
||||
Boolean lock = redisDAO.getDistributedLock("lock", uuid, 30_000);
|
||||
if (lock) {
|
||||
log.info("{} get lock!", Thread.currentThread().getName());
|
||||
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
// ...
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
Boolean locak = redisDAO.releaseDistributedLock("lock", uuid);
|
||||
log.info("{} release lock {}", Thread.currentThread().getName(), locak);
|
||||
}
|
||||
}
|
||||
};
|
||||
new Thread(runnable, "t1").start();
|
||||
new Thread(runnable, "t2").start();
|
||||
}
|
||||
}
|
||||
116
src/main/java/io/github/ehlxr/redis/RedisDAO.java
Normal file
116
src/main/java/io/github/ehlxr/redis/RedisDAO.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.redis;
|
||||
|
||||
/**
|
||||
* redis lock/滑动时间窗口限流
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-07-15 22:42.
|
||||
*/
|
||||
public interface RedisDAO {
|
||||
|
||||
/**
|
||||
* 释放分布式锁时使用的 lua 脚本,保证原子性
|
||||
* <p>
|
||||
* if (redis.call('get', KEYS[1]) == ARGV[1])
|
||||
* then
|
||||
* return redis.call('del', KEYS[1])
|
||||
* else
|
||||
* return 0
|
||||
* end
|
||||
*/
|
||||
String RELEASE_LOCK_LUA = "if (redis.call('get', KEYS[1]) == ARGV[1]) then return redis.call('del', KEYS[1]) else return 0 end";
|
||||
|
||||
/**
|
||||
* 滑动窗口限流使用的 lua 脚本,保证原子性
|
||||
* <p>
|
||||
* local key = KEYS[1];
|
||||
* local index = tonumber(ARGV[1]);
|
||||
* local time_window = tonumber(ARGV[2]);
|
||||
* local now_time = tonumber(ARGV[3]);
|
||||
* local far_time = redis.call('lindex', key, index);
|
||||
* if (not far_time)
|
||||
* then
|
||||
* redis.call('lpush', key, now_time);
|
||||
* redis.call('pexpire', key, time_window+1000);
|
||||
* return 1;
|
||||
* end
|
||||
* if (now_time - far_time > time_window)
|
||||
* then
|
||||
* redis.call('rpop', key);
|
||||
* redis.call('lpush', key, now_time);
|
||||
* redis.call('pexpire', key, time_window+1000);
|
||||
* return 1;
|
||||
* else
|
||||
* return 0;
|
||||
* end
|
||||
*/
|
||||
String SLIDE_WINDOW_LUA = "local key = KEYS[1];\n" + "local index = tonumber(ARGV[1]);\n" + "local time_window = tonumber(ARGV[2]);\n" + "local now_time = tonumber(ARGV[3]);\n" + "local far_time = redis.call('lindex', key, index);\n" + "if (not far_time)\n" + "then\n" + " redis.call('lpush', key, now_time);\n" + " redis.call('pexpire', key, time_window+1000);\n" + " return 1;\n" + "end\n" + "\n" + "if (now_time - far_time > time_window)\n" + "then\n" + " redis.call('rpop', key);\n" + " redis.call('lpush', key, now_time);\n" + " redis.call('pexpire', key, time_window+1000);\n" + " return 1;\n" + "else\n" + " return 0;\n" + "end";
|
||||
|
||||
/**
|
||||
* 获取分布式锁
|
||||
*
|
||||
* @param key key
|
||||
* @param value value,需要保证全局唯一,用来删除分布式锁时判断身份使用
|
||||
* @param expireTime 锁过期时间,毫秒,防止业务崩溃未删除锁,导致死锁
|
||||
* @return 是否获取成功锁
|
||||
*/
|
||||
Boolean getDistributedLock(String key, String value, long expireTime);
|
||||
|
||||
/**
|
||||
* 释放分布式锁
|
||||
*
|
||||
* @param key key
|
||||
* @param value value,需要和获取锁时传入的一致
|
||||
* @return 是否释放成功锁
|
||||
*/
|
||||
Boolean releaseDistributedLock(String key, String value);
|
||||
|
||||
/**
|
||||
* 分布式限流队列,在时间窗口内(包含该时间点),判断是否达到限流的阀值
|
||||
* 本接口实现的方法通过加锁避免并发问题,性能不高。只是为了说明限流逻辑如何实现
|
||||
*
|
||||
* @param key key
|
||||
* @param count 限流阀值
|
||||
* @param timeWindow 限流时间窗口
|
||||
* @return 是否允许通过(通过即不进行限流)
|
||||
*/
|
||||
Boolean slideWindow(String key, int count, long timeWindow);
|
||||
|
||||
/**
|
||||
* 分布式限流队列,在时间窗口内(包含该时间点),判断是否达到限流的阀值
|
||||
* 本接口实现的方法通过 Lua 脚本避免并发问题,性能较高。
|
||||
*
|
||||
* @param key key
|
||||
* @param count 限流阀值
|
||||
* @param timeWindow 限流时间窗口
|
||||
* @return 是否允许通过(通过即不进行限流)
|
||||
*/
|
||||
Boolean slideWindowLua(String key, int count, long timeWindow);
|
||||
|
||||
}
|
||||
|
||||
|
||||
31
src/main/java/io/github/ehlxr/redis/RedisTemplateConfig.java
Normal file
31
src/main/java/io/github/ehlxr/redis/RedisTemplateConfig.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package io.github.ehlxr.redis;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisTemplateConfig {
|
||||
@Bean(name = "redisTemplate")
|
||||
public RedisTemplate<String, String> getRedisTemplate(RedisConnectionFactory factory) {
|
||||
return buildRedisTemplateByString(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 redisTemplate 使用 string序列化
|
||||
*/
|
||||
public RedisTemplate<String, String> buildRedisTemplateByString(RedisConnectionFactory factory) {
|
||||
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(factory);
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(new StringRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
129
src/main/java/io/github/ehlxr/redis/impl/JedisDAOImpl.java
Normal file
129
src/main/java/io/github/ehlxr/redis/impl/JedisDAOImpl.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.redis.impl;
|
||||
|
||||
import io.github.ehlxr.redis.RedisDAO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import redis.clients.jedis.JedisCluster;
|
||||
import redis.clients.jedis.params.SetParams;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* redis lock/滑动时间窗口限流
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-07-15 22:44.
|
||||
*/
|
||||
// @Component("jedisDAOImpl")
|
||||
public class JedisDAOImpl implements RedisDAO {
|
||||
private final Logger log = LoggerFactory.getLogger(JedisDAOImpl.class);
|
||||
|
||||
// @Autowired
|
||||
private JedisCluster jc;
|
||||
|
||||
@Override
|
||||
public Boolean getDistributedLock(String key, String value, long expireTime) {
|
||||
String set = null;
|
||||
try {
|
||||
set = jc.set(key, value, SetParams.setParams().nx().px(expireTime));
|
||||
log.debug("getLock redis key: {}, value: {}, expireTime: {}, result: {}", key, value, expireTime, set);
|
||||
} catch (Exception e) {
|
||||
log.error("getLock redis key: {}, value: {}, expireTime: {}", key, value, expireTime, e);
|
||||
}
|
||||
return "OK".equals(set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean releaseDistributedLock(String key, String value) {
|
||||
Object eval = null;
|
||||
try {
|
||||
eval = jc.eval(RELEASE_LOCK_LUA, Collections.singletonList(key), Collections.singletonList(value));
|
||||
log.debug("releaseLock redis key: {}, value: {}, result: {}", key, value, eval);
|
||||
} catch (Exception e) {
|
||||
log.error("releaseLock redis key: {}, value: {}", key, value, e);
|
||||
}
|
||||
return Long.valueOf(1L).equals(eval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Boolean slideWindow(String key, int count, long timeWindow) {
|
||||
if (count <= 0 || timeWindow <= 0) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
// 获取当前时间
|
||||
long nowTime = System.currentTimeMillis();
|
||||
// 获取队列中,达到限流数量的位置,存储的时间戳
|
||||
String farTime = jc.lindex(key, count - 1);
|
||||
// 如果为空,说明限流队列还没满,则允许通过,并添加当前时间戳到队列开始位置
|
||||
if (farTime == null) {
|
||||
jc.lpush(key, String.valueOf(nowTime));
|
||||
// 给限流队列增加过期时间,防止长时间不用导致内存一直占用
|
||||
jc.pexpire(key, timeWindow + 1000L);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 队列已满(达到限制次数),用当前时间戳 减去 最早添加的时间戳
|
||||
if (nowTime - Long.parseLong(farTime) > timeWindow) {
|
||||
// 若结果大于 timeWindow,则说明在 timeWindow 内,通过的次数小于等于 count
|
||||
// 允许通过,并删除最早添加的时间戳,将当前时间添加到队列开始位置
|
||||
jc.rpop(key);
|
||||
jc.lpush(key, String.valueOf(nowTime));
|
||||
// 给限流队列增加过期时间,防止长时间不用导致内存一直占用
|
||||
jc.pexpire(key, timeWindow + 1000L);
|
||||
return true;
|
||||
}
|
||||
// 若结果小于等于 timeWindow,则说明在 timeWindow 内,通过的次数大于 count
|
||||
// 不允许通过
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
log.error("[logId:{}]", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean slideWindowLua(String key, int count, long timeWindow) {
|
||||
if (count <= 0 || timeWindow <= 0) {
|
||||
return false;
|
||||
}
|
||||
Object eval = null;
|
||||
try {
|
||||
List<String> argvList = new ArrayList<>();
|
||||
argvList.add(String.valueOf(count - 1));
|
||||
argvList.add(String.valueOf(timeWindow));
|
||||
argvList.add(String.valueOf(System.currentTimeMillis()));
|
||||
eval = jc.eval(SLIDE_WINDOW_LUA, Collections.singletonList(key), argvList);
|
||||
log.debug("slideWindowLua redis key: {}, count: {}, timeWindow: {}, result: {}", key, count, timeWindow, eval);
|
||||
} catch (Exception e) {
|
||||
log.error("slideWindowLua redis key: {}, count: {}, timeWindow: {}", key, count, timeWindow, e);
|
||||
}
|
||||
return Long.valueOf(1L).equals(eval);
|
||||
}
|
||||
}
|
||||
116
src/main/java/io/github/ehlxr/redis/impl/LettuceDAOImpl.java
Normal file
116
src/main/java/io/github/ehlxr/redis/impl/LettuceDAOImpl.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2020 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.redis.impl;
|
||||
|
||||
import io.github.ehlxr.redis.RedisDAO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.ListOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.data.redis.core.script.RedisScript;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-07-15 22:51.
|
||||
*/
|
||||
@Component("lettuceDAOImpl")
|
||||
public class LettuceDAOImpl implements RedisDAO {
|
||||
private static final Logger log = LoggerFactory.getLogger(LettuceDAOImpl.class);
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Override
|
||||
public Boolean getDistributedLock(String key, String value, long expireTime) {
|
||||
Boolean set = false;
|
||||
try {
|
||||
set = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS);
|
||||
log.info("getLock redis key: {}, value: {}, expireTime: {}, result: {}", key, value, expireTime, set);
|
||||
} catch (Exception e) {
|
||||
log.error("getLock redis key: {}, value: {}, expireTime: {}", key, value, expireTime, e);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean releaseDistributedLock(String key, String value) {
|
||||
Long execute = null;
|
||||
try {
|
||||
RedisScript<Long> redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA, Long.class);
|
||||
execute = redisTemplate.execute(redisScript, Collections.singletonList(key), value);
|
||||
log.debug("releaseLock redis key: {}, value: {}, result: {}", key, value, execute);
|
||||
} catch (Exception e) {
|
||||
log.error("releaseLock redis key: {}, value: {}", key, value, e);
|
||||
}
|
||||
return Long.valueOf(1L).equals(execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Boolean slideWindow(String key, int count, long timeWindow) {
|
||||
try {
|
||||
long nowTime = System.currentTimeMillis();
|
||||
ListOperations<String, String> list = redisTemplate.opsForList();
|
||||
String farTime = list.index(key, count - 1);
|
||||
if (farTime == null) {
|
||||
list.leftPush(key, String.valueOf(nowTime));
|
||||
redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
|
||||
return true;
|
||||
}
|
||||
if (nowTime - Long.parseLong(farTime) > timeWindow) {
|
||||
list.rightPop(key);
|
||||
list.leftPush(key, String.valueOf(nowTime));
|
||||
redisTemplate.expire(key, timeWindow + 1000L, TimeUnit.MILLISECONDS);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean slideWindowLua(String key, int count, long timeWindow) {
|
||||
if (count <= 0 || timeWindow <= 0) {
|
||||
return false;
|
||||
}
|
||||
Long execute = null;
|
||||
try {
|
||||
RedisScript<Long> redisScript = new DefaultRedisScript<>(SLIDE_WINDOW_LUA, Long.class);
|
||||
execute = redisTemplate.execute(redisScript, Collections.singletonList(key), String.valueOf(count - 1), String.valueOf(timeWindow), String.valueOf(System.currentTimeMillis()));
|
||||
log.debug("slideWindowLua redis key: {}, count: {}, timeWindow: {}, result: {}", key, count, timeWindow, execute);
|
||||
} catch (Exception e) {
|
||||
log.error("slideWindowLua redis key: {}, count: {}, timeWindow: {}", key, count, timeWindow, e);
|
||||
}
|
||||
return Long.valueOf(1L).equals(execute);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
package io.github.ehlxr.sort;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 冒泡排序
|
||||
* <p>
|
||||
@@ -33,6 +31,7 @@ import java.util.Arrays;
|
||||
* 下一次继续这个过程,直到所有数据元素都排好序。
|
||||
* <p>
|
||||
* 算法的核心在于每次通过两两比较交换位置,选出剩余无序序列里最大(小)的数据元素放到队尾。
|
||||
* 时间复杂度:O(n²)
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2020-10-01 16:40.
|
||||
@@ -50,13 +49,18 @@ public class BubbleSort {
|
||||
//外层:需要 length-1 次循环比较
|
||||
for (int i = 0; i < arr.length - 1; i++) {
|
||||
|
||||
boolean flag = false;
|
||||
//内层:每次循环需要两两比较的次数,每次比较后,都会将当前最大的数放到最后位置,所以每次比较次数递减一次
|
||||
for (int j = 0; j < arr.length - 1 - i; j++) {
|
||||
if (arr[j] > arr[j + 1]) {
|
||||
flag = true;
|
||||
swap(arr, j, j + 1);
|
||||
}
|
||||
}
|
||||
System.out.println("Sorting: " + Arrays.toString(arr));
|
||||
// System.out.println("Sorting: " + Arrays.toString(arr));
|
||||
if (!flag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +75,13 @@ public class BubbleSort {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
sort(new int[]{4, 9, 1, 6, 8, 2});
|
||||
int[] arr = new int[80000];
|
||||
for (int i = 0; i < 80000; i++) {
|
||||
arr[i] = (int) (Math.random() * 8000000); //生成一个[0, 8000000) 数
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
sort(arr);
|
||||
System.out.printf("排序花费时间 %dms.", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
package io.github.ehlxr.sort;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 插入排序
|
||||
* <p>
|
||||
@@ -55,7 +53,47 @@ public class InsertSort {
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println(Arrays.toString(arr));
|
||||
// System.out.println("第" + i + "轮:" + Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sort3(int[] arr) {
|
||||
for (int i = 1; i < arr.length; i++) {
|
||||
int j = i - 1; // 已排序的最后一个元素下标
|
||||
int temp = arr[i]; // 下一个元素(待排序元素)
|
||||
for (; j >= 0; j--) {
|
||||
if (temp < arr[j]) {
|
||||
arr[j + 1] = arr[j]; // arr[j] 后移
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j + 1 != i) {
|
||||
arr[j + 1] = temp;
|
||||
}
|
||||
// System.out.println("第" + i + "轮:" + Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sort2(int[] arr) {
|
||||
for (int i = 1; i < arr.length; i++) {
|
||||
int temp = arr[i]; // 下一个元素(待排序元素)
|
||||
int j = i - 1; // 已排序的最后一个元素下标
|
||||
while (j >= 0 && arr[j] > temp) {
|
||||
arr[j + 1] = arr[j]; // arr[j] 后移
|
||||
j--;
|
||||
}
|
||||
|
||||
if (j + 1 != i) {
|
||||
arr[j + 1] = temp;
|
||||
}
|
||||
// i=2, temp=1
|
||||
// 4, 9, 1, 8, 6, 2
|
||||
// 4, 9, 9, 8, 6, 2
|
||||
// 4, 4, 9, 8, 6, 2
|
||||
// 1, 4, 9, 8, 6, 2
|
||||
// System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +108,15 @@ public class InsertSort {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
sort(new int[]{4, 9, 1, 8, 6, 2});
|
||||
int[] arr = new int[80_000];
|
||||
for (int i = 0; i < 80_000; i++) {
|
||||
arr[i] = (int) (Math.random() * 8_000_000); //生成一个[0, 8000000) 数
|
||||
}
|
||||
// int[] arr = {4, 9, 1, 8, 6, 2};
|
||||
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
sort3(arr);
|
||||
System.out.printf("排序花费时间 %dms.", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,17 @@ import java.util.Arrays;
|
||||
*/
|
||||
public class MergeSort {
|
||||
public static void main(String[] args) {
|
||||
int[] arr = {4, 9, 1, 8, 6, 2};
|
||||
int[] arr = new int[800_000];
|
||||
for (int i = 0; i < 800_000; i++) {
|
||||
arr[i] = (int) (Math.random() * 80_000_000); //生成一个[0, 8000000) 数
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
sort(arr);
|
||||
System.out.printf("排序花费时间 %dms.", System.currentTimeMillis() - startTime);
|
||||
|
||||
// int[] arr = {4, 9, 1, 8, 6, 2};
|
||||
// merge(new int[]{1, 4, 9}, new int[]{2, 6, 8});
|
||||
System.out.println(Arrays.toString(sort(arr)));
|
||||
// System.out.println(Arrays.toString(sort(arr)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,8 +40,14 @@ import java.util.Arrays;
|
||||
*/
|
||||
public class QuickSort {
|
||||
public static void main(String[] args) {
|
||||
int[] arr = {4, 9, 1, 8, 6, 2};
|
||||
// int[] arr = {4, 9, 1, 8, 6, 2};
|
||||
int[] arr = new int[800_000];
|
||||
for (int i = 0; i < 800_000; i++) {
|
||||
arr[i] = (int) (Math.random() * 80_000_000); //生成一个[0, 8000000) 数
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
sort(arr, 0, arr.length - 1);
|
||||
System.out.printf("排序花费时间 %dms.", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +94,7 @@ public class QuickSort {
|
||||
// 循环以上步骤,直到 l 和 r 相遇
|
||||
}
|
||||
// arr[k] = p;
|
||||
System.out.println("Sorting: " + Arrays.toString(arr));
|
||||
// System.out.println("Sorting: " + Arrays.toString(arr));
|
||||
|
||||
sort(arr, i, k - 1);
|
||||
sort(arr, k + 1, j);
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
package io.github.ehlxr.sort;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 希尔排序
|
||||
* <p>
|
||||
@@ -61,12 +59,40 @@ public class ShellSort {
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(Arrays.toString(arr));
|
||||
// System.out.println(Arrays.toString(arr));
|
||||
|
||||
// 每次将 gap 折半减小,循环上述操作
|
||||
sort(arr, gap / 2);
|
||||
}
|
||||
|
||||
public static void sort2(int[] arr, int gap) {
|
||||
if (arr == null || arr.length <= 0 || gap < 1) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < gap; i++) {
|
||||
// 对按照 gap 进行分组的元素进行插入排序
|
||||
for (int j = gap + i; j < arr.length; j += gap) {
|
||||
int k = j - gap;
|
||||
int temp = arr[j];
|
||||
for (; k >= 0; k -= gap) {
|
||||
if (arr[k] > temp) {
|
||||
arr[k + gap] = arr[k];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (k + gap != j) {
|
||||
arr[k + gap] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
// System.out.println(Arrays.toString(arr));
|
||||
|
||||
// 每次将 gap 折半减小,循环上述操作
|
||||
sort2(arr, gap / 2);
|
||||
}
|
||||
|
||||
public static void swap(int[] arr, int i, int j) {
|
||||
int tmp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
@@ -74,9 +100,15 @@ public class ShellSort {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] arr = {4, 9, 1, 8, 6, 2};
|
||||
sort(arr, arr.length / 2);
|
||||
// sort(arr);
|
||||
int[] arr = new int[800_000];
|
||||
for (int i = 0; i < 800_000; i++) {
|
||||
arr[i] = (int) (Math.random() * 80_000_000); //生成一个[0, 8000000) 数
|
||||
}
|
||||
// int[] arr = {4, 9, 1, 8, 6, 2};
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
sort2(arr, arr.length / 2);
|
||||
System.out.printf("排序花费时间 %dms.", System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
// public static void sort(int[] arr) {
|
||||
|
||||
@@ -26,7 +26,6 @@ package io.github.ehlxr.springamq.controller;
|
||||
|
||||
import io.github.ehlxr.springamq.mq.producer.queue.QueueSender;
|
||||
import io.github.ehlxr.springamq.mq.producer.topic.TopicSender;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@@ -37,8 +36,8 @@ import javax.annotation.Resource;
|
||||
/**
|
||||
* @description controller测试
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/activemq")
|
||||
// @Controller
|
||||
// @RequestMapping("/activemq")
|
||||
public class ActivemqController {
|
||||
|
||||
@Resource
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
package io.github.ehlxr.springamq.mq.consumer.queue;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageListener;
|
||||
@@ -35,7 +33,7 @@ import javax.jms.TextMessage;
|
||||
/**
|
||||
* @description 队列消息监听器
|
||||
*/
|
||||
@Component
|
||||
// @Component
|
||||
public class QueueReceiver1 implements MessageListener {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
package io.github.ehlxr.springamq.mq.consumer.queue;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageListener;
|
||||
@@ -35,7 +33,7 @@ import javax.jms.TextMessage;
|
||||
/**
|
||||
* @description 队列消息监听器
|
||||
*/
|
||||
@Component
|
||||
// @Component
|
||||
public class QueueReceiver2 implements MessageListener {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
package io.github.ehlxr.springamq.mq.consumer.topic;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageListener;
|
||||
@@ -34,7 +32,7 @@ import javax.jms.TextMessage;
|
||||
/**
|
||||
* @description Topic消息监听器
|
||||
*/
|
||||
@Component
|
||||
// @Component
|
||||
public class TopicReceiver1 implements MessageListener{
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
package io.github.ehlxr.springamq.mq.consumer.topic;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageListener;
|
||||
@@ -34,7 +32,7 @@ import javax.jms.TextMessage;
|
||||
/**
|
||||
* @description Topic消息监听器
|
||||
*/
|
||||
@Component
|
||||
// @Component
|
||||
public class TopicReceiver2 implements MessageListener{
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,24 +24,21 @@
|
||||
|
||||
package io.github.ehlxr.springamq.mq.producer.queue;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.core.MessageCreator;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Session;
|
||||
|
||||
/**
|
||||
* @description 队列消息生产者,发送消息到队列
|
||||
* @description 队列消息生产者,发送消息到队列
|
||||
*/
|
||||
@Component("queueSender")
|
||||
// @Component("queueSender")
|
||||
public class QueueSender {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("jmsQueueTemplate")
|
||||
// @Autowired
|
||||
// @Qualifier("jmsQueueTemplate")
|
||||
private JmsTemplate jmsTemplate;//通过@Qualifier修饰符来注入对应的bean
|
||||
|
||||
/**
|
||||
@@ -49,7 +46,7 @@ public class QueueSender {
|
||||
* @param queueName 队列名称
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public void send(String queueName,final String message){
|
||||
public void send(String queueName, final String message) {
|
||||
jmsTemplate.send(queueName, new MessageCreator() {
|
||||
@Override
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
|
||||
@@ -24,11 +24,8 @@
|
||||
|
||||
package io.github.ehlxr.springamq.mq.producer.topic;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.core.MessageCreator;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
@@ -38,11 +35,11 @@ import javax.jms.Session;
|
||||
* @description Topic生产者发送消息到Topic
|
||||
*/
|
||||
|
||||
@Component("topicSender")
|
||||
// @Component("topicSender")
|
||||
public class TopicSender {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("jmsTopicTemplate")
|
||||
// @Autowired
|
||||
// @Qualifier("jmsTopicTemplate")
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
/**
|
||||
|
||||
57
src/main/java/io/github/ehlxr/test/OOMTest.java
Normal file
57
src/main/java/io/github/ehlxr/test/OOMTest.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* -Xms600m -Xmx600m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
|
||||
* -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/ehlxr/Downloads/hprof/1.hprof
|
||||
*
|
||||
* @author ehlxr
|
||||
* @since 2021-08-08 21:26.
|
||||
*/
|
||||
public class OOMTest {
|
||||
public static void main(String[] args) {
|
||||
ArrayList<Picture> list = new ArrayList<>();
|
||||
while (true) {
|
||||
try {
|
||||
Thread.sleep(5);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
list.add(new Picture(new Random().nextInt(100 * 50)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Picture {
|
||||
private final byte[] pixels;
|
||||
|
||||
public Picture(int length) {
|
||||
this.pixels = new byte[length];
|
||||
}
|
||||
}
|
||||
111
src/main/java/io/github/ehlxr/test/StudentTrace.java
Normal file
111
src/main/java/io/github/ehlxr/test/StudentTrace.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package io.github.ehlxr.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 有一个学生浏览网页的记录程序,它将记录 每个学生访问过的网站地址。
|
||||
* 它由三个部分组成:Student、WebPage和StudentTrace三个类
|
||||
* <p>
|
||||
* -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath=/Users/ehlxr/Downloads/hprof/student.hprof
|
||||
*
|
||||
* @author shkstart
|
||||
* @create 16:11
|
||||
*/
|
||||
public class StudentTrace {
|
||||
static List<WebPage> webpages = new ArrayList<>();
|
||||
|
||||
|
||||
public static void createWebPages() {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
WebPage wp = new WebPage();
|
||||
wp.setUrl("http://www." + i + ".com");
|
||||
wp.setContent(Integer.toString(i));
|
||||
webpages.add(wp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
createWebPages();//创建了100个网页
|
||||
//创建3个学生对象
|
||||
Student st3 = new Student(3, "Tom");
|
||||
Student st5 = new Student(5, "Jerry");
|
||||
Student st7 = new Student(7, "Lily");
|
||||
|
||||
for (int i = 0; i < webpages.size(); i++) {
|
||||
if (i % st3.getId() == 0)
|
||||
st3.visit(webpages.get(i));
|
||||
if (i % st5.getId() == 0)
|
||||
st5.visit(webpages.get(i));
|
||||
if (i % st7.getId() == 0)
|
||||
st7.visit(webpages.get(i));
|
||||
}
|
||||
webpages.clear();
|
||||
System.gc();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class Student {
|
||||
private int id;
|
||||
private String name;
|
||||
private List<WebPage> history = new ArrayList<>();
|
||||
|
||||
public Student(int id, String name) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<WebPage> getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
public void setHistory(List<WebPage> history) {
|
||||
this.history = history;
|
||||
}
|
||||
|
||||
public void visit(WebPage wp) {
|
||||
if (wp != null) {
|
||||
history.add(wp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WebPage {
|
||||
private String url;
|
||||
private String content;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
package io.github.ehlxr.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -34,7 +35,7 @@ import java.util.stream.Collectors;
|
||||
* Created by ehlxr on 2016/12/15.
|
||||
*/
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws IOException {
|
||||
// String s0 = "kvill";
|
||||
// String s1 = "kvill";
|
||||
// String s2 = "kvill";
|
||||
@@ -84,5 +85,7 @@ public class Test {
|
||||
System.out.println(s1 == s2);
|
||||
System.out.println(s == t); // false
|
||||
System.out.println(s.intern() == t.intern()); // true
|
||||
|
||||
System.in.read();
|
||||
}
|
||||
}
|
||||
|
||||
50
src/main/java/io/github/ehlxr/test/TestString.java
Normal file
50
src/main/java/io/github/ehlxr/test/TestString.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2021 xrv <xrg@live.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package io.github.ehlxr.test;
|
||||
|
||||
/**
|
||||
* @author ehlxr
|
||||
* @since 2021-05-14 16:17.
|
||||
*/
|
||||
public class TestString {
|
||||
public static void main(String[] args) {
|
||||
String s1 = "abc";
|
||||
String s2 = "ab";
|
||||
String s3 = s2 + "c";
|
||||
System.out.println(s1 == s3);//false
|
||||
|
||||
String s4 = s3.intern();
|
||||
System.out.println(s1 == s3);//false
|
||||
System.out.println(s1 == s4);//true
|
||||
|
||||
String s5 = "abc";
|
||||
System.out.println(s1 == s5);//true
|
||||
|
||||
String s6 = new String("abc");
|
||||
String s7 = new String("abc");
|
||||
System.out.println(s6 == s7);//false
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,68 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
|
||||
xmlns:jms="http://www.springframework.org/schema/jms"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-4.0.xsd
|
||||
http://www.springframework.org/schema/jms
|
||||
http://www.springframework.org/schema/jms/spring-jms-4.0.xsd
|
||||
http://activemq.apache.org/schema/core
|
||||
http://activemq.apache.org/schema/core/activemq-core-5.8.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
|
||||
|
||||
<!-- ActiveMQ 连接工厂 -->
|
||||
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
|
||||
<!-- 如果连接网络:tcp://ip:61616;未连接网络:tcp://localhost:61616 以及用户名,密码-->
|
||||
<amq:connectionFactory id="amqConnectionFactory"
|
||||
brokerURL="tcp://192.168.1.251:61616" userName="admin" password="admin" />
|
||||
<!--<!– ActiveMQ 连接工厂 –>-->
|
||||
<!--<!– 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供–>-->
|
||||
<!--<!– 如果连接网络:tcp://ip:61616;未连接网络:tcp://localhost:61616 以及用户名,密码–>-->
|
||||
<!--<amq:connectionFactory id="amqConnectionFactory"-->
|
||||
<!-- brokerURL="tcp://192.168.1.251:61616" userName="admin" password="admin" />-->
|
||||
|
||||
<!-- Spring Caching连接工厂 -->
|
||||
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
|
||||
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
|
||||
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
|
||||
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
|
||||
<!-- 同上,同理 -->
|
||||
<!-- <constructor-arg ref="amqConnectionFactory" /> -->
|
||||
<!-- Session缓存数量 -->
|
||||
<property name="sessionCacheSize" value="100" />
|
||||
</bean>
|
||||
<!--<!– Spring Caching连接工厂 –>-->
|
||||
<!--<!– Spring用于管理真正的ConnectionFactory的ConnectionFactory –> -->
|
||||
<!--<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">-->
|
||||
<!-- <!– 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory –> -->
|
||||
<!-- <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>-->
|
||||
<!-- <!– 同上,同理 –>-->
|
||||
<!-- <!– <constructor-arg ref="amqConnectionFactory" /> –>-->
|
||||
<!-- <!– Session缓存数量 –>-->
|
||||
<!-- <property name="sessionCacheSize" value="100" />-->
|
||||
<!--</bean>-->
|
||||
|
||||
<!-- Spring JmsTemplate 的消息生产者 start-->
|
||||
<!--<!– Spring JmsTemplate 的消息生产者 start–>-->
|
||||
|
||||
<!-- 定义JmsTemplate的Queue类型 -->
|
||||
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
|
||||
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
|
||||
<constructor-arg ref="connectionFactory" />
|
||||
<!-- 非pub/sub模型(发布/订阅),即队列模式 -->
|
||||
<property name="pubSubDomain" value="false" />
|
||||
</bean>
|
||||
<!--<!– 定义JmsTemplate的Queue类型 –>-->
|
||||
<!--<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">-->
|
||||
<!-- <!– 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 –> -->
|
||||
<!-- <constructor-arg ref="connectionFactory" />-->
|
||||
<!-- <!– 非pub/sub模型(发布/订阅),即队列模式 –>-->
|
||||
<!-- <property name="pubSubDomain" value="false" />-->
|
||||
<!--</bean>-->
|
||||
|
||||
<!-- 定义JmsTemplate的Topic类型 -->
|
||||
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
|
||||
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
|
||||
<constructor-arg ref="connectionFactory" />
|
||||
<!-- pub/sub模型(发布/订阅) -->
|
||||
<property name="pubSubDomain" value="true" />
|
||||
</bean>
|
||||
<!--<!– 定义JmsTemplate的Topic类型 –>-->
|
||||
<!--<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">-->
|
||||
<!-- <!– 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 –> -->
|
||||
<!-- <constructor-arg ref="connectionFactory" />-->
|
||||
<!-- <!– pub/sub模型(发布/订阅) –>-->
|
||||
<!-- <property name="pubSubDomain" value="true" />-->
|
||||
<!--</bean>-->
|
||||
|
||||
<!--Spring JmsTemplate 的消息生产者 end-->
|
||||
<!--<!–Spring JmsTemplate 的消息生产者 end–>-->
|
||||
|
||||
|
||||
<!-- 消息消费者 start-->
|
||||
<!--<!– 消息消费者 start–>-->
|
||||
|
||||
<!-- 定义Queue监听器 -->
|
||||
<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
|
||||
<jms:listener destination="test.queue" ref="queueReceiver1"/>
|
||||
<jms:listener destination="test.queue" ref="queueReceiver2"/>
|
||||
</jms:listener-container>
|
||||
<!--<!– 定义Queue监听器 –>-->
|
||||
<!--<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">-->
|
||||
<!-- <jms:listener destination="test.queue" ref="queueReceiver1"/>-->
|
||||
<!-- <jms:listener destination="test.queue" ref="queueReceiver2"/>-->
|
||||
<!--</jms:listener-container>-->
|
||||
|
||||
<!-- 定义Topic监听器 -->
|
||||
<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
|
||||
<jms:listener destination="test.topic" ref="topicReceiver1"/>
|
||||
<jms:listener destination="test.topic" ref="topicReceiver2"/>
|
||||
</jms:listener-container>
|
||||
<!--<!– 定义Topic监听器 –>-->
|
||||
<!--<jms:listener-container destination-type="topic" container-type="default" connection-factory="connectionFactory" acknowledge="auto">-->
|
||||
<!-- <jms:listener destination="test.topic" ref="topicReceiver1"/>-->
|
||||
<!-- <jms:listener destination="test.topic" ref="topicReceiver2"/>-->
|
||||
<!--</jms:listener-container>-->
|
||||
|
||||
<!-- 消息消费者 end -->
|
||||
<!--<!– 消息消费者 end –>-->
|
||||
</beans>
|
||||
7
src/main/resources/application-dev.yml
Normal file
7
src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
spring:
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
20
src/main/resources/application.yml
Normal file
20
src/main/resources/application.yml
Normal file
@@ -0,0 +1,20 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: budd
|
||||
|
||||
logging:
|
||||
file:
|
||||
path: /datalog/weblog/${spring.application.name}
|
||||
config: classpath:logback-spring.xml
|
||||
|
||||
server:
|
||||
tomcat:
|
||||
uri-encoding: UTF-8
|
||||
accept-count: 1000
|
||||
connection-timeout: 30000
|
||||
servlet:
|
||||
context-path: /budd
|
||||
session:
|
||||
timeout: 60
|
||||
@@ -1,25 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-4.0.xsd
|
||||
http://activemq.apache.org/schema/core
|
||||
http://activemq.apache.org/schema/core/activemq-core-5.9.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
|
||||
|
||||
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
|
||||
<!--<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>-->
|
||||
|
||||
<!-- 配置扫描路径 -->
|
||||
<context:component-scan base-package="me.ehlxr.springamq">
|
||||
<!-- 只扫描Service,也可以添加Repostory,但是要把Controller排除在外,Controller由spring-mvc.xml去加载 -->
|
||||
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> -->
|
||||
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> -->
|
||||
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> -->
|
||||
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
|
||||
</context:component-scan>
|
||||
<!--<context:component-scan base-package="me.ehlxr.springamq">-->
|
||||
<!-- 只扫描Service,也可以添加Repostory,但是要把Controller排除在外,Controller由spring-mvc.xml去加载 -->
|
||||
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> -->
|
||||
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" /> -->
|
||||
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Component" /> -->
|
||||
<!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
|
||||
<!--</context:component-scan>-->
|
||||
|
||||
</beans>
|
||||
@@ -1,27 +0,0 @@
|
||||
### direct log messages to stdout and logFile###
|
||||
log4j.rootCategory=INFO, stdout,logFile
|
||||
|
||||
# OpenSymphony Stuff
|
||||
log4j.logger.com.opensymphony=INFO
|
||||
log4j.logger.org.apache.struts2=INFO
|
||||
log4j.logger.org.apache.commons=INFO
|
||||
|
||||
# Spring Stuff
|
||||
log4j.logger.org.springframework=INFO
|
||||
log4j.logger.org.springframework.oxm=INFO
|
||||
|
||||
# Hibernate Stuff
|
||||
log4j.logger.org.hibernate=INFO
|
||||
log4j.logger.org.hibernate.type=INFO
|
||||
log4j.logger.org.hibernate.tool.hbm2ddl=INFO
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH\:mm\:ss} [%t] [%c.%M\:%L] %m%n
|
||||
|
||||
#log4j.appender.logFile=org.apache.log4j.RollingFileAppender
|
||||
#log4j.appender.logFile.File=${webapp.root}/logs/amq.log
|
||||
#log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
|
||||
#log4j.appender.logFile.layout.ConversionPattern=[%p] %-d{yyyy-MM-dd HH\:mm\:ss} [%t] [%c.%M\:%L] %m%n
|
||||
#log4j.appender.logFile.MaxFileSize = 5MB
|
||||
#log4j.appender.logFile.MaxBackupIndex =3
|
||||
276
src/main/resources/logback-spring.xml
Normal file
276
src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,276 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
|
||||
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
|
||||
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
|
||||
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
|
||||
<configuration scan="true" scanPeriod="10 seconds">
|
||||
<!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
|
||||
|
||||
<contextName>logback</contextName>
|
||||
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
|
||||
<!-- <property name="LOG_PATH" value="${logging.file.path}" />-->
|
||||
|
||||
<springProperty name="LOG_PATH" source="logging.file.path"/>
|
||||
<!--<springProperty name="ALIYUN_LOG_ENDPOINT" source="aliyun.log.endpoint"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYID" source="aliyun.log.accessKeyId"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_ACCESSKEYSECRET" source="aliyun.log.accessKeySecret"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_PROJECT" source="aliyun.log.project"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_INFO" source="aliyun.log.logstore.info"/>-->
|
||||
<!--<springProperty name="ALIYUN_LOG_LOGSTORE_ERROR" source="aliyun.log.logstore.error"/>-->
|
||||
|
||||
<!-- 彩色日志 -->
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
|
||||
<conversionRule conversionWord="wex"
|
||||
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
|
||||
<conversionRule conversionWord="wEx"
|
||||
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN"
|
||||
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%X{logTraceId}]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!--<property name="CONSOLE_LOG_PATTERN"-->
|
||||
<!-- value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%X{√logTraceId}]){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(at %class.%method){cyan} \\(%file:%line\\) %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>-->
|
||||
|
||||
<!--输出到控制台-->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>debug</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
|
||||
<!-- 设置字符集 -->
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--输出到文件-->
|
||||
<!-- 时间滚动输出 level为 DEBUG 日志 -->
|
||||
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||
<file>${LOG_PATH}/debug.log</file>
|
||||
<!--日志文件输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志归档 -->
|
||||
<fileNamePattern>${LOG_PATH}/debug/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<!--日志文件保留天数-->
|
||||
<maxHistory>15</maxHistory>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文件只记录debug级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>debug</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 时间滚动输出 level为 INFO 日志 -->
|
||||
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||
<file>${LOG_PATH}/info.log</file>
|
||||
<!--日志文件输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 每天日志归档路径以及格式 -->
|
||||
<fileNamePattern>${LOG_PATH}/info/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<!--日志文件保留天数-->
|
||||
<maxHistory>15</maxHistory>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文件只记录info级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>info</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 时间滚动输出 level为 WARN 日志 -->
|
||||
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||
<file>${LOG_PATH}/warn.log</file>
|
||||
<!--日志文件输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_PATH}/warn/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<!--日志文件保留天数-->
|
||||
<maxHistory>15</maxHistory>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文件只记录warn级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>warn</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 时间滚动输出 level为 ERROR 日志 -->
|
||||
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||
<file>${LOG_PATH}/error.log</file>
|
||||
<!--日志文件输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_PATH}/error/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<!--日志文件保留天数-->
|
||||
<maxHistory>15</maxHistory>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文件只记录ERROR级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!--<appender name="ALIYUN_LOG_INFO" class="com.aliyun.openservices.log.logback.LoghubAppender">-->
|
||||
<!-- <endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>-->
|
||||
<!-- <accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>-->
|
||||
<!-- <accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>-->
|
||||
<!-- <project>${ALIYUN_LOG_PROJECT}</project>-->
|
||||
<!-- <logStore>${ALIYUN_LOG_LOGSTORE_INFO}</logStore>-->
|
||||
|
||||
<!-- <totalSizeInBytes>104857600</totalSizeInBytes>-->
|
||||
<!-- <maxBlockMs>0</maxBlockMs>-->
|
||||
<!-- <ioThreadCount>8</ioThreadCount>-->
|
||||
<!-- <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>-->
|
||||
<!-- <batchCountThreshold>4096</batchCountThreshold>-->
|
||||
<!-- <lingerMs>2000</lingerMs>-->
|
||||
<!-- <retries>10</retries>-->
|
||||
<!-- <baseRetryBackoffMs>100</baseRetryBackoffMs>-->
|
||||
<!-- <maxRetryBackoffMs>50000</maxRetryBackoffMs>-->
|
||||
|
||||
<!-- <encoder>-->
|
||||
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>-->
|
||||
<!-- <charset>UTF-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
|
||||
<!-- <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>-->
|
||||
<!-- <timeZone>Asia/Shanghai</timeZone>-->
|
||||
|
||||
<!-- <filter class="ch.qos.logback.classic.filter.LevelFilter">-->
|
||||
<!-- <level>INFO</level>-->
|
||||
<!-- </filter>-->
|
||||
|
||||
<!-- <mdcFields>logTraceId</mdcFields>-->
|
||||
<!--</appender>-->
|
||||
|
||||
<!--<appender name="ALIYUN_LOG_ERROR" class="com.aliyun.openservices.log.logback.LoghubAppender">-->
|
||||
<!-- <endpoint>${ALIYUN_LOG_ENDPOINT}</endpoint>-->
|
||||
<!-- <accessKeyId>${ALIYUN_LOG_ACCESSKEYID}</accessKeyId>-->
|
||||
<!-- <accessKeySecret>${ALIYUN_LOG_ACCESSKEYSECRET}</accessKeySecret>-->
|
||||
<!-- <project>${ALIYUN_LOG_PROJECT}</project>-->
|
||||
<!-- <logStore>${ALIYUN_LOG_LOGSTORE_ERROR}</logStore>-->
|
||||
|
||||
<!-- <totalSizeInBytes>104857600</totalSizeInBytes>-->
|
||||
<!-- <maxBlockMs>0</maxBlockMs>-->
|
||||
<!-- <ioThreadCount>8</ioThreadCount>-->
|
||||
<!-- <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>-->
|
||||
<!-- <batchCountThreshold>4096</batchCountThreshold>-->
|
||||
<!-- <lingerMs>2000</lingerMs>-->
|
||||
<!-- <retries>10</retries>-->
|
||||
<!-- <baseRetryBackoffMs>100</baseRetryBackoffMs>-->
|
||||
<!-- <maxRetryBackoffMs>50000</maxRetryBackoffMs>-->
|
||||
|
||||
<!-- <encoder>-->
|
||||
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{logTraceId}] %logger{50} [%L] - %msg%n</pattern>-->
|
||||
<!-- <charset>UTF-8</charset>-->
|
||||
<!-- </encoder>-->
|
||||
|
||||
<!-- <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>-->
|
||||
<!-- <timeZone>Asia/Shanghai</timeZone>-->
|
||||
|
||||
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">-->
|
||||
<!-- <level>ERROR</level>-->
|
||||
<!-- </filter>-->
|
||||
|
||||
<!-- <mdcFields>logTraceId</mdcFields>-->
|
||||
<!--</appender>-->
|
||||
|
||||
<!--
|
||||
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
|
||||
以及指定<appender>。<logger>仅有一个name属性,
|
||||
一个可选的level和一个可选的addtivity属性。
|
||||
name:用来指定受此logger约束的某一个包或者具体的某一个类。
|
||||
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
|
||||
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
|
||||
如果未设置此属性,那么当前logger将会继承上级的级别。
|
||||
addtivity:是否向上级logger传递打印信息。默认是true。
|
||||
-->
|
||||
<!--<logger name="org.springframework.web" level="info"/>-->
|
||||
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
|
||||
<!--
|
||||
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
|
||||
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
|
||||
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
|
||||
-->
|
||||
|
||||
<!--
|
||||
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
|
||||
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
|
||||
不能设置为INHERITED或者同义词NULL。默认是DEBUG
|
||||
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
|
||||
-->
|
||||
|
||||
<springProfile name="dev">
|
||||
<logger name="io.github.ehlxr" level="debug"/>
|
||||
</springProfile>
|
||||
<!--<springProfile name="test">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<springProfile name="pre">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<springProfile name="stress">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<springProfile name="prod">-->
|
||||
<!-- <logger name="io.github.ehlxr" level="info"/>-->
|
||||
<!--</springProfile>-->
|
||||
<!--<logger name="com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver" level="warn"/>-->
|
||||
|
||||
<!-- 可用来获取 StatusManager 中的状态 -->
|
||||
<!--<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>-->
|
||||
<!-- 解决 aliyun loghub debug模式下循环发送的问题 -->
|
||||
<logger name="org.apache.http.impl.conn.Wire" level="WARN"/>
|
||||
<!--aliyun loghub 为了防止进程退出时,内存中的数据丢失,请加上此选项-->
|
||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<!--<appender-ref ref="DEBUG_FILE"/>-->
|
||||
<!--<appender-ref ref="INFO_FILE"/>-->
|
||||
<!--<appender-ref ref="WARN_FILE"/>-->
|
||||
<!--<appender-ref ref="ERROR_FILE"/>-->
|
||||
<!--<appender-ref ref="ALIYUN_LOG_INFO"/>-->
|
||||
<!--<appender-ref ref="ALIYUN_LOG_ERROR"/>-->
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -1,40 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 查找最新的schemaLocation 访问 http://www.springframework.org/schema/ -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/aop
|
||||
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-4.0.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
|
||||
http://www.springframework.org/schema/tx
|
||||
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
|
||||
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
|
||||
|
||||
<!-- 启用MVC注解 -->
|
||||
<mvc:annotation-driven />
|
||||
<!--<!– 启用MVC注解 –>-->
|
||||
<!--<mvc:annotation-driven />-->
|
||||
|
||||
<!-- 静态资源文件,不会被Spring MVC拦截 -->
|
||||
<mvc:resources location="/resources/" mapping="/resources/**"/>
|
||||
<!--<!– 静态资源文件,不会被Spring MVC拦截 –>-->
|
||||
<!--<mvc:resources location="/resources/" mapping="/resources/**"/>-->
|
||||
|
||||
<!-- 指定Sping组件扫描的基本包路径 -->
|
||||
<context:component-scan base-package="osc.git.eh3.springamq" >
|
||||
<!-- 这里只扫描Controller,不可重复加载Service -->
|
||||
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
|
||||
</context:component-scan>
|
||||
<!--<!– 指定Sping组件扫描的基本包路径 –>-->
|
||||
<!--<context:component-scan base-package="osc.git.eh3.springamq" >-->
|
||||
<!-- <!– 这里只扫描Controller,不可重复加载Service –>-->
|
||||
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
|
||||
<!--</context:component-scan>-->
|
||||
|
||||
<!-- JSP视图解析器-->
|
||||
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix" value="/WEB-INF/views/" />
|
||||
<property name="suffix" value=".jsp" />
|
||||
<!-- 定义其解析视图的order顺序为1 -->
|
||||
<property name="order" value="1" />
|
||||
</bean>
|
||||
<!--<!– JSP视图解析器–>-->
|
||||
<!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> -->
|
||||
<!-- <property name="prefix" value="/WEB-INF/views/" /> -->
|
||||
<!-- <property name="suffix" value=".jsp" />-->
|
||||
<!--<!– 定义其解析视图的order顺序为1 –>-->
|
||||
<!-- <property name="order" value="1" />-->
|
||||
<!--</bean>-->
|
||||
|
||||
</beans>
|
||||
@@ -1,71 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
<display-name>ActiveMQSpringDemo</display-name>
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<!-- Log4J Start -->
|
||||
<context-param>
|
||||
<param-name>log4jConfigLocation</param-name>
|
||||
<param-value>classpath:log4j.properties</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>log4jRefreshInterval</param-name>
|
||||
<param-value>6000</param-value>
|
||||
</context-param>
|
||||
<!-- Spring Log4J config -->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
|
||||
</listener>
|
||||
<!-- Log4J End -->
|
||||
<!--<!– Log4J Start –>-->
|
||||
<!--<context-param>-->
|
||||
<!-- <param-name>log4jConfigLocation</param-name>-->
|
||||
<!-- <param-value>classpath:log4j.properties</param-value>-->
|
||||
<!--</context-param>-->
|
||||
<!--<context-param>-->
|
||||
<!-- <param-name>log4jRefreshInterval</param-name>-->
|
||||
<!-- <param-value>6000</param-value>-->
|
||||
<!--</context-param>-->
|
||||
<!--<!– Spring Log4J config –>-->
|
||||
<!--<listener>-->
|
||||
<!-- <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>-->
|
||||
<!--</listener>-->
|
||||
<!--<!– Log4J End –>-->
|
||||
|
||||
<!-- Spring 编码过滤器 start -->
|
||||
<filter>
|
||||
<filter-name>characterEncoding</filter-name>
|
||||
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>encoding</param-name>
|
||||
<param-value>UTF-8</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>forceEncoding</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>characterEncoding</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
<!-- Spring 编码过滤器 End -->
|
||||
<!--<!– Spring 编码过滤器 start –>-->
|
||||
<!--<filter>-->
|
||||
<!-- <filter-name>characterEncoding</filter-name>-->
|
||||
<!-- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>-->
|
||||
<!-- <init-param>-->
|
||||
<!-- <param-name>encoding</param-name>-->
|
||||
<!-- <param-value>UTF-8</param-value>-->
|
||||
<!-- </init-param>-->
|
||||
<!-- <init-param>-->
|
||||
<!-- <param-name>forceEncoding</param-name>-->
|
||||
<!-- <param-value>true</param-value>-->
|
||||
<!-- </init-param>-->
|
||||
<!--</filter>-->
|
||||
<!--<filter-mapping>-->
|
||||
<!-- <filter-name>characterEncoding</filter-name>-->
|
||||
<!-- <url-pattern>/*</url-pattern>-->
|
||||
<!--</filter-mapping>-->
|
||||
<!--<!– Spring 编码过滤器 End –>-->
|
||||
|
||||
<!-- Spring Application Context Listener Start -->
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath*:applicationContext.xml,classpath*:ActiveMQ.xml</param-value>
|
||||
</context-param>
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
<!-- Spring Application Context Listener End -->
|
||||
<!--<!– Spring Application Context Listener Start –>-->
|
||||
<!--<context-param>-->
|
||||
<!-- <param-name>contextConfigLocation</param-name>-->
|
||||
<!-- <param-value>classpath*:applicationContext.xml,classpath*:ActiveMQ.xml</param-value>-->
|
||||
<!--</context-param>-->
|
||||
<!--<listener>-->
|
||||
<!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>-->
|
||||
<!--</listener>-->
|
||||
<!--<!– Spring Application Context Listener End –>-->
|
||||
|
||||
|
||||
<!-- Spring MVC Config Start -->
|
||||
<servlet>
|
||||
<servlet-name>SpringMVC</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<!--<!– Spring MVC Config Start –>-->
|
||||
<!--<servlet>-->
|
||||
<!-- <servlet-name>SpringMVC</servlet-name>-->
|
||||
<!-- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>-->
|
||||
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath:spring-mvc.xml</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>SpringMVC</servlet-name>
|
||||
<!-- Filter all resources -->
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
<!-- Spring MVC Config End -->
|
||||
<!-- <init-param>-->
|
||||
<!-- <param-name>contextConfigLocation</param-name>-->
|
||||
<!-- <param-value>classpath:spring-mvc.xml</param-value>-->
|
||||
<!-- </init-param>-->
|
||||
<!-- <load-on-startup>1</load-on-startup>-->
|
||||
<!--</servlet>-->
|
||||
<!--<servlet-mapping>-->
|
||||
<!-- <servlet-name>SpringMVC</servlet-name>-->
|
||||
<!-- <!– Filter all resources –>-->
|
||||
<!-- <url-pattern>/</url-pattern>-->
|
||||
<!--</servlet-mapping>-->
|
||||
<!--<!– Spring MVC Config End –>-->
|
||||
|
||||
</web-app>
|
||||
23
src/test/java/io/github/ehlxr/BuddApplicationTest.java
Normal file
23
src/test/java/io/github/ehlxr/BuddApplicationTest.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package io.github.ehlxr;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
@SpringBootTest
|
||||
@RunWith(SpringRunner.class)
|
||||
public class BuddApplicationTest {
|
||||
private static final Logger log = LoggerFactory.getLogger(BuddApplicationTest.class);
|
||||
|
||||
@Test
|
||||
public void redisLockTest() {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user