場景
我們團隊現在面臨著多端數據接口對接的問題,為了解決這個問題我們定義了接口對接的規范,
前端(安卓,Ios,web前端)和后端進行了數據的格式規范的討論,確定了json的數據格式:
1
2
3
4
5
6
7
8
9
10
|
{ "code" : "200" , "data" :{ "" : "" }, "message" : "處理成功" } { "code" : "300" , "data" :{ "" : "" }, "message" : "沒有此用戶" } |
code代表請求處理狀態:200為正常處理,300為業務異常處理,500就系統異常處理。
data代表后臺返回的數據。
message后臺的提示語,正常或者成功的時候會返回錯誤原因。
問題來了
讓每一個人對每一個json視圖的返回值都要進行包裝的話,豈不很麻煩,
這個時候AOP就登場了,我們可以利用aop的思想在請求返回json之后還未response到客戶端時為其包裝上一層。
實現步驟
啟用aop
1
2
3
4
5
6
7
|
<!-- base- package 如果多個,用“,”分隔 --> <context:component-scan base- package = "com.we,cn.isuyang" > <context:include-filter type= "annotation" expression= "org.springframework.stereotype.Service" /> <context:exclude-filter type= "annotation" expression= "org.springframework.stereotype.Controller" /> </context:component-scan> <!-- 打開aop 注解 --> <aop:aspectj-autoproxy /> |
創建切面
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
|
/** * json返回切面 * <p> * 用于處理json返回結果 * * @author ZhuangJunxiang(529272571@qq.com) * @Date 2017年4月28日 */ @Component @Aspect @Order ( 2 ) public class JsonReturnAspect { /** * 設置分頁默認值 * <p> * 如果分頁沒有設置值,則默認從系統的配置文件里讀取 * * @param pjp 切點 */ @Around (value = "@annotation(org.springframework.web.bind.annotation.ResponseBody)" ) @Order ( 1 ) public Object warp( final ProceedingJoinPoint pjp) throws Throwable { Object list = pjp.proceed(); if (isReturnVoid(pjp)) { HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getResponse(); if (isNeedWrap(pjp)) { response.getWriter().write(JsonUtil.toJson(success( "操作成功" ))); } return list; } return data(list); } /** * 是否需要包裹 * * @param pjp 切點 * * @return true表示不需要 */ private boolean isNeedWrap( final ProceedingJoinPoint pjp) { Method method = AspectUtil.getMethod(pjp); return !method.isAnnotationPresent(Void. class ); } /** * 是否返回空 * * @param pjp * @return true:返回類型為void,false:返回類型不是void */ private boolean isReturnVoid(ProceedingJoinPoint pjp) { Method method = AspectUtil.getMethod(pjp); Class<?> returnType = method.getReturnType(); return "void" .equals(returnType.getName()); } /** * 構建成功后的返回對象 * <p> * 消息為空時,不提示,不為空則進行提示 * * @param message 成功消息 * @return json對象 */ public static Map<String, Object> success( final String message) { Map<String, Object> map = MapUtil.map(); map.put( "code" , StatusCode.SUCCESS.key()); map.put( "message" , message); map.put( "data" , "" ); return map; } /** * 構建成功后的返回對象 * <p> * 消息為空時,不提示,不為空則進行提示 * * @param message 成功消息 * @return json對象 */ public static Map<String, Object> data( final Object data) { Map<String, Object> map = MapUtil.map(); map.put( "code" , StatusCode.SUCCESS.key()); map.put( "message" , message); map.put( "data" ,data); return map; } } |
分析一下
@Component 這個注解表示將這個對象交給spring容器進行實例化
@Aspect 表示這是一個切面類
@Around(value = "@annotation(org.springframework.web.bind.annotation.ResponseBody)")
表示凡是方法上帶有@ResponseBody注解的都是這個切面中切點,換句話說都會被攔截。
注意:
warp方法中的ProceedingJoinPoint參數只有環繞通知才可以使用JoinPoint的子類ProceedingJoinPoint,
各連接點類型可以調用代理的方法,并獲取、改變返回值。否則就是用JoinPoint。
情況一:假設conroller類中的函數不需要任何返回值
比如:我對一個實體對象進行更新我只需要把更新結果返回去就OK了,不需要填充數據
返回的數據格式:
1
2
3
4
5
|
{ "code" : "200" , "data" : "" , "message" : "處理成功" } |
實現思路:
在切面處理類的處理函數中獲取到這個函數的返回值類型如果是void就返回指定格式的數據。
上面的isReturnVoid()就是做這樣的一個判斷。
你只需要將函數的返回值為void即可:
1
2
3
4
5
|
@RequestMapping @ResponseBody public void add( long matchId, Model model) { slxSignupViewService.setAddInfo(matchId, model); } |
情況二:假設conroller類中的函數的返回值不需要包裹呢
比如:
某些前端插件以及第三方對接(支付)的返回值是規定好的,
以及下載文件,我們這些就是多余了,
實現思路:
自定一個@Void的注解:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * 空注解 * <p> * 用于標識將controller層中的返回值原模原樣的out出去 * * @author WangSen(wangsenhehe@126.com) * @Date 2017年8月17日 */ @Target ({ ElementType.METHOD }) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface Void { } |
在controller層的方法上添加這個注解
1
2
3
4
5
6
7
8
9
|
/** * 支付完成 */ @Void @ResponseBody @RequestMapping public void payFinish() throws IOException { alipayViewService.payFinish(); } |
在這個切面處理類上判斷這個函數是否包含這個注解如果包含
就不作處理,原模原樣的返回出去。
JsonReturnAspect類中的isNeedWrap()方法就是處理這個需求。
總結
以上所述是小編給大家介紹的自定義spring mvc的json視圖實現思路解析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://www.cnblogs.com/wangsen/p/8031283.html