feat(SpringDemo): 添加接口重试机制

- 新增重试相关的异常类和枚举类型- 实现重试切面,支持接口级别的重试限制
- 添加重试控制器和相关注解
- 修改数据库连接配置,启用SSL

Changes
application.yaml
AppTest.java
AppTest.java
BockingQueueDemo.java
BuinessException.java
DelayQueueDemo.java
ErrorType.java
FunctionInterfaceDemo.java
FutureRelative.java
LCR155.java
LCR186.java
LeetCod42_1.java
LeetCode15.java
LeetCode45.java
LeetCode48.java
LeetCode51.java
LeetCode392.java
LeetCode494.java
LeetCode718.java
LeetCode_32.java
P1.java
pom.xml
pom.xml
pom.xml
pom.xml
RetryAspect.java
RetryController.java
RetryLimit.java
sadasf.bpmn20.xml
sdoih.bpmn
SpringDemoApplication.java
workflow.md
Unversioned Files
C:\Users\wenhai\project\javaProject\LeetCode\Activiti7Demo\.gitignore
C:\Users\wenhai\project\javaProject\LeetCode\Activiti7Demo\src\main\java\cn\whai\activiti\Activiti7DemoApplication.java
C:\Users\wenhai\project\javaProject\LeetCode\Activiti7Demo\src\test\java\cn\whai\activiti\activiti7demo\Activiti7DemoApplicationTests.java
C:\Users\wenhai\project\javaProject\LeetCode\Activiti7Demo\src\main\resources\application.yaml
C:\Users\wenhai\project\javaProject\LeetCode\Activiti7Demo\pom.xml
This commit is contained in:
whai 2024-11-11 13:47:20 +08:00
parent 9e8153e434
commit ea493390a6
37 changed files with 1341 additions and 9 deletions

33
Activiti7Demo/.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

80
Activiti7Demo/pom.xml Normal file
View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.whai.activiti</groupId>
<artifactId>Activiti7Demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Activiti7Demo</name>
<description>Activiti7Demo Springboot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- Activiti 7.x依赖 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.GA</version>
<!-- 由于activiti7是使用mybatis作为orm框架我这里整合mybatis-plus所以需要排除mybatis -->
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mysql 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- MyBatis-Plus依赖包 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,19 @@
package cn.whai.activiti;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
@SpringBootApplication(exclude = {
//activiti 默认整合security屏蔽Security认证
SecurityAutoConfiguration.class,
ManagementWebSecurityAutoConfiguration.class
})
public class Activiti7DemoApplication {
public static void main(String[] args) {
SpringApplication.run(Activiti7DemoApplication.class, args);
}
}

View File

@ -0,0 +1,18 @@
server:
port: 18080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/activiti?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
activiti:
db-history-used: true
history-level: full
database-schema-update: true
check-process-definitions: false
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
id="Definitions_1"
targetNamespace="http://bpmn.io/schema/bpmn"
exporter="bpmn-js (https://bpmn.io)"
exporterVersion="10.3.0">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:userTask id="UserTask_1" name="任务">
<bpmn:incoming>SequenceFlow_1</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_2</bpmn:outgoing>
</bpmn:userTask>
<bpmn:endEvent id="EndEvent_1">
<bpmn:incoming>SequenceFlow_2</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="StartEvent_1" targetRef="UserTask_1" />
<bpmn:sequenceFlow id="SequenceFlow_2" sourceRef="UserTask_1" targetRef="EndEvent_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
<dc:Bounds x="173" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_1_di" bpmnElement="UserTask_1">
<dc:Bounds x="263" y="90" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_1_di" bpmnElement="EndEvent_1">
<dc:Bounds x="423" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_1_di" bpmnElement="SequenceFlow_1">
<di:waypoint x="209" y="120" />
<di:waypoint x="263" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_2_di" bpmnElement="SequenceFlow_2">
<di:waypoint x="363" y="120" />
<di:waypoint x="423" y="120" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,24 @@
package cn.whai.activiti.activiti7demo;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
class Activiti7DemoApplicationTests {
@Test
void contextLoads() {
}
}

