Compare commits

..

42 Commits

Author SHA1 Message Date
cc5cbc1ebb change to springboot 2021-08-29 12:23:13 +08:00
e76d89f774 update at 2021-08-12 23:15:14 by ehlxr 2021-08-12 23:15:14 +08:00
ee6f67a6ab add sort coast time test 2021-08-01 20:55:49 +08:00
b3dbc9f668 update at 2021-07-16 10:48:40 by ehlxr 2021-07-16 10:48:40 +08:00
163882bb4d update at 2021-07-16 09:37:58 by ehlxr 2021-07-16 09:37:58 +08:00
3947896a04 Merge branch 'master' of github.com:ehlxr/budd 2021-07-16 09:35:26 +08:00
d3b548c8b4 add SlideWindow 2021-07-15 23:01:08 +08:00
cc013f3b86 add SlideWindow 2021-07-15 22:05:54 +08:00
e106affde0 add SlideWindow 2021-07-15 22:04:29 +08:00
7aca97aa2e update at 2021-07-15 21:46:50 by ehlxr 2021-07-15 21:46:50 +08:00
2f74ee2c8c update at 2021-07-15 18:35:46 by ehlxr 2021-07-15 18:35:46 +08:00
0b5acb84ab add mergesort time test 2021-07-03 13:11:51 +08:00
dccb21493b add quicksort time test 2021-07-02 22:40:15 +08:00
7cfdaab3d0 add sort coast time test 2021-06-29 21:21:03 +08:00
bf4d8c5fb9 add sort coast time test 2021-06-29 18:39:19 +08:00
5865722a7d add sort coast time test 2021-06-29 18:20:12 +08:00
165f099240 add sort test 2021-06-28 22:13:54 +08:00
f581b143dc update at 2021-06-09 09:14:40 by ehlxr 2021-06-09 09:14:40 +08:00
8d2f0d57b5 update at 2021-06-08 23:36:39 by ehlxr 2021-06-08 23:36:39 +08:00
1fb0c52138 update at 2021-05-28 22:48:00 by ehlxr 2021-05-28 22:48:00 +08:00
3b5b3b50a9 update at 2021-05-24 23:12:21 by ehlxr 2021-05-24 23:12:21 +08:00
f5ff83737c Merge branch 'master' of github.com:ehlxr/budd 2021-05-14 16:26:08 +08:00
59c2bd2e3c update at 2021-05-14 16:25:51 by ehlxr 2021-05-14 16:25:51 +08:00
367798c0dc Create SECURITY.md 2021-04-23 09:26:59 +08:00
d194341936 Merge pull request #14 from ehlxr/dependabot/maven/org.mybatis-mybatis-3.5.6
Bump mybatis from 3.2.7 to 3.5.6
2021-04-23 09:26:08 +08:00
dependabot[bot]
3ee99909b8 Bump mybatis from 3.2.7 to 3.5.6
Bumps [mybatis](https://github.com/mybatis/mybatis-3) from 3.2.7 to 3.5.6.
- [Release notes](https://github.com/mybatis/mybatis-3/releases)
- [Commits](https://github.com/mybatis/mybatis-3/compare/mybatis-3.2.7...mybatis-3.5.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-22 16:43:53 +00:00
2584e13e20 add linked list stack 2021-04-16 09:27:46 +08:00
612feb1e9e add linked list stack 2021-04-16 09:05:48 +08:00
6c8b22b204 add linked list stack 2021-04-15 23:43:44 +08:00
fa4748c57c add josephu question 2021-04-13 22:16:11 +08:00
lixiangrong
16dad8f7b6 add jsephu 2021-04-09 22:35:08 +08:00
lixiangrong
d8a328c472 update at 2021-04-07 22:21:36 by ehlxr 2021-04-07 22:21:36 +08:00
lixiangrong
b83d324c54 add doubleLinkedList 2021-04-07 21:14:47 +08:00
lixiangrong
522969e077 update at 2021-04-06 09:36:50 by ehlxr 2021-04-06 09:36:50 +08:00
lixiangrong
19161217b7 update at 2021-04-05 22:30:28 by ehlxr 2021-04-05 22:30:28 +08:00
lixiangrong
2953e48009 reverse linkedlist 2021-04-04 22:32:26 +08:00
lixiangrong
69d714f19a update at 2021-04-04 16:31:55 by ehlxr 2021-04-04 16:31:55 +08:00
de91226dba Merge pull request #12 from ehlxr/dependabot/maven/com.fasterxml.jackson.core-jackson-databind-2.10.5.1
Bump jackson-databind from 2.10.3 to 2.10.5.1
2021-04-02 12:50:40 +08:00
7403cea6a7 Merge pull request #13 from ehlxr/dependabot/maven/com.google.guava-guava-29.0-jre
Bump guava from 28.2-jre to 29.0-jre
2021-04-02 12:50:30 +08:00
dependabot[bot]
6a59bac8b9 Bump guava from 28.2-jre to 29.0-jre
Bumps [guava](https://github.com/google/guava) from 28.2-jre to 29.0-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-31 18:50:49 +00:00
7697a84edf add array queue 2021-03-30 23:17:07 +08:00
dependabot[bot]
9f737f1a45 Bump jackson-databind from 2.10.3 to 2.10.5.1
Bumps [jackson-databind](https://github.com/FasterXML/jackson) from 2.10.3 to 2.10.5.1.
- [Release notes](https://github.com/FasterXML/jackson/releases)
- [Commits](https://github.com/FasterXML/jackson/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-02-18 21:47:29 +00:00
46 changed files with 2864 additions and 317 deletions

21
SECURITY.md Normal file
View 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
View File

@@ -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>

View 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);
}
}

View File

@@ -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());
}
}

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package io.github.ehlxr.redis;
package io.github.ehlxr;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

View File

@@ -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 + "]";
}
}

