通过自定义注解获取Controller层下方法的url

需求:现在有这么个需求,假如有一个自定义注解,我打在Controller层的方法上面,然后需要输出这个方法的路径,然后controller是多个,不能指定,方法也不能指定,大概就是一个方法解决所有类似的情况,该怎么做?(自定义注解@ResMapping)

 

import jdk.nashorn.internal.ir.annotations.Ignore;
import org.omg.CORBA.DynAnyPackage.Invalid;

import java.lang.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author :xianglong
 * @Company com.suixingpay
 * @Create 2018/11/30 16:17
 * @Effect :
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResMapping {
}

首先我们的思路就是先要通过@Controller和@ResController去找到这个类,然后遍历其中的方法,如果发现某个方法上面有@ResMapping,看下面这个例子。

@Slf4j
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*")
public class MqController {

    @PostMapping("/login")
    @ResMapping
    public JsonResult login(@RequestBody UserInfoForm userInfoForm, HttpServletRequest request) throws IOException{
       
    }

然后需要通过日志打印这么个数据:/api/login,这就是这么个需求。我们一步一步来解决这个问题,最后我把有用的代码贴出来供大家直接使用,重在学习!

1.BeanPostProcessor接口

这个接口里面有两个需要实现的方法,

@Slf4j
@Configuration
public class PostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

你可以试试在里面将beanName输出看看,你会发现几乎所有的spring容器内的bean都会通过这个实现的方法输出出来,这就很好的解决了一个问题:怎么获取controller控制类,那就是通过反射的机制,判断类上是否有@Controller

 @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class clz = bean.getClass();
        /**判断此bean是否是controlelr*/
        boolean clzHasAnno = clz.isAnnotationPresent(Controller.class);
        boolean clzzHasAnno = clz.isAnnotationPresent(RestController.class);
        if (clzHasAnno || clzzHasAnno) {
        }
    return bean;
}

我感觉我直接贴代码比较合适,因为上面有注释


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * bean后置处理器
 *
 * @author xl
 */
@Slf4j
@Configuration
public class PostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class clz = bean.getClass();
        /**判断此bean是否是controlelr*/
        boolean clzHasAnno = clz.isAnnotationPresent(Controller.class);
        boolean clzzHasAnno = clz.isAnnotationPresent(RestController.class);
        if (clzHasAnno || clzzHasAnno) {
            Method[] methods = clz.getDeclaredMethods();
            for (Method method : methods) {
                /**优先判断某个方法是否有自定义注解*/
                boolean getHasAnno = method.isAnnotationPresent(ResMapping.class);
                if (getHasAnno) {
                    /**获取此类的一级路径,没有返回空*/
                    String fath = StringUtils.defaultString(lookupRequestMappingPath(bean.getClass().getAnnotations()));
                    RequestMapping isRequestMapping = AnnotationUtils.findAnnotation(method,RequestMapping.class);
                    if (isRequestMapping != null) {
                        String path = lookupRequestMappingPath(AnnotationUtils.getAnnotations(method));
                        path = fath+path;
                        log.info("Request entry ->{path:{}}",path);
                    }
                }
            }
        }
        return bean;
    }
    private String lookupRequestMappingPath(Annotation[] annotations) {
        for (Annotation ann : annotations) {
            Class annType = ann.annotationType();
            // 如果annType与RequestMapping类型一致 或 RequestMapping注释存在于annType上
            if (annType.isAssignableFrom(RequestMapping.class) || annType.isAnnotationPresent(RequestMapping.class)) {
                String[] paths = (String[]) AnnotationUtils.getValue(ann);
                return paths.length > 0 ? paths[0] : null;
            }
        }
        return null;
    }
}

这是整个过程,自定义注解也给了,可以自己试试,不懂的可以私信我

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章