feat(leetcode): 添加多个 leetcode 问题的解决方案

- 新增了多个 leetcode 问题的 Java 解决方案,包括:
  - 问题 16: 最接近的三数之和
  - 问题 43: 字符串相乘
  - 问题 148: 排序链表
  - 问题274: H 指数
  - 问题 322: 零钱兑换
  - 问题 377: 组合总和Ⅳ
  - 问题474: 一和零
  - 问题 740: 删除并获得最大点数
- 更新了部分现有代码文件,优化了结构和注释

Default Changelist
.gitignore
AbstractClass.java
AbstractFactoryPattern.java
application.yaml
AProviderController.java
AService.java
BProviderController.java
BroomFilter.java
BService.java
CacheComparatorDemo.java
CacheConfig.java
CacheConstants.java
CacheDecoratorController.java
DynamicThreadPoolController.java
EventController.java
FactoryAndStrategy.java
FilterConfig.java
GlobalExceptionHandler.java
HttpStatus.java
IdempotenceController.java
LeetCode002.java
LeetCode16.java
LeetCode33.java
LeetCode43.java
LeetCode84.java
LeetCode148.java
LeetCode274.java
LeetCode322.java
LeetCode377.java
LeetCode474.java
LeetCode740.java
LimitType.java
ListNode.java
LoadBalanceConfig.java
MinioController.java
mvnw
mvnw.cmd
MyAutoConfiguration.java
P1.java
PersonProtocol.proto
pom.xml
protocolDemo.java
RabbitMQController.java
RateLimitAspect.java
RateLimiter.java
RedEnvelopeController.java
RedisConfig.java
RedisDataTest.java
redisson.yaml
RedissonConfig.java
RestConfig.java
ResVo.java
RobEnvelope.lua
SelfFilter.java
spring.factories
SpringDemoApplication.java
SpringDemoApplicationTests.java
SSEEmitter.java
TestController.java
UserService.java
WhiteListController.java
WxQrLoginController.java
工厂模式的几种类型,简单工厂、工厂方法、抽象工厂.md
Unversioned Files
D:\project\LeetCode\SpringCloud\ServiceA\src\main\resources\application.yaml
D:\project\LeetCode\SpringCloud\ServiceB\src\main\resources\application.yaml
D:\project\LeetCode\SpringCloud\ServiceA\pom.xml
D:\project\LeetCode\SpringCloud\ServiceB\pom.xml
D:\project\LeetCode\SpringCloud\pom.xml
D:\project\LeetCode\SpringCloud\ServiceA\src\main\java\com\whai\springcloud\servicea\ServiceAApplication.java
D:\project\LeetCode\SpringCloud\ServiceA\src\test\java\com\whai\springcloud\servicea\ServiceAApplicationTests.java
D:\project\LeetCode\SpringCloud\ServiceB\src\main\java\com\whai\springcloud\serviceb\ServiceBApplication.java
D:\project\LeetCode\SpringCloud\ServiceB\src\test\java\com\whai\springcloud\serviceb\ServiceBApplicationTests.java
D:\project\LeetCode\SpringCloud\ServiceA\src\test\java\com\whai\springcloud\springcloud\SpringCloudApplicationTests.java
D:\project\LeetCode\SpringCloud\ServiceB\src\test\java\com\whai\springcloud\springcloud\SpringCloudApplicationTests.java
This commit is contained in:
whaifree 2024-10-31 11:27:58 +08:00
parent 7ea67e280f
commit b6e5672f09
76 changed files with 1682 additions and 123 deletions

View File

@ -54,5 +54,6 @@ public class FactoryAndStrategy {
}
}
}

View File

