通過自定義註解獲取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;
    }
}

這是整個過程,自定義註解也給了,可以自己試試,不懂的可以私信我

 

 

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