您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何實(shí)現(xiàn)自定義spring mvc的json視圖”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何實(shí)現(xiàn)自定義spring mvc的json視圖”這篇文章吧。
場(chǎng)景
我們團(tuán)隊(duì)現(xiàn)在面臨著多端數(shù)據(jù)接口對(duì)接的問(wèn)題,為了解決這個(gè)問(wèn)題我們定義了接口對(duì)接的規(guī)范,
前端(安卓,Ios,web前端)和后端進(jìn)行了數(shù)據(jù)的格式規(guī)范的討論,確定了json的數(shù)據(jù)格式:
{ "code":"200", "data":{"":""}, "message":"處理成功" } { "code":"300", "data":{"":""}, "message":"沒有此用戶" }
code代表請(qǐng)求處理狀態(tài):200為正常處理,300為業(yè)務(wù)異常處理,500就系統(tǒng)異常處理。
data代表后臺(tái)返回的數(shù)據(jù)。
message后臺(tái)的提示語(yǔ),正?;蛘叱晒Φ臅r(shí)候會(huì)返回錯(cuò)誤原因。
問(wèn)題來(lái)了
讓每一個(gè)人對(duì)每一個(gè)json視圖的返回值都要進(jìn)行包裝的話,豈不很麻煩,
這個(gè)時(shí)候AOP就登場(chǎng)了,我們可以利用aop的思想在請(qǐng)求返回json之后還未response到客戶端時(shí)為其包裝上一層。
實(shí)現(xiàn)步驟
啟用aop
<!-- base-package 如果多個(gè),用“,”分隔 --> <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 />
創(chuàng)建切面
/** * json返回切面 * <p> * 用于處理json返回結(jié)果 * * @author ZhuangJunxiang(529272571@qq.com) * @Date 2017年4月28日 */ @Component @Aspect @Order(2) public class JsonReturnAspect { /** * 設(shè)置分頁(yè)默認(rèn)值 * <p> * 如果分頁(yè)沒有設(shè)置值,則默認(rèn)從系統(tǒng)的配置文件里讀取 * * @param pjp 切點(diǎn) */ @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 切點(diǎn) * * @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()); } /** * 構(gòu)建成功后的返回對(duì)象 * <p> * 消息為空時(shí),不提示,不為空則進(jìn)行提示 * * @param message 成功消息 * @return json對(duì)象 */ 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; } /** * 構(gòu)建成功后的返回對(duì)象 * <p> * 消息為空時(shí),不提示,不為空則進(jìn)行提示 * * @param message 成功消息 * @return json對(duì)象 */ 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 這個(gè)注解表示將這個(gè)對(duì)象交給spring容器進(jìn)行實(shí)例化
@Aspect 表示這是一個(gè)切面類
@Around(value = "@annotation(org.springframework.web.bind.annotation.ResponseBody)")
表示凡是方法上帶有@ResponseBody注解的都是這個(gè)切面中切點(diǎn),換句話說(shuō)都會(huì)被攔截。
注意:
warp方法中的ProceedingJoinPoint參數(shù)只有環(huán)繞通知才可以使用JoinPoint的子類ProceedingJoinPoint,
各連接點(diǎn)類型可以調(diào)用代理的方法,并獲取、改變返回值。否則就是用JoinPoint。
情況一:假設(shè)conroller類中的函數(shù)不需要任何返回值
比如:我對(duì)一個(gè)實(shí)體對(duì)象進(jìn)行更新我只需要把更新結(jié)果返回去就OK了,不需要填充數(shù)據(jù)
返回的數(shù)據(jù)格式:
{ "code":"200", "data":"", "message":"處理成功" }
實(shí)現(xiàn)思路:
在切面處理類的處理函數(shù)中獲取到這個(gè)函數(shù)的返回值類型如果是void就返回指定格式的數(shù)據(jù)。
上面的isReturnVoid()就是做這樣的一個(gè)判斷。
你只需要將函數(shù)的返回值為void即可:
@RequestMapping @ResponseBody public void add(long matchId, Model model) { slxSignupViewService.setAddInfo(matchId, model); }
情況二:假設(shè)conroller類中的函數(shù)的返回值不需要包裹呢
比如:
某些前端插件以及第三方對(duì)接(支付)的返回值是規(guī)定好的,
以及下載文件,我們這些就是多余了,
實(shí)現(xiàn)思路:
自定一個(gè)@Void的注解:
/** * 空注解 * <p> * 用于標(biāo)識(shí)將controller層中的返回值原模原樣的out出去 * * @author WangSen(wangsenhehe@126.com) * @Date 2017年8月17日 */ @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Void { }
在controller層的方法上添加這個(gè)注解
/** * 支付完成 */ @Void @ResponseBody @RequestMapping public void payFinish() throws IOException { alipayViewService.payFinish(); }
在這個(gè)切面處理類上判斷這個(gè)函數(shù)是否包含這個(gè)注解如果包含
就不作處理,原模原樣的返回出去。
JsonReturnAspect類中的isNeedWrap()方法就是處理這個(gè)需求。
以上是“如何實(shí)現(xiàn)自定義spring mvc的json視圖”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。