@ -2,6 +2,11 @@ package cn.whaifree.designPattern.kama.CreateType.AbstractFactoryPattern;
public class AbstractFactoryPattern {
/**
* AbstractFactory--> ModernFactory --|
* --> ClassicFactory --|-->Sofa OR Chair
* @param args
*/
// https://kamacoder.com/problempage.php?pid=1077
public static void main(String[] args) {

View File

@ -0,0 +1,57 @@
### 简单工厂
一个工厂生产多种产品
```java
public static Product createProduct(String type) {
if ("A".equalsIgnoreCase(type)) {
return new ProductA();
} else if ("B".equalsIgnoreCase(type)) {
return new ProductB();
}
throw new IllegalArgumentException("Unknown product type");
}
```
### 工厂方法
对工厂抽象
```java
// 抽象工厂接口
interface Factory {
Product createProduct();
}
// 具体工厂A
class FactoryA implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
public static void main(String[] args) {
Factory factory = new FactoryA();
Product product = factory.createProduct();
product.use(); // 输出: Using Product A
}
```
### 抽象工厂
对产品再次抽象出不同属性
```java
// 产品族A接口
interface AbstractProductA {
void featureA();
}
// 具体产品A1
class ProductA1 implements AbstractProductA {
@Override
public void featureA() {
System.out.println("Feature A1");
}
}
```

View File

@ -0,0 +1,79 @@
package cn.whaifree.interview.PA;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/30 17:38
* @注释
*/
public class P1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt();
int m = in.nextInt();
/**
* 0 1 2
* 0 0 0 0
* 1 1 1 1
* 2 1 2 3
* 3 1 3 6
*/
int[] dp = new int[m + 1];
dp[0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 1; j <= m; j++) {
dp[j] = dp[j] + dp[j - 1];
}
}
System.out.println(dp[m]);
}
}
}
class p2{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
int res = 0;
for (int right = 0; right <= str.length(); right++) {
for (int left = 0; left < right; left++) {
String leftStr = str.substring(0, left);
String rightStr = str.substring(right, str.length());
String concat = leftStr + rightStr;
if (!concat.isEmpty() && huiwen(concat)) {
System.out.println(concat);
res++;
}
}
}
System.out.println(res);
}
public static boolean huiwen(String str){
int left = 0;
int right = str.length() - 1;
while (left < right) {
if (str.charAt(left) != str.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}

View File

@ -1,5 +1,7 @@
package cn.whaifree.leetCode;
import cn.whaifree.leetCode.model.ListNode;
import java.util.ArrayList;
/**
@ -109,13 +111,13 @@ public class LeetCode002 {
}
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
//class ListNode {
// int val;
// ListNode next;
// ListNode() {}
// ListNode(int val) { this.val = val; }
// ListNode(int val, ListNode next) { this.val = val; this.next = next; }
//}
class RefCountGC{
// 这个成员属性的唯一作用就是占用一点内存

View File

@ -0,0 +1,116 @@
package cn.whaifree.leetCode;
import org.junit.Test;
import cn.whaifree.leetCode.model.ListNode;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 14:35
* @注释
*/
public class LeetCode148 {
@Test
public void test() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{-1,5,3,4,0});
ListNode listNode1 = new Solution().sortList(listNode);
listNode1.printList();
}
class Solution {
/**
* 冒泡
* @param head
* @return
*/
public ListNode sortList(ListNode head) {
ListNode resList = new ListNode(-1);
ListNode tmpHead = new ListNode(-1, head);
ListNode pre = tmpHead;
ListNode index = pre; // 用于对比index.next和index.next的指针
ListNode markMaxPre = pre; // 用于标记一次循环的最大值
while (index.next != null) {
// 一次循环找到最大的一个
while (index.next != null) {
if (markMaxPre.next.val < index.next.val) {
markMaxPre = index;
}
index = index.next;
}
ListNode thisMax = markMaxPre.next;
markMaxPre.next = markMaxPre.next.next;
addToHead(resList, thisMax);
index = pre;
markMaxPre = pre;
}
return resList.next;
}
public void addToHead(ListNode pre, ListNode newNode) {
if (newNode == null) {
return;
}
ListNode next = pre.next;
pre.next = newNode;
newNode.next = next;
}
}
@Test
public void test2() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{4,2,1,3});
ListNode listNode1 = new Solution2().sortList(listNode);
listNode1.printList();
}
/**
* 归并排序
*/
class Solution2 {
// 我们使用 fast,slow 快慢双指针法奇数个节点找到中点偶数个节点找到中心左边的节点
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode fast = head.next; // 注意不要一起开始
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode BHead = slow.next;
slow.next = null;
ListNode sortAfterA = sortList(head);
ListNode sortAfterB = sortList(BHead);
return merge(sortAfterA, sortAfterB);
}
public ListNode merge(ListNode A, ListNode B) {
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while (A != null && B != null) {
if (A.val < B.val) {
cur.next = A;
A = A.next;
} else {
cur.next = B;
B = B.next;
}
cur = cur.next;
}
cur.next = A != null ? A : B;
return dummy.next;
}
}
}

View File

