learn and grow up

自己封装模拟json全路径获取某个对象下某个变量的工具类

字数统计: 1k阅读时长: 5 min
2020/05/15 Share

写在前面

最近需要写一个针对controller内参数的数据权限校验组件,所以需要想办法获取都某个对象的某个变量(可能跨层级)的值,所以研究和封装了一套可以使用的工具类

代码

废话不多说,直接上代码,注释也写得比较明白了,就不赘述了

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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**
* 权限相关工具类
* @author yyt
*/
@Slf4j
public class AuthUtils {

//auth数据原型key
public static final String AUTH_DOMAIN_PROTOTYPE_KEY="domainPrototype";

//设置到request的属性,如有
public static void putToRequestAttributes(Object o){
HttpServletRequest request= SpringRequestHolderUtil.getRequest();
if(request!=null){
request.setAttribute(AUTH_DOMAIN_PROTOTYPE_KEY,o);
}
}

@Nullable
public static Object findInRequestAttributes(){
HttpServletRequest request= SpringRequestHolderUtil.getRequest();
if(request!=null){
return request.getAttribute(AUTH_DOMAIN_PROTOTYPE_KEY);
}
return null;
}

/**
* 判断是否需要拦截
* @param lookupPath
* @return
*/
public static boolean matches(String lookupPath, List<String> urlList) {
if(urlList==null){
return false;
}
for (String pattern : urlList) {
if (pathMatcher.match(pattern, lookupPath)) {
return true;
}
}
return false;
}

/**
* 获取对象指定属性的类型为T值,嵌套类请使用.来表示(如datas.person.name),最底层只支持list<T> 、T、T[]
* @param value
* @param fieldName
* @return
* @throws IllegalAccessException
*/
public static <T> Set<T> getTValueByField(Object value, String fieldName,Class<T> clz) throws IllegalAccessException {
if(value==null|| StringUtils.isEmpty(fieldName)){
return Collections.emptySet();
}


//拆分.,递归获取有效资源值
if(fieldName.contains(".")){
String[] strings=spiltStrBySpot(fieldName);
Object ob=getValueByFieldName(value,strings[0]);
return getTValueByField(ob,strings[1],clz);
}

Set<T> result = new HashSet<>();
if("_this_".equals(fieldName)){
result.add((T)value);
return result;
}


Object ob=getValueByFieldName(value,fieldName);
if(ob==null){
return Collections.emptySet();
}
Integer[] i=new Integer[]{};
if(ob.getClass() == clz){
//单个对象
result.add((T)ob);
}else if(ob.getClass().isArray()){
//数组
Object item=Arrays.asList((Object[])ob).get(0);
if(item.getClass() == clz){
result.addAll(Arrays.asList((T[])ob));
}else{
//TODO 按照规则不应该走到这里,走到这里是最后一层,只能强转为String
//result.add(());
throwException(item,clz);
}
}else if(ob instanceof Collection){
//list
Collection collection = (Collection) ob;
for(Object item : collection){
if(item.getClass() == clz){
result.add((T) item);
}else{
//TODO 按照规则不应该走到这里,走到这里是最后一层,只能强转为String
//result.add(item.toString());
throwException(item,clz);
}
}
}else{
throwException(ob,clz);
}
return result;
}
private static void throwException(Object item,Class clz){
log.error("class {} cannot cast to class {}",item.getClass(),clz.toString());
throw new ClassCastException("classCast error");
}

public static Object getValueByFieldName(Object value,String fieldName) throws IllegalAccessException {
if(value==null|| StringUtils.isEmpty(fieldName)){
return null;
}

//如果是字符串,则尝试转为JSON,再获取值
if(value.getClass()==String.class){
JSONObject jsonObject=JSONObject.parseObject((String)value);
return getValueByFieldName(jsonObject,fieldName);

}

if(value instanceof Map){
return ((Map) value).get(fieldName);
}

if(value instanceof Collection){
Set<Object> resultObject=new HashSet<>();
Collection collection = (Collection) value;
int index = 0;
for(Object item : collection){
Object o=getValueByFieldName(item,fieldName);
resultObject.add(o);
}
return resultObject;
}

if(value.getClass().isArray()){
Object[] vs=(Object[])value;
Set<Object> resultObject=new HashSet<>(vs.length);
for(Object item:vs){
Object o =getValueByFieldName(item,fieldName);
resultObject.add(o);
}
return resultObject;
}

Field[] fields = value.getClass().getDeclaredFields();
for(Field field: fields){
String name = field.getName();
if(!fieldName.equals(name)){
continue;
}
field.setAccessible(true);
Object resultValue = field.get(value);
return resultValue;
}
return null;
}



/**
* 对字符串中的.进行拆分返回第一段字符串和剩余字符串,如data.ls.name,返回data,ls.name
* @param name
* @return
*/
public static final String[] spiltStrBySpot(String name){

int i=name.indexOf(".");
if(i==-1){
return new String[]{name};
}
String name1=name.substring(0,i);
String name2=name.substring(i+1);
return new String[]{name1,name2};
}

//for quick test
public static void main(String[] args) throws IllegalAccessException {
/*String name="data.ls.name";
spiltStrBySpot(name);

List<Object> ls=new ArrayList<>();
Boolean b=ls.getClass().isArray();

Object[] os=new Object[]{};
b=os.getClass().isArray();*/
TestClass testClass=new TestClass();
testClass.strings=new String[]{"1","2","3"};
testClass.integers=new Integer[]{1,2,3};
testClass.i=100;
List<String> lists = new ArrayList<>();
lists.add("4");
lists.add("5");
testClass.lists=lists;
Set<String> strings2=getTValueByField(testClass,"strings",String.class);
Set<Integer> integers2=getTValueByField(testClass,"integers",Integer.class);
Set<String> lists2=getTValueByField(testClass,"lists",String.class);
Set<Integer> i=getTValueByField(testClass,"i",Integer.class);


log.error("Strings {}",strings2);
log.error("integers2 {}",integers2);
log.error("lists2 {}",lists2);
log.error("i {}",i);
//测试失败案例
Set<String> i2=getTValueByField(testClass,"i",String.class);

//JSONArray
return;
}

@Data
static class TestClass{
String[] strings;
Integer[] integers;
List<String> lists;
Integer i;
}

//路径是否拦截match类,出处:org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandlerExecutionChain
private static PathMatcher pathMatcher = new AntPathMatcher();
}
CATALOG
  1. 1. 写在前面
  2. 2. 代码