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


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com