SpringBoot基於切面來攔截@PathVariable引數及丟擲異常全域性處理方法
阿新 • • 發佈:2020-11-02
SpringBoot基於切面來攔截@PathVariable引數及丟擲異常全域性處理方法
微信小程式的介面驗證防止非法請求,登入的時候獲取openId生成一個七天有效期token存入redis中。
後續每次請求都需要把token作為引數傳給後臺介面進行驗證,為了方便使用@PathVariable 直接將引數做為路徑傳過來 不用每一次都新增param引數也方便前端介面的請求。
例如:
@ApiOperation(value = "小程式登入") @PostMapping("/login") public AntdResponse login(@RequestParam String username, @RequestParam String password, @RequestParam String openId) throws Exception { String st = wxTokenService.passport(username, password); //省略。。。。。 String wxToken = IdUtil.simpleUUID(); data.put("wxToken", wxToken); wxTokenService.saveWxTokenToRedis(wxToken, openId); return new AntdResponse().success("登入成功,登入有效期七天").data(data); } @ApiOperation(value = "預約訂單") @PostMapping("/{wxToken}/addOrder") public AntdResponse addOrder(@PathVariable String wxToken, @RequestBody ProductOrderDto productOrderDto){ String openId = wxTokenService.getOpenIdByWxToken(wxToken); orderService.addOrder(openId, productOrderDto); return new AntdResponse().success("預約訂單成功"); }
為了方便統一驗證,基於切面來實現資料的驗證。
package cn.pconline.antd.smallshop.interceptor; import cn.pconline.antd.common.exception.WxTokenException; import cn.pconline.antd.smallshop.service.IWxTokenService; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.HandlerMapping; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * @Description 微信小程式登入攔截 * @Author jie.zhao * @Date 2020/10/26 18:08 */ @Component @Aspect public class WxMiniInterceptor { @Autowired private IWxTokenService wxTokenService; //這裡需要把登入的請求控制器排除出去 @Pointcut("within (cn.pconline.antd.smallshop.wxmini..*) && !within(cn.pconline.antd.smallshop.wxmini.WxMiniLoginController)") public void pointCut() { } @Around("pointCut()") public Object trackInfo(ProceedingJoinPoint joinPoint) throws Throwable { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); Map pathVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); String wxToken = (String) pathVariables.get("wxToken"); if (wxToken == null) { throw new WxTokenException("微信小程式令牌引數缺失!"); } String openId = wxTokenService.getOpenIdByWxToken(wxToken); if (openId == null || "".equals(openId)) { throw new WxTokenException("登入失效,請重新登入!"); } return joinPoint.proceed(); } }
全域性異常處理
@RestControllerAdvice @Order(value = Ordered.HIGHEST_PRECEDENCE) public class GlobalExceptionHandler { @ExceptionHandler(value = WxTokenException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public AntdResponse handleWxTokenException(WxTokenException e) { log.error("微信Token攔截異常資訊:", e); return new AntdResponse().message(e.getMessage()).code(Code.C500.getCode().toString()).status(ResponseStat.ERROR.getText()); } }
package cn.pconline.antd.common.exception;
/**
* 微信授權token異常
*/
public class WxTokenException extends RuntimeException {
private static final long serialVersionUID = -3608667856397125671L;
public WxTokenException(String message) {
super(message);
}
}
這裡需要注意的是 WxTokenException 要繼承RuntimeException而不是Exception,否則的話會報UndeclaredThrowableException。
java.lang.reflect.UndeclaredThrowableException
at com.insigmaunited.lightai.controller.UserController$$EnhancerBySpringCGLIB$$e4eb8ece.profile(<generated>)
異常原因:
我們的異常處理類,實際是 動態代理的一個實現。
如果一個異常是檢查型異常並且沒有在動態代理的介面處宣告,那麼它將會被包裝成UndeclaredThrowableException.
而我們定義的自定義異常,被定義成了檢查型異常,導致被包裝成了UndeclaredThrowableException
java.lang.reflect.UndeclaredThrowableException的解決