Chuenhung的个人网站

chuenhung.github.io

需求

项目中共用了一个Redis,而项目中部分代码使用了JetCache的@Cached注解。所以需要给@Cached动态配置area属性值,用来区分dev和test环境。

问题

自定义注解的属性值需要常量值,即static final修饰,直接通过配置文件不可行。

解决方案

1、使用AOP切面拦截使用注解的方法,动态修改注解的属性值。切面1。
2、注解的底层一般也有一个AOP切面。切面2。
需要确保切面1在切面2之前执行 (使用@order(int)注解,值越小越先执行)。

示例代码

yml配置文件:

1
2
testAop:
actionValue: 测试-10101908-action

切面1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
@Aspect
@Slf4j
@Order(1)
public class MyAspect {

@Value("${testAop.actionValue}")
private String actionValue;

@Before(value = "@annotation(webLogAnnotation)")
public void aopTest(WebLogAnnotation webLogAnnotation) throws Throwable {
InvocationHandler invocationHandler = Proxy.getInvocationHandler(webLogAnnotation);
Field value = invocationHandler.getClass().getDeclaredField( "memberValues");
value.setAccessible(true);
Map<String,Object> memberValues = (Map<String,Object>) value.get(invocationHandler);
memberValues.put("action", actionValue);
log.info("MyAspect.aopTest memberValues:{}",memberValues);
}
}

切面2:

1
2
3
4
5
6
7
8
9
@Component
@Aspect
@Order(2)
public class WebLogAspect{

@Around("@annotation(webLogAnnotation)")
public Object logAround(ProceedingJoinPoint joinPoint, WebLogAnnotation webLogAnnotation) throws Throwable {
// do something......
}

controller:

1
2
3
4
5
@PostMapping("/getList")
@WebLogAnnotation(logType = "30010051",action = "通讯录-分页查询列表action",description = "'通讯录-分页查询列表desc'")
public PageResponseMsg<AddressBookVo> getList(@RequestBody @Valid PageRequest<QueryAddressBookListReq> pageDto){
// do something......
}

经测试,WebLogAspect中成功获取到MyAspect 中修改的注解参数值。如下所示:
在这里插入图片描述
遗留问题:

  • 必须传入该参数才可以获取到修改后的值
  • 通过反射方法method.getAnnotation(WebLogAnnotation.class)获取到的是原始值。若@Cached底层也是通过反射实现,则修改不了。

通过反射动态修改自定义注解属性值SpringBoot实现对自定义注解的切面自定义注解属性动态赋值

SpringBoot校验List失效解决方法

失效场景示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequestMapping("/v1/jx/flowSummary")
@Slf4j
public class JxFlowSummaryController {

@Operation(summary = "批量修改原始得分")
@PostMapping("/updateScore")
public ResponseDto batchUpdateScore(@RequestBody @Valid List<BatchUpdateScoreDto> dtoList) {
// jxFlowSummaryService.batchUpdateScore(dtoList);
return ResponseUtil.wrapSuccess(null);
}
}

解决方法一:在controller上加上@Validated注解

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequestMapping("/v1/jx/flowSummary")
@Slf4j
@Validated
public class JxFlowSummaryController {

@Operation(summary = "批量修改原始得分")
@PostMapping("/updateScore")
public ResponseDto batchUpdateScore(@RequestBody @Valid List<BatchUpdateScoreDto> dtoList){
return ResponseUtil.wrapSuccess(null);
}
}

解决方法一:校验效果如下
在这里插入图片描述

解决方法二:自定义实现一个ValidatedList,接口参数使用ValidatedList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import lombok.Data;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
* 自定义校验list
*
* @author liquanhong
* @createTime 2023/11/23
*/
@Data
public class ValidatedList<E> implements List<E>, Serializable {

@Valid
private List<E> list = new LinkedList<>();

@Override
public int size() {
return list.size();
}

@Override
public boolean isEmpty() {
return list.isEmpty();
}

@Override
public boolean contains(Object o) {
return list.contains(o);
}

@Override
public Iterator<E> iterator() {
return list.iterator();
}

@Override
public Object[] toArray() {
return list.toArray();
}

@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}

@Override
public boolean add(E e) {
return list.add(e);
}

@Override
public boolean remove(Object o) {
return list.remove(o);
}

@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}

@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}

@Override
public boolean addAll(int index, Collection<? extends E> c) {
return list.addAll(index, c);
}

@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}

@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}

@Override
public void clear() {
list.clear();
}

@Override
public E get(int index) {
return list.get(index);
}

@Override
public E set(int index, E element) {
return list.set(index, element);
}

@Override
public void add(int index, E element) {
list.add(index, element);
}

@Override
public E remove(int index) {
return list.remove(index);
}

@Override
public int indexOf(Object o) {
return list.indexOf(o);
}

@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}

@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}

@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}

@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}

// List改为了 ValidatedList
@Operation(summary = "批量修改原始得分")
@PostMapping("/updateScore")
public ResponseDto batchUpdateScore(@RequestBody @Valid ValidatedList<BatchUpdateScoreDto> dtoList){
return ResponseUtil.wrapSuccess(null);
}

解决方法二:校验效果如下
在这里插入图片描述

附:校验基本数据类型和String类型的方法参数时也需要在类上加@Validated

参考链接

狂神说-Elasticsearch 7.6入门学习笔记

狂神说-Elasticsearch 7.6入门学习笔记

Windows Elasticsearch IK分词器插件启动报错

错误如下:

1
java.security.Acces ControlException: access denied (\ik\config\IKAnalyzer.cfg.xml" "read")

原因:
D:\Program Files文件夹下的所有文件默认都是只读权限。
解决方法:
Elasticsearch不要安装在 Program Files 、Program Files (x86) 这些目录下。

参考链接

阅读全文 »

在Java中将类作为参数传递(泛型)

1
2
3
4
5
6
7
示例代码如下:
// 示例方法
public <T> void downloadErrorData(Class<T> className){
List<T> downloadList = new ArrayList<>();
}
// 调用示例
importService.downloadErrorData(PropositionExpertImportVo.class);
阅读全文 »
0%