@ -0,0 +1,51 @@
package cn.whaifree.leetCode;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/28 14:50
* @注释
*/
public class LeetCode16 {
@Test
public void test() {
int[] nums = {4, 0, 5, -5, 3, 3, 0, -4, -5};
System.out.println(new Solution().threeSumClosest(nums, -2));
}
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int closeV = Integer.MAX_VALUE;
for (int left = 0; left < nums.length; left++) {
int mid = left + 1;
int right = nums.length - 1;
while (mid < right) {
int mv = nums[mid] + nums[left] + nums[right];
if (Math.abs(mv - target) < Math.abs(closeV - target)) {
closeV = mv;
}
if (mv > target) {
right = right - 1;
} else if (mv < target) {
mid = mid + 1;
} else {
return target;
}
}
}
return closeV;
}
}
}

View File

@ -0,0 +1,65 @@
package cn.whaifree.leetCode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/28 15:23
* @注释
*/
public class LeetCode43 {
@Test
public void test() {
String num1 = "12";
String num2 = "12";
Solution solution = new Solution();
String result = solution.multiply(num1, num2);
System.out.println(result);
}
class Solution {
/**
* 12345
* 678
*
* <img src="https://assets.leetcode-cn.com/solution-static/43/sol1.png">
* @param num1
* @param num2
* @return
*/
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
char[] char1 = num1.toCharArray();
char[] char2 = num2.toCharArray();
int[] ans = new int[char1.length + char2.length];
for (int i = char1.length - 1; i >= 0; i--) {
int V1 = char1[i] - '0';
for (int j = char2.length - 1; j >= 0; j--) {
int V2 = char2[j] - '0';
int product = V1 * V2;
int sum = ans[i + j + 1] + product;
int pre = sum / 10;
int retail = sum % 10;
ans[i + j + 1] = retail;
ans[i + j] = ans[i + j] + pre;
}
}
StringBuilder sb=new StringBuilder();
for (int i = 0; i < ans.length; i++) {
if (i == 0 && ans[i] == 0) {
continue;
}
sb.append(ans[i]);
}
return sb.toString();
}
}
}

View File

@ -0,0 +1,55 @@
package cn.whaifree.leetCode;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/30 16:21
* @注释
*/
public class LeetCode740 {
@Test
public void test() {
int[] nums = new int[]{2, 2, 3, 3, 3, 4};
int res = new Solution().deleteAndEarn(nums);
System.out.println(res);
}
class Solution {
/**
*
* 打家劫舍
* @param nums
* @return
*/
public int deleteAndEarn(int[] nums) {
int max = Arrays.stream(nums).max().getAsInt();
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
int[] sum = new int[max + 1]; // sum[i]表示选择i进行打劫的收益
// 每个数字出现的总点数能获取的总收益
map.forEach(
(k, v) -> sum[k] = v * k
);
int[] dp = new int[max + 1];
dp[0] = 0;
dp[1] = sum[1];
for (int i = 2; i <= max; i++) {
// dp[i-1] 不抢 dp[i-2] + 本节点
dp[i] = Math.max(dp[i - 1], dp[i - 2] + sum[i]);
}
return dp[max];
}
}
}

View File

@ -44,12 +44,15 @@ public class ListNode {
System.out.println("null!");
}
ListNode curr = head;
StringBuilder sb = new StringBuilder();
while (curr != null) {
System.out.print(curr.val + " ");
sb.append(curr.val).append("->");
curr = curr.next;
}
System.out.println(sb);
}
public void printList() {
printList(this);
}

View File

@ -0,0 +1,42 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 12:25
* @注释
*/
public class LeetCode274 {
@Test
public void test() {
int[] citations = {2};
int res = new Solution().hIndex(citations);
System.out.println(res);
}
class Solution {
/**
* 0 1 3 5 6
* @param citations
* @return
*/
public int hIndex(int[] citations) {
Arrays.sort(citations);
for (int i = 0; i < citations.length; i++) {
if (citations[i] >= citations.length - i) {
return citations.length - i;
}
}
return 0;
}
}
}

View File