View File

@@ -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;
}
}

View File

@@ -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 + "]";
}
}

View File

@@ -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];
}
}

View File

@@ -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];
}
}

View File

@@ -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 + "}";
}
}

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View 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));
}
}
}

View File

@@ -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);
}
/**

View 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();
}
}

View 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);
}

View 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;
}
}

View 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);
}
}

View 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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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)));
}
/**

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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;
/**

View 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];
}
}

View 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;
}
}

View File

@@ -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();
}
}

View 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
}
}

View File

@@ -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" />
<!--&lt;!&ndash; ActiveMQ 连接工厂 &ndash;&gt;-->
<!--&lt;!&ndash; 真正可以产生Connection的ConnectionFactory由对应的 JMS服务厂商提供&ndash;&gt;-->
<!--&lt;!&ndash; 如果连接网络tcp://ip:61616未连接网络tcp://localhost:61616 以及用户名,密码&ndash;&gt;-->
<!--<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 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的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-->
<!--&lt;!&ndash; Spring Caching连接工厂 &ndash;&gt;-->
<!--&lt;!&ndash; Spring用于管理真正的ConnectionFactory的ConnectionFactory &ndash;&gt; -->
<!--<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">-->
<!-- &lt;!&ndash; 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory &ndash;&gt; -->
<!-- <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>-->
<!-- &lt;!&ndash; 同上,同理 &ndash;&gt;-->
<!-- &lt;!&ndash; <constructor-arg ref="amqConnectionFactory" /> &ndash;&gt;-->
<!-- &lt;!&ndash; Session缓存数量 &ndash;&gt;-->
<!-- <property name="sessionCacheSize" value="100" />-->
<!--</bean>-->
<!-- 消息消费者 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>
<!-- 定义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 -->
<!--&lt;!&ndash; Spring JmsTemplate 的消息生产者 start&ndash;&gt;-->
<!--&lt;!&ndash; 定义JmsTemplate的Queue类型 &ndash;&gt;-->
<!--<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">-->
<!-- &lt;!&ndash; 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 &ndash;&gt; -->
<!-- <constructor-arg ref="connectionFactory" />-->
<!-- &lt;!&ndash; 非pub/sub模型发布/订阅),即队列模式 &ndash;&gt;-->
<!-- <property name="pubSubDomain" value="false" />-->
<!--</bean>-->
<!--&lt;!&ndash; 定义JmsTemplate的Topic类型 &ndash;&gt;-->
<!--<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">-->
<!-- &lt;!&ndash; 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 &ndash;&gt; -->
<!-- <constructor-arg ref="connectionFactory" />-->
<!-- &lt;!&ndash; pub/sub模型发布/订阅) &ndash;&gt;-->
<!-- <property name="pubSubDomain" value="true" />-->
<!--</bean>-->
<!--&lt;!&ndash;Spring JmsTemplate 的消息生产者 end&ndash;&gt;-->
<!--&lt;!&ndash; 消息消费者 start&ndash;&gt;-->
<!--&lt;!&ndash; 定义Queue监听器 &ndash;&gt;-->
<!--<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>-->
<!--&lt;!&ndash; 定义Topic监听器 &ndash;&gt;-->
<!--<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>-->
<!--&lt;!&ndash; 消息消费者 end &ndash;&gt;-->
</beans>

View File

@@ -0,0 +1,7 @@
server:
port: 8081
spring:
redis:
host: 127.0.0.1
port: 6379

View 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

View File

@@ -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">
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
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"/>-->
<!-- 配置扫描路径 -->
<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>

View File

@@ -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

View 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(-&#45;&#45;){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>

View File

@@ -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">
<!-- 启用MVC注解 -->
<mvc:annotation-driven />
<!-- 静态资源文件不会被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>
<!-- 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 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">
<!--&lt;!&ndash; 启用MVC注解 &ndash;&gt;-->
<!--<mvc:annotation-driven />-->
<!--&lt;!&ndash; 静态资源文件不会被Spring MVC拦截 &ndash;&gt;-->
<!--<mvc:resources location="/resources/" mapping="/resources/**"/>-->
<!--&lt;!&ndash; 指定Sping组件扫描的基本包路径 &ndash;&gt;-->
<!--<context:component-scan base-package="osc.git.eh3.springamq" >-->
<!-- &lt;!&ndash; 这里只扫描Controller不可重复加载Service &ndash;&gt;-->
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
<!--</context:component-scan>-->
<!--&lt;!&ndash; JSP视图解析器&ndash;&gt;-->
<!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> -->
<!-- <property name="prefix" value="/WEB-INF/views/" /> -->
<!-- <property name="suffix" value=".jsp" />-->
<!--&lt;!&ndash; 定义其解析视图的order顺序为1 &ndash;&gt;-->
<!-- <property name="order" value="1" />-->
<!--</bean>-->
</beans>

View File

@@ -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 -->
<!--&lt;!&ndash; Log4J Start &ndash;&gt;-->
<!--<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>-->
<!--&lt;!&ndash; Spring Log4J config &ndash;&gt;-->
<!--<listener>-->
<!-- <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>-->
<!--</listener>-->
<!--&lt;!&ndash; Log4J End &ndash;&gt;-->
<!-- 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 -->
<!--&lt;!&ndash; Spring 编码过滤器 start &ndash;&gt;-->
<!--<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>-->
<!--&lt;!&ndash; Spring 编码过滤器 End &ndash;&gt;-->
<!-- 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 -->
<!--&lt;!&ndash; Spring Application Context Listener Start &ndash;&gt;-->
<!--<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>-->
<!--&lt;!&ndash; Spring Application Context Listener End &ndash;&gt;-->
<!-- Spring MVC Config Start -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--&lt;!&ndash; Spring MVC Config Start &ndash;&gt;-->
<!--<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>-->
<!-- &lt;!&ndash; Filter all resources &ndash;&gt;-->
<!-- <url-pattern>/</url-pattern>-->
<!--</servlet-mapping>-->
<!--&lt;!&ndash; Spring MVC Config End &ndash;&gt;-->
</web-app>

View 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() {
}
}