spring-boot-admin源码分析及单机监控spring-boot-monitor的实现(二)

 2019-11-02 21:20  阅读(1042)
文章分类:Spring boot

SpringBootMonitor

spring-boot-admin源码分析及单机监控spring-boot-monitor的实现(一)

spring-boot-admin源码分析及单机监控spring-boot-monitor的实现(二)

spring-boot-admin源码分析及单机监控spring-boot-monitor的实现(三)

1.spring-boot-admin配置分析

spring-boot-admin使用AdminServerCoreConfiguration进行属性配置,@EnableConfigurationProperties

(AdminServerProperties.class)
指出注入
AdminServerProperties类,AdminServerProperties类中注解

@ConfigurationProperties(“spring.boot.admin”),将读取application.yml配置文件中以spring.boot.admin

开头的配置,并与属性一一对应。同时,AdminServerCoreConfiguration也注入了一系列bean,总的来说,

AdminServerCoreConfiguration就是注入配置及业务处理bean的管理。

spring-boot-admin使用AdminServerWebConfiguration进行web相关配置管理。AdminServerWebConfiguration

继承自WebMvcConfigurerAdapter,实现了ApplicationContextAware。其中最主要的就是重写了addResourceHandlers

和addViewControllers方法。在addResourceHandlers方法中,它将所有访问contextPath + / 的路径映射到

classpath:/META-INF/spring-boot-admin-server-ui/下;将contextPath + all-modules.css/js 映射到