57
Activiti7Demo/workflow.md Normal file
View File

@ -0,0 +1,57 @@
## WordFlow 工作流引擎
是一种按照预定义规则【需要符合BPMN规范】进行部署将业务和节点的流程进行分离【特定形式进行关联】
### 二、什么是Activiti7
Activiti 是一个工作流引擎, activiti 可以将业务系统中复杂的业务流程抽取出来,使用专门的
建模语言BPMN2.0)进行定义,业务系统按照预先定义的流程进行执行
https://www.activiti.org
2.2 Activiti7内部核心机制
1⃣业务流程图要规范化需要遵守一套标准。
2⃣业务流程图本质上就是一个XML文件而XML可以存放所要的数据。
3⃣读取业务流程图的过程就是解析XML文件的过程。
4⃣读取一个业务流程图的结点就相当于解析一个XML的结点进一步将数据插入到MySQL表中形成一条记录。
5⃣将一个业务流程图的所有节点都读取并存入到MySQL表中。
6⃣后面只要读取MySQL表中的记录就相当于读取业务流程图的一个节点。
7⃣业务流程的推进后面就转换为读取表中的数据并且处理数据结束的时候这一行数据就可以删除了。
### BPMN
BPMNBusiness Process Model And Notation业务流程模型和符号是由BPMIBusiness Process Management Initiative开发的一套的业务流程建模符号使用BPMN提供的符号可以创建业务流程。2004年5月发布了BPMN1.0规范。
> [processOn BPMN 概念](https://www.processon.com/knowledge/bpmndiagram)
>
> ### BPMN 的核心元素
> - 活动:活动是 BPMN 中最基本的元素之一,它代表了业务流程中的一个具体任务或操作。可以自动/手动、
> - 事件:事件是 BPMN 中用于表示流程中的特定时刻或状态的元素。例如,开始事件、结束事件、中间事件等。
> - 网关:网关用于控制流程的执行路径,可以实现并行、条件、互斥等多种逻辑。
> - 泳道:泳道用于将流程分解为多个并行的部分,每个泳道代表一个独立的执行路径。
> 一个BPMN的例子
> - 当事人填写请假单启动流程后把请假单ID绑定到流程中
> - 部门经理对请假单进行审核;
> - 然后人事经理进行复核并进行备案;
> - 最后请假流程结束。
### Activiti支持的数据库
- Activiti的运行需要数据库的支撑支持如下:
- h2
- MySQL
- Oracle
- Db2
- postgres
- mysql
- 在Navicat工具中创建`activiti`的数据库,用于后续的实验.

View File

@ -2,7 +2,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<groupId>com.whai</groupId>
<artifactId>LeetCode</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

View File

@ -0,0 +1,83 @@
package cn.whaifree.interview.js;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/10 19:27
* @注释
*/
public class P1 {
public static void main(String[] args) {
System.out.println(Arrays.toString(new P1().solve(new int[]{2,3,2,3,2})));
}
/**
* 代码中的类名方法名参数名已经指定请勿修改直接返回方法规定的值即可
*
*
* @param arr int整型一维数组
* @return int整型一维数组
*/
public int[] solve (int[] arr) {
// write code here
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if (!map.containsKey(arr[i])) {
map.put(arr[i], new ArrayList<>());
}
map.get(arr[i]).add(i + 1);
}
int[] res = new int[arr.length];
for (Map.Entry<Integer, List<Integer>> entry : map.entrySet()) {
List<Integer> value = entry.getValue();
if (value.size() == 2) {
Integer a = value.get(1);
Integer b = value.get(0);
res[b - 1] = a;
res[a - 1] = b;
}else {
for (Integer i : value) {
res[i - 1] = -1;
}
}
}
return res;
}
}
class p2{
public static void main(String[] args) {
System.out.println(new p2().solve(new int[]{1, 2}));
}
/**
* 代码中的类名方法名参数名已经指定请勿修改直接返回方法规定的值即可
*
*
* @param arr int整型一维数组
* @return long长整型
*/
public long solve (int[] arr) {
int n = arr.length;
int[][] dp = new int[n][n];
for (int len = 2; len <= n; len++) {
for (int i = 0; i <= n - len; i++) {
int j = i + len - 1;
if (arr[i] == arr[j]) {
dp[i][j] = dp[i + 1][j - 1];
}else {
dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]) +
Math.abs(arr[i] - arr[j]);
}
}
}
int i = dp[0][n - 1];
return i;
}
}

