思路: 为了灵活性 aop采用的是注解式的实现方式 因考虑到部分接口只需要判断是否登录,而有些接口则强制登录。
创建自定义未登录异常,创建全局异常拦截,当未登录时直接主动发起异常,即可对未登录异常进行拦截并进行返回,以达到强制登录的效果。
通过反射可获取当前运行中方法中的参数,鉴权完成后 直接对当前参数赋值,即可。也可利用aop+反射 对接口返回值进行处理。
aop 相关代码:
此处对未登录用户返回ID为0,用以判断
/** * @author furutaka */ @Aspect @Component @Slf4j public class CheckLoginAopImpl { @Pointcut("@annotation(com.lottery.api.annotation.CheckLoginAop)") public void CheckLoginAop(){ } @Before("CheckLoginAop()") public void before(JoinPoint joinPoint) throws MemberException { // MessageInfo messageInfo=new BaseModel(); Object[]o=joinPoint.getArgs(); HttpServletRequest request=(HttpServletRequest)o[0]; String phone = request.getHeader("phone"); NutMap nutMap= RedisUtils.getLoginInfo(phone); MemberInfo info=(MemberInfo)o[1]; if (nutMap==null||!nutMap.getString("token").equals(request.getHeader("token"))){ log.info("用户不存在"); info.setId(0L); info.setIsUpdateToken(Constants.TYPE_ONE); }else{ info.setId(nutMap.getLong("memberId")); info.setExpiredTime(nutMap.getTime("expiredTime")); info.setPhone(phone); info.setBaseToken(request.getHeader("token")); info.setIsUpdateToken(Constants.TYPE_ONE); Long time=System.currentTimeMillis(); } @After("CheckLoginAop()") public void after(JoinPoint joinPoint){ } /** * 后置通知 * @param ret * @throws Throwable */ @AfterReturning(returning = "ret", pointcut = "CheckLoginAop()") public void afterReturning(JoinPoint joinPoint,Object ret) throws Throwable { // 处理完请求,返回内容 // ReQueryResult result =(ReQueryResult)ret; // Object[]o=joinPoint.getArgs(); // MemberInfo info=(MemberInfo)o[1]; // result.setIsUpdateToken(Constants.TYPE_ONE); // if (info!=null&&info.getIsUpdateToken()==Constants.TYPE_ZERO){ // result.setIsUpdateToken(Constants.TYPE_ZERO); // result.setToken(info.getBaseToken()); // } // // if (result.getData()!=null){ NutMap nutMap=(NutMap)result.getData(); nutMap.setv("aop","aop"); result.setData(nutMap); // } // // System.out.println(ret); } }
aop使用方式:
@CheckLoginAop @ApiOperation(value = "获得会员购买价格") @JsonInclude(JsonInclude.Include.NON_NULL) @RequestMapping(value = "/memberPrice", method = RequestMethod.GET) public ReQueryResult<List<SysConfig>> memberPrice(HttpServletRequest request,@ApiIgnore()MemberInfo memberInfo){ result=new ReQueryResult();result.success(SUCCESS_DESC); return result; }
自定义异常:
/** * @author furutaka */ public class MemberException extends RuntimeException { public MemberException(String message){ super(message); } }
全局异常拦截:
/** * @author furutaka */ @RestControllerAdvice @ResponseBody @Slf4j public class GlobalExceptionHandler { @Resource private StringRedisTemplate template; /** * 全局异常拦截 * @param request * @param e * @return */ @ExceptionHandler(value = {Exception.class,NoHandlerFoundException.class}) public ReQueryResult exceptionHandler(HttpServletRequest request, Exception e) { ReQueryResult result = new ReQueryResult(); log.error("异常日志记录 {}",e.getMessage()); log.info(ExceptionUtils.getFullStackTrace(e)); if (e instanceof MemberException) { MemberException memberException = (MemberException) e; result.loginError("账号未登录"); return result; } if (e instanceof NoHandlerFoundException) { String ip = request.getHeader("X-FORWARDED-FOR"); if (StringUtils.isEmpty(ip)) { ip = request.getRemoteAddr(); } log.info("无url 访问ip : {}",ip); result.setResultCode(TYPE_ONE_HUNDRED_ONE_STR); result.setResultDesc("未找到url"); return result; } result.error("系统异常"); return result; } }
url异常拦截需要 :
spring: mvc: throw-exception-if-no-handler-found: true resources: add-mappings: false