在实际项目中有时需要用到自定义注解方便业务的实现,比如说日志,在实现自定义注解时一般和拦截器一起结合,通过拦截器实现注解的业务,也可用aop实现,具体如下
先顶一个控制层,其中@VerifyToken就是我们要实现的自定义注解
@RestController@RequestMapping("/user")public class UserController { /** *@VerifyToken就是我们要实现的自定义注解 / @VerifyToken // 加上注解表示需要该方法需要验证token @GetMapping("/getUser") public Result getUser(String id){ User u = userService.findUserById(id); return new Result("1001","成功",u); }}
定义一个自定义注解接口类,还可以往注解类中添加其他属性
@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface VerifyToken { boolean required() default true;}
编写拦截器,preHandle方法为主要方法
@Componentpublic class AuthInterceptor implements HandlerInterceptor { @Autowired private UserService userService; @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { Map params = new HashMap<>(); Enumeration paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) { String paramName = (String) paramNames.nextElement(); String[] paramValues = request.getParameterValues(paramName); if (paramValues.length == 1) { if (paramValues[0].length() != 0) { params.put(paramName, paramValues[0]); } } } HandlerMethod hander = (HandlerMethod) handler; System.out.println("请求类:"+hander.getClass()+";请求方法:"+((HandlerMethod) handler).getMethod().getName()+";请求参数:"+ JSONUtils.toJSonString(params)); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("222222222222222222222"); } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception{ boolean bo = false; // 获取token String token = request.getHeader("token"); // 如果不是映射到Controller直接放行 if(!(object instanceof HandlerMethod)){ bo = true; } // 检查是否需要验证token HandlerMethod handlerMethod = (HandlerMethod)object; Method method = handlerMethod.getMethod(); if(method.isAnnotationPresent(VerifyToken.class)){ String str = checkToken(method,token); if(!StringUtils.isEmpty(str)) throw new RuntimeException(str); else bo = true; }else bo = true; return bo; } public String checkToken(Method method,String token){ VerifyToken loginToken = method.getAnnotation(VerifyToken.class); if(loginToken.required()){ if(null == token){ return "该请求没有token,请先获取token"; } if(TokenUtil.verifyToken(token)){// 有效,判断是否要刷新令牌 return null; }else{ return "无效令牌"; } } return null; }}
将拦截器注册到spring中管理,这样就完成了
@Componentpublic class InterceptorConfig implements WebMvcConfigurer { @Autowired private AuthInterceptor authInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { System.out.println("=================请求已拦截"); // 拦截所有请求 registry.addInterceptor(authInterceptor).addPathPatterns("/**"); }}