View File

@ -0,0 +1,66 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/9 18:04
* @注释
*/
public class LCR155 {
class Node {
public int val;
public Node left;
public Node right;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val,Node _left,Node _right) {
val = _val;
left = _left;
right = _right;
}
}
@Test
public void test() {
Solution solution = new Solution();
Node node = new Node(4);
Node node1 = solution.treeToDoublyList(node);
System.out.println(node1);
}
class Solution {
Node head = new Node(-1);
Node index = head;
public Node treeToDoublyList(Node root) {
if (root == null) {
return null;
}
in(root);
index.right = head.right;
head.right.left = index;
return head.right;
}
public void in(Node root) {
if (root == null) {
return;
}
in(root.left);
index.right = root;
root.left = index;
index = root;
in(root.right);
}
}
}

View File

@ -0,0 +1,34 @@
package cn.whaifree.redo.redo_all_241016;
import java.util.Set;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/9 18:20
* @注释
*/
public class LCR186 {
class Solution {
public boolean checkDynasty(int[] places) {
int[] set = new int[14];
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int i = 0; i < places.length; i++) {
if (places[i] == 0) {
continue;
// 差值为5以内并且不重复就能推出这是个顺子
}
if (set[places[i]] != 0) {
// 已经存在直接返回
return false;
}
set[places[i]]++;
min = Math.min(min, places[i]);
max = Math.max(max, places[i]);
}
return max - min < 5;
}
}
}

View File

@ -0,0 +1,52 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/11 10:36
* @注释
*/
public class LeetCod42_1 {
@Test
public void test() {
int[] height = {4,2,0,3,2,5};
int trap = new Solution().trap(height);
System.out.println(trap);
}
class Solution {
/**
* 每个位置左边第一个比他大的
* @param height
* @return
*/
public int trap(int[] height) {
Deque<Integer> stack = new ArrayDeque<>();
stack.push(0);
int res = 0;
for (int i = 1; i < height.length; i++) {
while (!stack.isEmpty() && height[stack.peek()] < height[i]) {
// 单调递增
Integer pop = stack.pop();
int level = height[pop];
if (!stack.isEmpty()) {
int left = stack.peek();
int right = i;
int sub = Math.min(height[left], height[right]) - level;
res += sub * (right - left - 1);
}
}
stack.push(i);
}
return res;
}
}
}

View File

@ -0,0 +1,60 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/6 13:20
* @注释
*/
public class LeetCode15 {
@Test
public void test() {
int[] nums = {1,2,-2,-1};
System.out.println(new Solution().threeSum(nums));
}
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
for (int left = 0; left < nums.length; left++) {
if (left > 0 && nums[left] == nums[left - 1]) {
continue;
}
int mid = left + 1;
int right = nums.length - 1;
while (mid < right) {
int sum = nums[left] + nums[mid] + nums[right];
if (sum == 0) {
res.add(Arrays.asList(nums[left], nums[mid], nums[right]));
while (mid < right && nums[mid] == nums[mid + 1]) {
mid++;
}
while (mid < right && nums[right] == nums[right - 1]) {
right--;
}
mid++;
right--;
} else if (sum < 0) {
mid++;
} else {
right--;
}
}
}
return res;
}
}
}

View File

