Spring动态增删Controller

动态增删Controller

1、方式一:注册一个Controller中的指定方法

​ 在spring4.0以后,spring官方已经提供了动态注册删除controller,我们直接代码演示

@Component
public class MappingService {

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;

    RequestMappingInfo requestMappingInfo;

    public void addMapping() throws Exception {
        // 这里的path和请求方式都和我们在jar包中那个类定义的是一样的,不然照样会出现404,还有其他参数,这里就先不设置了
        requestMappingInfo = RequestMappingInfo
                .paths("/one/demo")
                .methods(RequestMethod.GET)
                .build();

        URLClassLoader classLoader = new URLClassLoader(new URL[]{new               URL(MappingService.class.getResource("/") + "1.jar")});
        Class<?> myController = classLoader.loadClass("com.example.dynamicmap.MyController");
        Object obj = myController.newInstance();
        // 这里就注册了我们的handlermapping,但是这里只能一个一个方法进行注册(而且不限制你重复注册,但是如果重复注册的话,请求的时候会报错)
        requestMappingHandlerMapping.registerMapping(requestMappingInfo, obj, myController.getDeclaredMethod("getOneName",String.class));
    }

    public void removeMapping() {
        requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);
    }

}

缺点:就是有些地方限制的比较死,而且这里的地址和请求方式之类的还要我们自己去手动设置,不好!同时针对一些请求,假设你必须加上特定注解才能访问成功。所以和真正的在spring中写请求还是有一定去别的

有点:这里我们需要哪些类就映射那些类,这种压力相对较小

2、方式二:注册整个Controller类

同样直接看代码

@Component
// 这里我们需要用到ApplicationContext,但是这个类又不能直接注入,这里就是用这种方法set进来
public class AutoService implements ApplicationContextAware {

    private RequestMappingHandlerMapping requestMappingHandlerMapping;
    private ApplicationContext applicationContext;

    public void addMapping() throws Exception {
        requestMappingHandlerMapping=(RequestMappingHandlerMapping)applicationContext.getBean("requestMappingHandlerMapping");
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();

        URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL(com.example.dynamicmap.one.MappingService.class.getResource("/") + "1.jar")});
        Class<?> myController = classLoader.loadClass("com.example.dynamicmap.MyController");
        // 这里通过builder直接生成了mycontrooler的definition,然后注册进去
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(myController);
        defaultListableBeanFactory.registerBeanDefinition("myc", beanDefinitionBuilder.getBeanDefinition());
        Method method=requestMappingHandlerMapping.getClass().getSuperclass().getSuperclass().getDeclaredMethod("detectHandlerMethods",Object.class);
        method.setAccessible(true);
        method.invoke(requestMappingHandlerMapping,"myc");
    }

    public void removeMapping() {
        requestMappingHandlerMapping=(RequestMappingHandlerMapping)applicationContext.getBean("requestMappingHandlerMapping");
        Object controller= applicationContext.getBean("myc");
        if (controller==null) {
            System.out.println("spring容器中已不存在该实体");
        }
        Class<?> targetClass = controller.getClass();
        ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
            @Override
            public void doWith(Method method) {
                Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
                try {
                    Method createMappingMethod = RequestMappingHandlerMapping.class.
                            getDeclaredMethod("getMappingForMethod", Method.class, Class.class);
                    createMappingMethod.setAccessible(true);
                    RequestMappingInfo requestMappingInfo =(RequestMappingInfo)
                            createMappingMethod.invoke(requestMappingHandlerMapping,specificMethod,targetClass);
                    if(requestMappingInfo != null) {
                        requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }, ReflectionUtils.USER_DECLARED_METHODS);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}

优点:可以直接加载一个类,和我们正常些Controller是一样的,而且不用去解析什么方法了,很方便

缺点:一家在整个类就会加载起来,如果一个类中接口过多,会有一定影响

Github地址: https://github.com/colin-xun/dynamicmap.git

猜你喜欢

转载自www.cnblogs.com/colin-xun/p/10573504.html