@ -0,0 +1,51 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/30 15:12
* @注释
*/
public class LeetCode322 {
@Test
public void test() {
int[] coins = {2, 5};
int amount = 12;
Solution solution = new Solution();
int result = solution.coinChange(coins, amount);
System.out.println(result);
}
class Solution {
/**
* 无穷背包
* 0 1 2 3 4 5 6 7 8 9 10 11
* 1 1 1 2 3 4 5 6 7 8 9 10 11
* 2 1 1 1 2
* 5
*
* @param coins
* @param amount
* @return
*/
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int j = 1; j <= amount; j++) {
for (int i = 0; i < coins.length; i++) {
if (j >= coins[i] && dp[j - coins[i]] != Integer.MAX_VALUE) {
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
}
}
}
return dp[amount] == Integer.MAX_VALUE? -1 : dp[amount];
}
}
}

View File

@ -0,0 +1,80 @@
package cn.whaifree.redo.redo_all_241016;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/30 14:11
* @注释
*/
public class LeetCode33 {
class Solution {
/**
*
*
*
* @param nums
* @param target
* @return
*/
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[left] <= nums[mid]) {
// |4 5 6 7 8 | 0 1
// 目标值在4-6那么就右边指针mid-1 否则不在这个指针去另一个乱序区间找
// mid k
if (target < nums[mid] && target >= nums[left]) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
// 4 5 |0 1 2 3|
if (target > nums[mid] && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
}
class Solution1 {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[mid] >= nums[left]) {
// | mid k |
if (nums[left] <= target && target < nums[mid]) {
right = mid - 1;
}else {
left = mid + 1;
}
}else {
// | k mid |
if (nums[right] >= target && target > nums[mid]) {
left = mid + 1;
}else {
right = mid - 1;
}
}
}
return -1;
}
}
}

View File

@ -0,0 +1,59 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 14:04
* @注释
*/
public class LeetCode377 {
@Test
public void test() {
int[] nums = {1, 2, 3, 4};
int target = 4;
int result = new Solution().combinationSum4(nums, target);
System.out.println(result);
}
class Solution {
/**
* 背包容量 target+1
* 无穷背包
*
* 0-i 中任选装满背包的组合数
*
* 组合数有排序
*
* 0 1 2 3 4 5
* 1 1 1 1 1 1 1
* 2 1 1 2 2 3 3 dp[j]+dp[j-nums[i]] // 没有排序
* 3 1 1 2 3 4 5
*
* @param nums
* @param target
* @return
*/
public int combinationSum4(int[] nums, int target) {
/**
* 先遍历背包就可以让之前的背包都获得所有物品放入的可能性
*
* 计算dp[4]的时候结果集只有 {1,3} 这样的集合忽略了{3,1}
*/
int[] dp = new int[target + 1];
dp[0] = 1;
for (int j = 1 ; j <= target; j++) { // 有顺序先遍历背包
for (int i = 0; i < nums.length; i++) {
if (nums[i] <= j) {
dp[j] = dp[j] + dp[j - nums[i]];
}
}
}
return dp[target];
}
}
}

View File

@ -0,0 +1,61 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/30 15:42
* @注释
*/
public class LeetCode474 {
@Test
public void test() {
String[] strs = {"10", "0001", "1", "0"};
int m = 5;
int n = 3;
Solution solution = new Solution();
int result = solution.findMaxForm(strs, m, n);
System.out.println(result);
}
class Solution {
/**
*
* 从str 0-i中任意取满足j个0和k个1的最大长度
*
* @param strs
* @param m
* @param n
* @return
*/
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i < strs.length; i++) {
String str = strs[i];
int zeroCount = countZero(str);
int oneCount = str.length() - zeroCount;
for (int j = m; j >= 0; j--) {
for (int k = n; k >= 0; k--) {
if (j >= zeroCount && k >= oneCount) {
dp[j][k] = Math.max(dp[j][k], dp[j - zeroCount][k - oneCount] + 1);
}
}
}
}
return dp[m][n];
}
public int countZero(String str) {
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '0') {
count++;
}
}
return count;
}
}
}

View File