@ -0,0 +1,76 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/8 17:22
* @注释
*/
public class LeetCode392 {
@Test
public void test() {
System.out.println(new Solution().isSubsequence("abc", "ahbgdc"));
}
class Solution {
public boolean isSubsequence(String s, String t) {
if (s.isBlank()) {
return true;
}
int sIndex = 0;
int i = 0;
for (; i < t.length(); i++) {
if (sIndex == s.length()) {
break;
}
if (s.charAt(sIndex) == t.charAt(i)) {
sIndex++;
}
}
return sIndex == s.length();
}
}
@Test
public void test2() {
System.out.println(new Solution1().isSubsequence("abc", "ahbgdc"));
}
class Solution1 {
/**
*
* ''a h b g d c
* '' 1 1 1 1 1 1 1
* a 0 1 1 1 1 1 1
* b 0 0 0 1 1 1 1
* c 0 0 0 0 0 0 1
*
* 0-1背包问题
* @param s
* @param t
* @return
*/
public boolean isSubsequence(String s, String t) {
boolean[][] dp = new boolean[s.length() + 1][t.length() + 1];
for (int i = 0; i < t.length() + 1; i++) {
dp[0][i] = true;
}
for (int i = 1; i <= s.length(); i++) {
for (int j = 1; j <= t.length(); j++) {
if (s.charAt(i - 1) != t.charAt(j - 1) || !dp[i - 1][j - 1]) {
dp[i][j] = dp[i][j - 1];
} else {
dp[i][j] = true;
}
}
}
return dp[s.length()][t.length()];
}
}
}

View File

@ -0,0 +1,83 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/8 19:52
* @注释
*/
public class LeetCode45 {
@Test
public void test() {
int[] nums = {2,3,1,1,4};
int jump = new Solution().jump(nums);
System.out.println(jump);
}
class Solution {
/**
*
* @param nums
* @return
*/
public int jump(int[] nums) {
if (nums.length == 1) {
return 0;
}
int curCover = 0;
int maxCover = 0;
int jump = 0;
for (int i = 0; i < nums.length; i++) {
maxCover = Math.max(maxCover, i + nums[i]);
// 如果从这个 起跳点 起跳叫做第 1 跳跃
// 那么从后面 nums[0]个格子起跳 可以叫做第 2 跳跃
if (i == curCover) {
curCover = maxCover;
jump++;
}
if (curCover >= nums.length - 1) {
return jump;
}
}
return jump;
}
}
@Test
public void test1() {
int[] nums = {2,3,1,1,4};
int jump = new Solution1().jump(nums);
System.out.println(jump);
}
class Solution1 {
/**
* [2,3,1,1,4]
* 0 1 1 2 2
* @param nums
* @return
*/
public int jump(int[] nums) {
if (nums.length == 1) {
return 0;
}
// 动态规划
int[] dp = new int[nums.length];
dp[0] = 0;
for (int i = 1; i < nums.length; i++) {
int min = Integer.MAX_VALUE;
for (int j = 0; j < i; j++) {
if (nums[j] >= i - j) {
min = Math.min(min, dp[j] + 1);
}
}
dp[i] = min;
}
return dp[nums.length - 1];
}
}
}

View File

@ -0,0 +1,28 @@
package cn.whaifree.redo.redo_all_241016;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/6 13:31
* @注释
*/
public class LeetCode48 {
class Solution {
public void rotate(int[][] matrix) {
int len = matrix.length;
for (int i = 0; i < len / 2; i++) {
for (int j = i; j < len; j++) {
int x = i;
int y = j;
int n = len - 1;
int tmp = matrix[x][y];
matrix[x][y] = matrix[n - y][x];
matrix[n - y][x] = matrix[n - x][n - y];
matrix[n - x][n - y] = matrix[y][n - x];
matrix[y][n - x] = tmp;
}
}
}
}
}

View File

