需求:现在有这么个需求,假如有一个自定义注解,我打在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;
}
}
这是整个过程,自定义注解也给了,可以自己试试,不懂的可以私信我