@ -0,0 +1,98 @@
package cn.whaifree.redo.redo_all_241016;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 11:15
* @注释
*/
public class LeetCode84 {
@Test
public void test() {
int[] heights = {1,1};
Solution solution = new Solution();
int i = solution.largestRectangleArea(heights);
System.out.println(i);
}
class Solution {
/**
* 15
*
*
*
* @param heights
* @return
*/
public int largestRectangleArea(int[] heights) {
int[] left = new int[heights.length];
int[] right = new int[heights.length];
// 对每个元素找到左边第一个比他小的
left[0] = -1;
for (int i = 0; i < heights.length; i++) {
int index = i - 1;
while (index >= 0 && heights[index] >= heights[i]) {
index = left[index];
}
left[i] = index;
}
// 对每个元素找到右边第一个比他小的
right[heights.length - 1] = heights.length;
for (int i = heights.length - 1; i >= 0; i--) {
int index = i + 1;
while (index <= heights.length - 1 && heights[index] >= heights[i]) {
index = right[index];
}
right[i] = index;
}
int maxArea = 0;
for (int i = 0; i < right.length; i++) {
maxArea = Math.max(maxArea, heights[i] * (right[i] - left[i] - 1));
}
return maxArea;
}
}
class Solution1 {
/**
* 29
*
*
*
* @param heights
* @return
*/
public int largestRectangleArea(int[] heights) {
int[] h = new int[heights.length + 2];
System.arraycopy(heights, 0, h, 1, heights.length);
heights = h;
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int res = 0;
for (int i = 1; i < heights.length; i++) {
while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
Integer pop = stack.pop();
if (!stack.isEmpty()) {
int right = i;
int left = pop;
int region = (right - left - 1) * heights[pop];
res = Math.max(res, region);
}
}
stack.push(i);
}
return res;
}
}
}

View File

@ -0,0 +1,10 @@
package cn.whaifree.tech.protocolDemo;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/28 20:10
* @注释
*/
public class protocolDemo {
}

View File

@ -0,0 +1,21 @@
syntax = "proto3";
option java_package = "com.example.protobufdemo";
option java_outer_classname = "PersonProto";
message Person {
int32 id = 1;
string name = 2;
string email = 3;
}
/*
<!-- Protobuf runtime library -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.21.9</version>
</dependency>
*/

View File

@ -0,0 +1,54 @@
<?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>com.whai.springcloud</groupId>
<artifactId>SpringCloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.whai.springcloud</groupId>
<artifactId>ServiceA</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ServiceA</name>
<description>ServiceA</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,17 @@
package com.whai.springcloud.servicea;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceAApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceAApplication.class, args);
}
}

View File

@ -0,0 +1,13 @@
package com.whai.springcloud.servicea.config;
import org.springframework.context.annotation.Configuration;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 18:31
* @注释
*/
@Configuration
public class LoadBalanceConfig {
}

View File

@ -0,0 +1,22 @@
package com.whai.springcloud.servicea.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 18:29
* @注释
*/
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder.build();
}
}

View File

@ -0,0 +1,43 @@
package com.whai.springcloud.servicea.controller;
import com.whai.springcloud.servicea.service.BService;
import jakarta.annotation.Resource;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 17:58
* @注释
*/
@RestController
public class AProviderController {
@Resource
private BService bService;
@GetMapping("/hello")
public String hello(String msg) {
System.out.println("A---->B");
return bService.getB(msg);
}
@Resource
private DiscoveryClient discoveryClient;
@Resource
private RestTemplate restTemplate;
@GetMapping("/getBDiscovey")
public String getBDiscovey(){
List<ServiceInstance> instances = discoveryClient.getInstances("service-b");
ServiceInstance serviceInstance = instances.get(0);
return restTemplate.getForObject("http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/getB?msg=hello", String.class);
}
}

View File

@ -0,0 +1,96 @@
package com.whai.springcloud.servicea.controller;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 21:51
* @注释
*/
@RestController
public class DynamicThreadPoolController {
static ThreadPoolExecutor executor ;
@Resource
private ConfigurableEnvironment environment;
@PostConstruct
public void init() {
executor = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors() * 4, 10, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("DynamicThreadPoolController");
return thread;
}
},
new ThreadPoolExecutor.AbortPolicy()
);
}
@GetMapping("/dynamicCoreSize")
public String dynamicCoreSize() {
return "Dynamic Core Size: " + executor.getCorePoolSize();
}
}
@Configuration
@RefreshScope
@EnableConfigurationProperties(ThreadConfigProperties.class) // 自动引入Properties会自动加入Context
class DynamicThreadPoolConfig implements ApplicationListener<EnvironmentChangeEvent> {
@Resource
ThreadConfigProperties threadConfigProperties;
@Override
public void onApplicationEvent(EnvironmentChangeEvent event) {
if (event.getKeys().contains("dynamic.coreSize")) {
// 获取值
Integer coreSize = threadConfigProperties.getCoreSize();
// 更新线程池
DynamicThreadPoolController.executor.setCorePoolSize(coreSize);
}
}
}
@ConfigurationProperties(prefix = "dynamic")
class ThreadConfigProperties {
int coreSize;
int maxSize;
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
public int getCoreSize() {
return coreSize;
}
public void setCoreSize(int coreSize) {
this.coreSize = coreSize;
}
}