@ -0,0 +1,71 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/10 17:19
* @注释
*/
public class LeetCode494 {
class Solution {
/**
* 背包问题
*
* 1 2 1 1 1 3
* x为需要变成负数的数量
*
* sum = x * 2 + target
*
* x = sum-target /2
*
* 把nums里装到容量为x的背包中
* 有几种方法可以装满
*
* 0 1 2 3
* 1 1 1 0 0
* 2 1 1 1 1
* 2 1 1 2 2
* 1
* 1
*
* 1 2 -2 1 1
* 1 2 -2 -1 -1
* -1 2 -2 1 -1
* -1 2 -2 -1 1
*
*
*
* @param nums
* @param target
* @return
*/
public int findTargetSumWays(int[] nums, int target) {
Integer sum = Arrays.stream(nums).sum();
int pkgSize = (sum - target) / 2;
int[] dp = new int[pkgSize + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = pkgSize; j >= 0; j--) {
if (j >= nums[i]) {
dp[j] = dp[j] + dp[j - nums[i]];
}
}
}
return dp[pkgSize];
}
}
@Test
public void test() {
int[] nums = {1};
int target = 1;
System.out.println(new Solution().findTargetSumWays(nums, target));
}
}

View File

@ -0,0 +1,87 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/8 18:34
* @注释
*/
public class LeetCode51 {
@Test
public void test() {
for (List<String> solveNQueen : new Solution().solveNQueens(4)) {
System.out.println(solveNQueen);
}
}
class Solution {
List<List<String>> res = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
char[][] map = new char[n][n];
for (char[] chars : map) {
Arrays.fill(chars, '.');
}
backTracking(map, 0);
return res;
}
public void backTracking(char[][] map, int x) {
if (x == map.length) {
ArrayList<String> e = new ArrayList<>();
for (char[] chars : map) {
e.add(new String(chars));
}
res.add(e);
return;
}
if (x > map.length) {
return;
}
for (int i = 0; i < map.length; i++) {
if (cal(map, x, i)) {
map[x][i] = 'Q';
backTracking(map, x + 1);
map[x][i] = '.';
}
}
}
// 往左上搜索
public boolean cal(char[][] map, int x, int y) {
// 往左边搜索
for (int i = y; i >= 0; i--) {
if (map[x][i] == 'Q') {
return false;
}
}
// 往上搜索
for (int i = x; i >= 0; i--) {
if (map[i][y] == 'Q') {
return false;
}
}
// 往左上搜索
for (int i = x, j = y; i >= 0 && j >= 0; i--, j--) {
if (map[i][j] == 'Q') {
return false;
}
}
// 往右上搜索
for (int i = x, j = y; i >= 0 && j < map.length; i--, j++) {
if (map[i][j] == 'Q') {
return false;
}
}
return true;
}
}
}

View File

@ -0,0 +1,52 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/8 17:16
* @注释
*/
public class LeetCode718 {
@Test
public void test() {
Solution solution = new Solution();
System.out.println(solution.findLength(new int[]{1, 2, 3, 2, 1, 5, 8, 9}, new int[]{3, 2, 1, 5, 8, 4, 7}));
}
class Solution {
/**
* 连续
* 0-i 0-j内最长公共的子数组的长度
*
* 1 2 3 2 1
* 3 0 0 1 0 0
* 2 0 1 0 2 0
* 1 1 0 1
* 4
* 7
*
* @param nums1
* @param nums2
* @return
*/
public int findLength(int[] nums1, int[] nums2) {
int[][] dp = new int[nums1.length + 1][nums2.length + 1];
int max = 0;
for (int i = 1; i <= nums1.length; i++) {
for (int j = 1; j <= nums2.length; j++) {
if (nums1[i - 1] == nums2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
max = Math.max(max, dp[i][j]);
}
}
}
return max;
}
}
}

View File

@ -0,0 +1,54 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/11 11:36
* @注释
*/
public class LeetCode_32 {
@Test
public void test() {
Solution solution = new Solution();
System.out.println(solution.longestValidParentheses("(()(()()"));
}
class Solution {
public int longestValidParentheses(String s) {
boolean[] mark = new boolean[s.length()];
char[] arr = s.toCharArray();
Deque<Integer> stack = new ArrayDeque<>();
for (int i = 0; i < arr.length; i++) {
if (arr[i] == '(') {
stack.push(i);
} else if (!stack.isEmpty()) {
Integer pop = stack.pop();
mark[pop] = true;
mark[i] = true;
}
}
int left = 0;
int right = 0;
int maxLen = 0;
while (right < mark.length) {
if (!mark[right]) {
maxLen = Math.max(maxLen, right - left);
left = right + 1;
}
right++;
}
return Math.max(maxLen, right - left);
}
}
}

