自定义注解的使用

自定义注解的使用

  • 注解+拦截器 实现登录校验

项目中在进入方法之前判断用户是否登录、登录了则继续执行方法,未登录则返回异常信息。

a.先定义一个注解@NeedLogin

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLogin {

}

 b.再写个拦截器,控制具体逻辑

public class NeedLoginInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 反射获取方法上的NeedLogin注解
        if (handler instanceof HandlerMethod){
            /**
             * 注意:
             * 当接口顶层没有设置根路劲时,Spring boot 将接口理解为静态资源(ResourceHttpRequestHandler)
             *  @see com.yds.start.controller.DemoErrorController
             * (HandlerMethod)handler 会报错(ClassCastException)
             *
             * ResourceHttpRequestHandler是用来处理静态资源的;而HandlerMethod则是springMVC中用@Controller声明的一个bean及对应的处理方法.
             *
             */
            HandlerMethod handlerMethod = (HandlerMethod)handler;
            NeedLogin loginRequired = handlerMethod.getMethod().getAnnotation(NeedLogin.class);
            if(loginRequired != null){
                // 有NeedLogin注解说明需要登录,提示用户登录
                response.setContentType("text/plain; charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.print("你访问的资源需要登录");
                writer.flush();
                writer.close();
                return false;
            }
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

}

 c.看效果(写两个接口一个带@NeedLogin,一个不带)

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @NeedLogin
    @GetMapping(value = "/getMyInfo")
    public String getMyInfo() {
        String myInfo = userService.getMyInfo();
        return myInfo;
    }

    @GetMapping(value = "/login")
    public String login() {
        return "login";
    }

}

  • 注解+AOP 日志打印

项目中可以根据注解自定义打印日志

a.定义注解@MyLog

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface MyLog {
}

b.AOP 实现逻辑

@Slf4j
@Aspect
@Component
public class LogAspect {
    /**
     * PointCut表示这是一个切点,@annotation表示这个切点切到一个注解上,后面带该注解的全类名
     *  切面最主要的就是切点,所有的故事都围绕切点发生
     *  logPointCut()代表切点名称
     */
    @Pointcut("@annotation(com.yds.start.common.annotation.MyLog)")
    public void logPointCut() {
    }

    /**
     * 环绕通知
     * @param joinPoint
     */
    @Around("logPointCut()")
    public void logAround(ProceedingJoinPoint joinPoint){
        // 获取方法名称
        String methodName = joinPoint.getSignature().getName();
        // 获取入参
        Object[] param = joinPoint.getArgs();

        StringBuilder sb = new StringBuilder();
        for(Object o : param){
            sb.append(o + "; ");
        }
        log.info("进入[{}]方法,参数为:{}" ,methodName, sb);

        // 继续执行方法
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        log.info(methodName + "方法执行结束");
    }

}

c.看效果(写个接口,加上@MyLog注解)

@MyLog
@GetMapping(value = "/test")
public String test(String str) {
    return str;
}

访问http://127.0.0.1:8080/demo/test?str=123

观察控制台输出:

2022-02-23 10:10:04.317  INFO 95922 --- [nio-8080-exec-6] com.yds.start.common.aop.LogAspect       : 进入[test]方法,参数为:123; 
2022-02-23 10:10:04.318  INFO 95922 --- [nio-8080-exec-6] com.yds.start.common.aop.LogAspect       : test方法执行结束

 

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 自定义注解的使用