View File

@ -0,0 +1,23 @@
package com.whai.springcloud.servicea.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 17:58
* @注释
*/
@Service
@FeignClient("ServiceB")
public interface BService {
@GetMapping("/getB")
String getB(@RequestParam("msg") String msg);
}

View File

@ -0,0 +1,40 @@
server:
port: 12120
spring:
application:
name: ServiceA
cloud:
nacos:
username: nacos
password: nacos
discovery:
namespace: 97ff159f-6177-4aab-b735-bd75458949d4
group: DEFAULT_GROUP
server-addr: localhost:8848
config:
# 配置所属命名空间的id我们配置名称为dev的id在命名空间列表查看id的值
namespace: 97ff159f-6177-4aab-b735-bd75458949d4
# 文件名,如果没有配置则默认为 ${spring.application.name}
prefix: springboot3-nacos
# 配置所属分组
group: DEFAULT_GROUP
# 后缀名,只支持 properties 和 yaml 类型
file-extension: yaml
# nacos服务器地址
server-addr: localhost:8848
# 配置自动刷新
refresh-enabled: true
# 启用远程同步配置
enable-remote-sync-config: true
config:
import:
- optional:nacos:${spring.application.name}.${spring.cloud.nacos.config.file-extension}
# Logger Config
logging:
level:
com.hexadecimal: debug
hexadecimal:
name: whai

View File

@ -0,0 +1,13 @@
package com.whai.springcloud.servicea;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ServiceAApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -0,0 +1,13 @@
package com.whai.springcloud.springcloud;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringCloudApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -0,0 +1,54 @@
<?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>com.whai.springcloud</groupId>
<artifactId>SpringCloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.whai.springcloud</groupId>
<artifactId>ServiceB</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ServiceB</name>
<description>ServiceB</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,17 @@
package com.whai.springcloud.serviceb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceBApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceBApplication.class, args);
}
}

View File

@ -0,0 +1,31 @@
package com.whai.springcloud.serviceb.controller;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 17:58
* @注释
*/
@RestController
public class BProviderController {
private final Environment environment;
@Autowired
public BProviderController(Environment environment) {
this.environment = environment;
}
// 提供服务
@RequestMapping("/getB")
public String getB(String msg) {
return StrUtil.format("BProviderController.getB, msg: {}, port: {}", msg, environment.getProperty("server.port"));
}
}

View File

@ -0,0 +1,10 @@
package com.whai.springcloud.serviceb.service;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 17:58
* @注释
*/
public interface AService {
}

View File

@ -0,0 +1,40 @@
spring:
application:
name: ServiceB
cloud:
nacos:
username: nacos
password: nacos
discovery:
namespace: 97ff159f-6177-4aab-b735-bd75458949d4
group: DEFAULT_GROUP
server-addr: localhost:8848
config:
# ?????????id????????dev?id??????????id??
namespace: 97ff159f-6177-4aab-b735-bd75458949d4
# ?????????????? ${spring.application.name}
# prefix: springboot3-nacos
# ??????
group: DEFAULT_GROUP
# ??????? properties ? yaml ??
file-extension: yaml
# nacos?????
server-addr: localhost:8848
# ??????
refresh-enabled: true
# ????????
enable-remote-sync-config: true
config:
import:
- optional:nacos:${spring.application.name}.${spring.cloud.nacos.config.file-extension}
# Logger Config
logging:
level:
com.hexadecimal: debug
hexadecimal:
name: whai
# --server.port=12139

View File

@ -0,0 +1,13 @@
package com.whai.springcloud.serviceb;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ServiceBApplicationTests {
@Test
void contextLoads() {
}
}

View File

@ -0,0 +1,13 @@
package com.whai.springcloud.springcloud;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringCloudApplicationTests {
@Test
void contextLoads() {
}
}

103
SpringCloud/pom.xml Normal file
View File

@ -0,0 +1,103 @@
<?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>3.3.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.whai.springcloud</groupId>
<artifactId>SpringCloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringCloud</name>
<description>SpringCloud</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
</properties>
<dependencies>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.14</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.boot/nacos-config-spring-boot-starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2023.0.1.3</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2023.0.1.3</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-consul-config</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-consul-discovery</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