View File

@ -0,0 +1,45 @@
package cn.whaifree.tech;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/5 22:22
* @注释
*/
public class BockingQueueDemo {
static int size = 3;
static List<String> instanceId = List.of();
static {
for (int i = 0; i < 50; i++) {
instanceId.add("instance" + i);
}
}
public static void main(String[] args) {
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
new Thread(new Runnable() {
@Override
public void run() {
queue.addAll(instanceId);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < size; i++) {
}
}
}).start();
}
}

View File

@ -0,0 +1,16 @@
package cn.whaifree.tech.demo.thread;
import java.util.concurrent.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/5 14:24
* @注释
*/
public class DelayQueueDemo {
public static void main(String[] args) {
}
}

View File

@ -17,9 +17,14 @@ public class FutureRelative {
final static ExecutorService executorService = Executors.newFixedThreadPool(10,
Executors.defaultThreadFactory());
final static ExecutorService executorService1 = Executors.newScheduledThreadPool(10);
public static void main(String[] args) {
futureTaskDemo();
// futureTaskDemo();
}

View File

@ -1,4 +1,4 @@
package org.example;
package com.whai;
import junit.framework.Test;
import junit.framework.TestCase;

View File

@ -2,7 +2,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<groupId>com.whai</groupId>
<artifactId>LeetCode</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

View File

@ -1,6 +1,7 @@
package cn.whaifree.tech;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**

View File

@ -1,4 +1,4 @@
package org.example;
package com.whai;
import junit.framework.Test;
import junit.framework.TestCase;

View File

@ -2,7 +2,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<groupId>com.whai</groupId>
<artifactId>LeetCode</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

View File

@ -2,8 +2,10 @@ package cn.whaifree.springdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@SpringBootApplication
@EnableAspectJAutoProxy
public class SpringDemoApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,22 @@
package cn.whaifree.springdemo.controller.interceptRetry;
import lombok.Getter;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/10 15:26
* @注释
*/
public class BuinessException extends RuntimeException {
@Getter
private ErrorType type;
private Integer code;
public BuinessException(ErrorType type, Integer code) {
this.type = type;
this.code = code;
}
}

View File

@ -0,0 +1,18 @@
package cn.whaifree.springdemo.controller.interceptRetry;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/10 15:26
* @注释
*/
public enum ErrorType {
RetryType("Retry Too Many", 503);
private String type;
private Integer code;
ErrorType (String type, Integer code) {
this.type = type;
this.code = code;
}
}

View File

@ -0,0 +1,24 @@
package cn.whaifree.springdemo.controller.interceptRetry;
import cn.whaifree.springdemo.controller.interceptRetry.aspect.RetryLimit;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/9 21:56
* @注释
*/
@RestController
public class RetryController {
@PostMapping("/try")
@RetryLimit(limitCount = 3, limitTime = 1, limitKey = "ip", resMsg = "retry请求频繁")
public String tryMethod(int success) {
if (success == 1) {
throw new BuinessException(ErrorType.RetryType, 500);
}
return "tryMethod";
}
}

View File

@ -0,0 +1,146 @@
package cn.whaifree.springdemo.controller.interceptRetry.aspect;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import cn.whaifree.springdemo.controller.interceptRetry.BuinessException;
import cn.whaifree.springdemo.controller.interceptRetry.ErrorType;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.Maps;
import com.mysql.cj.util.LogUtils;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Getter;
import org.apache.catalina.util.RequestUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.WebUtils;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/9 21:57
* @注释
*/
@Aspect
@Component
@Order(100)
public class RetryAspect {
/**
* 一个Cache只能有一个有效期
* 所以要根据有效期进行分组
* <p>
* exprieTimekeyOfIptime
* <p>
* <p>
* 对不同时间用不同cache实现
*/
Map<Integer, Cache<String, AtomicInteger>> cacheMap = new HashMap<>();
@Resource
@Lazy
private ApplicationContext applicationContext;
@PostConstruct
public void init() {
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
// 这里有疑问可能拿到RetryAspect走getBean导致循环依赖RetryAspect循环依赖RetryAspect
if (beanDefinitionName.equalsIgnoreCase(this.getClass().getSimpleName())) {
continue;
}
Object bean = applicationContext.getBean(beanDefinitionName);
Method[] methods = bean.getClass().getDeclaredMethods();
for (Method method : methods) {
try {
// 手动用反射获取不到注解
RetryLimit retryLimit = AnnotationUtils.findAnnotation(method, RetryLimit.class);
// RetryLimit retryLimit = method.getAnnotation(RetryLimit.class);
if (retryLimit == null) {
continue;
}
int expireTime = retryLimit.limitTime();
Cache<String, AtomicInteger> build = Caffeine.newBuilder().expireAfterAccess(Duration.ofMinutes(expireTime)).maximumSize(1000).build();
cacheMap.put(expireTime, build);
} catch (Exception e) {
e.printStackTrace();
}
}
}
System.out.println(cacheMap);
}
@Around("@annotation(cn.whaifree.springdemo.controller.interceptRetry.aspect.RetryLimit)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取方法签名设置方法可以访问
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
method.setAccessible(true);
// 获取注解
RetryLimit retryAn = AnnotationUtils.findAnnotation(method, RetryLimit.class);
if (retryAn == null) {
return joinPoint.proceed();
}
// 如果包含注解放入缓存key为ip或者其他限流keyvalue为次数
Cache<String, AtomicInteger> cache = cacheMap.get(retryAn.limitTime());
String limitKey = retryAn.limitKey();
if (limitKey == null || limitKey.equals("ip")) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
limitKey = request.getRemoteAddr();
}else if (limitKey.equals("userId")) {
// 其他策略
}
// 如果缓存中没有这个ip访问过初始化为0
AtomicInteger atomicInteger = cache.get(limitKey, s -> new AtomicInteger(0));
if (atomicInteger.intValue() >= retryAn.limitCount()) {
throw new RuntimeException(retryAn.resMsg());
}
try {
return joinPoint.proceed();
} catch (BuinessException e) {
// 如果不是验证错误向上抛出
if (!e.getType().equals(ErrorType.RetryType)) {
throw e;
}
// 如果验证错误对atomic++
atomicInteger.incrementAndGet();
String msg = retryAn.resMsg() + ",重试次数:" + atomicInteger.intValue();
throw new RuntimeException(msg);
}
}
}