classpath*:/META-INF/spring-boot-admin-server-ui/*/module.css/js 上,它根据自己的逻辑去实现了

这些资源的整合访问。在addViewControllers方法中,将contextPath + / 的访问forward到index.html。

2.spring-boot-monitor配置实现。

我们提供MonitorConfiguration、MonitorProperties、MonitorWebConfiguration分别实现对应的功能。

MonitorConfiguration:

package com.cff.boot.monitor.config;

    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Configuration;

    @Configuration
    @EnableConfigurationProperties(MonitorProperties.class)
    public class MonitorConfiguration {
        private final MonitorProperties monitorProperties;

        public MonitorConfiguration(MonitorProperties monitorProperties) {
            this.monitorProperties = monitorProperties;
        }

    }

MonitorProperties:

package com.cff.boot.monitor.config;

    import org.springframework.boot.context.properties.ConfigurationProperties;

    @ConfigurationProperties("spring.boot.monitor")
    public class MonitorProperties {
        private String contextPath = "/sbim";
        private String username = "";
        private String password = "";
        public String getContextPath() {
            return contextPath;
        }

        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }

    }

MonitorWebConfiguration:

package com.cff.boot.monitor.config;

    import java.util.List;
    import java.util.Map;

    import org.springframework.beans.BeansException;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.web.ServerProperties;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.support.ResourcePatternResolver;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    import org.springframework.util.StringUtils;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

    import com.cff.boot.monitor.model.AppInfo;
    import com.cff.boot.monitor.resolver.UrlFilteringResourceResolver;
    import com.cff.boot.monitor.store.SimpleAppInfoStore;
    import com.cff.boot.monitor.web.RestApiController;
    import com.fasterxml.jackson.databind.ObjectMapper;

    @Configuration
    @AutoConfigureAfter({MonitorConfiguration.class})
    public class MonitorWebConfiguration extends WebMvcConfigurerAdapter
    implements ApplicationContextAware{
        private final ApplicationEventPublisher publisher;
        private final ServerProperties server;
        private final ResourcePatternResolver resourcePatternResolver;
        private final MonitorProperties monitorProperties;
        private ApplicationContext applicationContext;

        public MonitorWebConfiguration(ApplicationEventPublisher publisher, ServerProperties server,
                ResourcePatternResolver resourcePatternResolver,
                MonitorProperties monitorProperties) {
            this.publisher = publisher;
            this.server = server;
            this.resourcePatternResolver = resourcePatternResolver;
            this.monitorProperties = monitorProperties;
        }

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

        @Override
        public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
            if (!hasConverter(converters, MappingJackson2HttpMessageConverter.class)) {
                ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
                        .applicationContext(this.applicationContext).build();
                converters.add(new MappingJackson2HttpMessageConverter(objectMapper));
            }
        }

        private boolean hasConverter(List<HttpMessageConverter<?>> converters,
                Class<? extends HttpMessageConverter<?>> clazz) {
            for (HttpMessageConverter<?> converter : converters) {
                if (clazz.isInstance(converter)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            System.out.println("路径:" + monitorProperties.getContextPath());
            registry.addResourceHandler(monitorProperties.getContextPath() + "/**")
                    .addResourceLocations("classpath:/META-INF/spring-boot-monitor-ui/")
                    .resourceChain(true)
                    .addResolver(new UrlFilteringResourceResolver(".min"));
        }

        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            String contextPath = monitorProperties.getContextPath();
            if (StringUtils.hasText(contextPath)) {
                registry.addRedirectViewController(contextPath, server.getPath(contextPath) + "/");
            }
            registry.addViewController(contextPath + "/").setViewName("forward:login.html");
        }

        @Bean
        @ConditionalOnMissingBean
        public SimpleAppInfoStore appInfoStore() {
            SimpleAppInfoStore simpleAppInfoStore = new SimpleAppInfoStore();
            String appId = applicationContext.getId();
            String appName = appId.substring(0, appId.indexOf(":"));
            String appInfo = appId;
            String appStatus = "UP";
            AppInfo app = new AppInfo(appName,"",appInfo,appStatus);
            simpleAppInfoStore.addApp(app);
            return simpleAppInfoStore;
        }

        @Bean
        @ConditionalOnMissingBean
        public RestApiController restApiController(SimpleAppInfoStore simpleAppInfoStore) {
            return new RestApiController(monitorProperties,simpleAppInfoStore);
        }
    }

addViewControllor是必须的,不然使用模版引擎会导致自定义的内容失效。

拷贝一个ResourceResolver改个名,也懒得去了解它是干嘛的了。UrlFilteringResourceResolver:

/*
     * Copyright 2014 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package com.cff.boot.monitor.resolver;

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;

    import javax.servlet.http.HttpServletRequest;

    import org.springframework.core.io.Resource;
    import org.springframework.util.StringUtils;
    import org.springframework.web.servlet.resource.AbstractResourceResolver;
    import org.springframework.web.servlet.resource.ResourceResolver;
    import org.springframework.web.servlet.resource.ResourceResolverChain;

    /**
     * {@link ResourceResolver} which is looking for minified version of resources.
     *
     * @author Johannes Edmeier
     */
    public class UrlFilteringResourceResolver extends AbstractResourceResolver {
        private final String extensionPrefix;

        public UrlFilteringResourceResolver(String extensionPrefix) {
            this.extensionPrefix = extensionPrefix;
        }

        @Override
        protected Resource resolveResourceInternal(HttpServletRequest request, String requestPath,
                List<? extends Resource> locations, ResourceResolverChain chain) {
            List<Resource> newLocations = new ArrayList<>(locations.size());
            for (Resource location : locations) {
                Resource minified = findMinified(location);
                newLocations.add(minified != null ? minified : location);
            }

            return chain.resolveResource(request, requestPath, newLocations);
        }

        private Resource findMinified(Resource resource) {
            try {
                String basename = StringUtils.stripFilenameExtension(resource.getFilename());
                String extension = StringUtils.getFilenameExtension(resource.getFilename());
                Resource minified = resource
                        .createRelative(basename + extensionPrefix + '.' + extension);
                if (minified.exists()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Found minified file for '" + resource.getFilename() + "': '"
                                + minified.getFilename() + "'");
                    }
                    return minified;
                }
            } catch (IOException ex) {
                logger.trace("No minified resource for [" + resource.getFilename() + "]", ex);
            }
            return null;
        }

        @Override
        protected String resolveUrlPathInternal(String resourceUrlPath,
                List<? extends Resource> locations, ResourceResolverChain chain) {
            return chain.resolveUrlPath(resourceUrlPath, locations);
        }

    }

来源:http://ddrv.cn

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> spring-boot-admin源码分析及单机监控spring-boot-monitor的实现(二)

相关推荐