View File

@ -9,10 +9,10 @@
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.whaifree</groupId>
<artifactId>springDemo</artifactId>
<artifactId>SpringDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springDemo</name>
<description>springDemo</description>
<name>SpringDemo</name>
<description>SpringDemo</description>
<url/>
<licenses>
<license/>

View File

@ -0,0 +1,44 @@
//package cn.whaifree.springdemo.config;
//
//import org.springframework.cache.Cache;
//import org.springframework.cache.CacheManager;
//import org.springframework.cache.annotation.EnableCaching;
//import org.springframework.cache.concurrent.ConcurrentMapCache;
//import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.transaction.annotation.EnableTransactionManagement;
//
//import java.util.Arrays;
//import java.util.Collection;
//
///**
// * @version 1.0
// * @Author whai文海
// * @Date 2024/10/25 22:44
// * @注释
// */
//@Configuration
//@EnableCaching()
//@EnableTransactionManagement()
//public class CacheConfig {
// @Bean
// public CacheManager cacheManager() {
// return new CustomCacheManager();
// }
//
// // 自定义的 CacheManager装饰每个缓存为 TransactionAwareCacheDecorator
// static class CustomCacheManager implements CacheManager {
// @Override
// public Cache getCache(String name) {
// Cache cache = new ConcurrentMapCache(name); // 使用 ConcurrentMapCache 实现缓存
// return new TransactionAwareCacheDecorator(cache); // 包装为 TransactionAwareCacheDecorator
// }
//
// @Override
// public Collection<String> getCacheNames() {
// return Arrays.asList("myCache"); // 设定缓存的名称
// }
// }
//
//}

View File

@ -0,0 +1,67 @@
//package cn.whaifree.springdemo.controller.CacheDecoratorDemo;
//
//import cn.hutool.extra.spring.SpringUtil;
//import jakarta.annotation.Resource;
//import org.springframework.cache.Cache;
//import org.springframework.cache.annotation.CachePut;
//import org.springframework.cache.annotation.Cacheable;
//import org.springframework.data.redis.cache.RedisCacheManager;
//import org.springframework.transaction.annotation.Transactional;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//
///**
// * @version 1.0
// * @Author whai文海
// * @Date 2024/10/25 22:43
// * @注释
// */
//@RestController
//public class CacheDecoratorController {
//
// @Resource
// private final RedisCacheManager cacheManager;
//
//
// public CacheDecoratorController(RedisCacheManager cacheManager) {
// this.cacheManager = cacheManager;
// }
//
// @RequestMapping("/getData")
// public String getData(Long id) {
// // 先从缓存中获取数据
// String data = SpringUtil.getBean(CacheDecoratorController.class).getDataById(id);
// return data;
// }
//
// @RequestMapping("/update")
// public void update(Long id, String newValue) {
// // 更新数据
// SpringUtil.getBean(CacheDecoratorController.class).updateData(id, newValue);
// }
//
// @Cacheable(value = "myCache", key = "#id")
// public String getDataById(Long id) {
// // 模拟获取数据操作
// return "Data for ID " + id;
// }
//
// @Transactional
// @CachePut(value = "myCache", key = "#id", condition = "#result != null")
// public String updateData(Long id, String newValue) {
// // 更新数据库操作
// // ...
// // 返回的新值会在事务提交后自动更新到缓存中
// // return newValue;
//
//
// // 或者手动操作缓存
// Cache myCache = cacheManager.getCache("myCache");
// if (myCache != null) {
// myCache.put(id, newValue);
// return null;
// }
// return null;
// }
//
//}

View File

@ -0,0 +1,57 @@
package cn.whaifree.springdemo.utils.BroomFilter;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/30 21:01
* @注释
*/
@Component
public class BroomFilter{
RedisTemplate redisTemplate = SpringUtil.getBean("redisTemplate", RedisTemplate.class);
private int hashCount; // 哈希函数数量
private int size; // 位图大小
private String key; // Redis 中的 Bitmap
public BroomFilter() {
this.hashCount = 10;
this.size = 1000000;
this.key = "broomFilter";
}
public boolean contains(Object o) {
// 计算Hashcode
int[] hash = getHash(o);
for (int i : hash) {
// 检查位图中对应位置是否为true
if (!redisTemplate.opsForValue().getBit(key, i)) {
return false;
}
}
return true;
}
public void addToBroom(Object o) {
// 计算Hashcode
int[] hash = getHash(o);
for (int i : hash) {
// 设置位图中对应位置为true
redisTemplate.opsForValue().setBit(key, i, true);
}
}
// 生成哈希值
private int[] getHash(Object value) {
int[] result = new int[hashCount];
for (int i = 0; i < hashCount; i++) {
result[i] = Math.abs(value.hashCode() + i * 123456) % size;
}
return result;
}
}

