Spring自定义注解DEMO及使用场合

937 阅读2分钟

DEMO

自定义注解

@Target(ElementType.METHOD)   //TYPE类  FIeld 变量
@Retention(RetentionPolicy.RUNTIME)
public @interface BusinessLog {

    String url() default "";

    String value() default "";
}

使用自定义注解

public class StudentService {

    @BusinessLog(value = "学习接口",url = "/user/study")
    public void study() {
        System.out.println("正在教室学习");
    }
}

反射读取注释内容

class WadeApplicationTests {
    public static void main(String[] args) {
        Class<StudentService> studentServiceClass = StudentService.class;
        for (Method m : studentServiceClass.getDeclaredMethods()) {
            BusinessLog annotation = m.getAnnotation(BusinessLog.class);
            System.out.println("读取自定义注解内容"+annotation.url()+"----"+annotation.value());   //  读取自定义注解内容:user/study----学习接口
        }
    }

}

使用场景

登录鉴权或资源鉴权

1.自定义注解

//接口需要登录认证
@Target(ElementType.METHOD)    
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequird {

}

2.controller的方法中使用

    @LoginRequird
    @RequestMapping
    public Object index(ModelAndView modelAndView, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "5") Integer size,HttpSession session) {
        PageHelper.startPage(pageNum, size);
        List<User> userList = userService.getUserList();
        PageInfo<User> stringPageInfo = new PageInfo<>(userList);
        modelAndView.addObject("page", stringPageInfo);
        modelAndView.setViewName("index");
        return modelAndView;
    }

3.HandlerInterceptor 拦截器定义拦截请求

@Component
@Slf4j
public class MyHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        HandlerMethod handlerMethod = (HandlerMethod)handler;
        LoginRequird annotation = handlerMethod.getMethod().getAnnotation(LoginRequird.class);
        //有LoginRequired表明要鉴权,否则放行
        if (annotation != null) {
            Object name = request.getSession().getAttribute("name");
            log.info("name : {}", name);
            if (name == null) {
                response.sendRedirect("/user/login");
                return false;
            } else {
                return true;
            }
        }
        log.info("prehandler通过");
        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 {
        
    }
}

4.使用拦截器

@Configuration
public class MyWebConfig implements WebMvcConfigurer {

    @Autowired
    private MyHandlerInterceptor myHandlerInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myHandlerInterceptor).addPathPatterns("/**");
    }
}

做资源权限认证,比如某些接口管理员权限用户才能访问。代码实现类似!

自定义注解+AOP做日志系统

自定义注解

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

    /**
     * 业务的名称,例如:"修改菜单"
     */
    String value() default "";

    /**
     * 被修改的实体的唯一标识,例如:菜单实体的唯一标识为"id"
     */
    String key() default "id";

    /**
     * 字典(用于查找key的中文名称和字段的中文名称)
     */
    Class<? extends AbstractDictMap> dict() default SystemDict.class;

    /**
     * 菜单url
     */
    String url() default "";
}

AOP

@Aspect
@Component
public class LogAop {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Pointcut(value = "@annotation(cn.wyb.wade.annotion.BussinessLog)")
    public void cutService() {
    }

    @Around("cutService()")
    public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {

        //先执行业务
        Object result = point.proceed();

        try {
            handle(point);
        } catch (Exception e) {
            log.error("日志记录出错!", e);
        }

        return result;
    }

    private void handle(ProceedingJoinPoint point) throws Exception {

        //获取拦截的方法名
        Signature sig = point.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Object target = point.getTarget();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        String methodName = currentMethod.getName();

        //如果当前用户未登录,不做日志
        ShiroUser user = ShiroKit.getUser();
        if (null == user) {
            return;
        }

        //获取拦截方法的参数
        String className = point.getTarget().getClass().getName();
        Object[] params = point.getArgs();

        //获取操作名称
        BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class);
        String bussinessName = annotation.value();
        String key = annotation.key();
        Class dictClass = annotation.dict();
        String url = annotation.url();

        StringBuilder sb = new StringBuilder();
        for (Object param : params) {
            sb.append(param);
            sb.append(" & ");
        }
        
		//保存日志
        LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(), user.getShopId(), bussinessName, className, methodName, msg, url));
    }
}