最近基於AOP做了一個攔截並能夠返回錯誤信息到前端的示例程序,目標
1.通過自定義注解所帶參數,進入切面判斷是否合法
2.合法的繼續訪問
3.不合法的通過自定義異常向前端返回錯誤信息
我能想到的有三個思路
1.filter實現
2.基於HttpServletResponse,也可以重定向
3.自定義異常+@ControllerAdvice
第一種方法,類似SpringSecurity,我沒那么做。
第二種方法,無法在切面里獲取HttpServletResponse對象,或是HttpServletResponse為null,所以我放棄了,我嘗試了如下方法
ServletWebRequest servletContainer = (ServletWebRequest)RequestContextHolder.getRequestAttributes();
HttpServletResponse response = servletContainer.getResponse();
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); ServletWebRequest servletWebRequest=new ServletWebRequest(request); HttpServletResponse response=servletWebRequest.getResponse();
都不行
第三種方法,調通了,自己還無法評估優劣
源代碼地址如下:https://github.com/flyingJiang/InterceptorDemo
接下來我挑主要的說,順便各位幫忙看看這樣做是否有缺陷
首先,是切面。我希望實現,滿足條件就禁止用戶進入api,如果不滿足就繼續。這個@Around注解,用Before能實現嗎?我沒能實現,是不是我太糾結return?
package com.flying.aspect; import com.flying.annotation.Auth; import com.flying.exception.MyException; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Aspect @Component public class AuthInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(AuthInterceptor.class); private static final String NO_AUTH = "沒有權限哦!這是一個切面!"; @Autowired ControllerExceptionHandler controllerExceptionHandler; @Around("execution(public * com.flying.controller.*.*(..)) && @annotation(auth)") public Object checkAuth(ProceedingJoinPoint pjp, Auth auth) throws Throwable{ MethodSignature signature = (MethodSignature) pjp.getSignature(); String authString = auth.value(); LOGGER.info("checkAuth,method: {}, clientCode={}", signature.getMethod().getName(), authString); // Assume that only yes and no permissions are required for authentication if (authString.equals("yes")){ LOGGER.warn("checkAuth,{}", NO_AUTH); return controllerExceptionHandler.handleNoAuthException(new MyException(NO_AUTH)); }else{ return pjp.proceed(); } } }
再者就是我引入切面異常,這樣做是不是不好,還有什么號方法嗎?
package com.flying.aspect; import com.flying.constant.HttpCodeEnum; import com.flying.entity.Result; import com.flying.exception.MyException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @ControllerAdvice public class ControllerExceptionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ControllerExceptionHandler.class); @ExceptionHandler({ MyException.class }) @ResponseBody public Result handleNoAuthException(MyException e) { LOGGER.error("handle handleNoAuthException, ex={}", e.getMessage(), e); Result result = Result.build(HttpCodeEnum.CODE_401.getValue(),e.getMessage()); return result; } }
結果截圖
這是bug嗎,這個怎么刪除?