View File

@ -1,8 +1,11 @@
package cn.whaifree.springdemo.RedisData;
import cn.hutool.extra.spring.SpringUtil;
import cn.whaifree.springdemo.utils.BroomFilter.BroomFilter;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.BitFieldSubCommands;
@ -23,6 +26,8 @@ public class RedisDataTest {
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private SpringUtil springUtil;
@Test
public void testHyperloglog() {
@ -68,8 +73,6 @@ public class RedisDataTest {
// 创建BitFieldSubCommands对象用于执行更复杂的位图操作
BitFieldSubCommands subCommands = BitFieldSubCommands.create();
// 添加一个指令到subCommands中获取第11个位从0开始计数的64位整型值
@ -114,4 +117,30 @@ public class RedisDataTest {
}
}
@Test
public void testbitMap2() {
BroomFilter broomFilter = new BroomFilter();
broomFilter.addToBroom("obj1");
broomFilter.addToBroom("obj2");
broomFilter.addToBroom("obj3");
broomFilter.addToBroom("obj4");
broomFilter.addToBroom("obj5");
broomFilter.addToBroom("obj6");
broomFilter.addToBroom("obj7");
broomFilter.addToBroom("obj8");
broomFilter.addToBroom("obj9");
broomFilter.addToBroom("obj10");
broomFilter.addToBroom("obj11");
broomFilter.addToBroom("obj12");
broomFilter.addToBroom("obj13");
broomFilter.addToBroom("obj14");
broomFilter.addToBroom("obj15");
System.out.println(broomFilter.contains("obj1"));
System.out.println(broomFilter.contains("obj16"));
}
}

View File

@ -1,43 +0,0 @@
package cn.whaifree.springdemo.config;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.transaction.TransactionAwareCacheDecorator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.Arrays;
import java.util.Collection;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/25 22:44
* @注释
*/
@Configuration
@EnableCaching()
@EnableTransactionManagement()
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new CustomCacheManager();
}
// 自定义的 CacheManager装饰每个缓存为 TransactionAwareCacheDecorator
static class CustomCacheManager implements CacheManager {
@Override
public Cache getCache(String name) {
Cache cache = new ConcurrentMapCache(name); // 使用 ConcurrentMapCache 实现缓存
return new TransactionAwareCacheDecorator(cache); // 包装为 TransactionAwareCacheDecorator
}
@Override
public Collection<String> getCacheNames() {
return Arrays.asList("myCache"); // 设定缓存的名称
}
}
}

View File

@ -1,66 +0,0 @@
package cn.whaifree.springdemo.controller.CacheDecoratorDemo;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/25 22:43
* @注释
*/
@RestController
public class CacheDecoratorController {
private final SpringUtil springUtil;
private final RedisCacheManager cacheManager;
public CacheDecoratorController(SpringUtil springUtil, RedisCacheManager cacheManager) {
this.springUtil = springUtil;
this.cacheManager = cacheManager;
}
@RequestMapping("/getData")
public String getData(Long id) {
// 先从缓存中获取数据
String data = SpringUtil.getBean(CacheDecoratorController.class).getDataById(id);
return data;
}
@RequestMapping("/update")
public void update(Long id, String newValue) {
// 更新数据
SpringUtil.getBean(CacheDecoratorController.class).updateData(id, newValue);
}
@Cacheable(value = "myCache", key = "#id")
public String getDataById(Long id) {
// 模拟获取数据操作
return "Data for ID " + id;
}
@Transactional
@CachePut(value = "myCache", key = "#id", condition = "#result != null")
public String updateData(Long id, String newValue) {
// 更新数据库操作
// ...
// 返回的新值会在事务提交后自动更新到缓存中
// return newValue;
// 或者手动操作缓存
Cache myCache = cacheManager.getCache("myCache");
if (myCache != null) {
myCache.put(id, newValue);
return null;
}
return null;
}
}