View File

@ -0,0 +1,26 @@
package cn.whaifree.springdemo.controller.interceptRetry.aspect;
import cn.whaifree.springdemo.controller.interceptRetry.ErrorType;
import cn.whaifree.springdemo.utils.ResVo;
import org.springframework.data.redis.connection.ReturnType;
import java.lang.annotation.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/11/9 21:57
* @注释
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RetryLimit {
int limitCount() default 3;
int limitTime() default 60;
String limitKey() default "ip";
String resMsg() default "请求过于频繁";
ErrorType errorType() default ErrorType.RetryType;
}

View File

@ -8,7 +8,7 @@ my:
spring:
datasource:
url: jdbc:mysql://localhost:3306/springTest?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
url: jdbc:mysql://localhost:3306/springTest?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver

View File

@ -4,10 +4,10 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId> <!--groupId表示当前 Maven 项目隶属的组织或公司-->
<groupId>com.whai</groupId> <!--groupId表示当前 Maven 项目隶属的组织或公司-->
<artifactId>LeetCode</artifactId> <!--当前 Maven 项目的名称-->
<version>1.0-SNAPSHOT</version><!--定义了 Maven 项目当前所处版本-->
<packaging>jar</packaging>
<packaging>pom</packaging>
<modules>
<module>ForJdk8</module>
<module>ForJdk17</module>

2
sdoih.bpmn Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1730813700188" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"/>