All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.plugin.extension.resources.resolver.PluginResourceWebMvcResolver Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version
package org.zodiac.plugin.extension.resources.resolver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileUrlResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.resource.AbstractResourceResolver;
import org.springframework.web.servlet.resource.ResourceResolverChain;
import org.zodiac.plugin.factory.PluginRegistryInfo;
import org.zodiac.plugin.factory.process.pipe.loader.PluginResource;
import org.zodiac.plugin.realize.BasePlugin;
import org.zodiac.sdk.toolkit.constants.CharPool;
import org.zodiac.sdk.toolkit.constants.StringPool;
import org.zodiac.sdk.toolkit.util.lang.StrUtil;

import javax.servlet.http.HttpServletRequest;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 插件资源WebMvc发现者。
 */
public class PluginResourceWebMvcResolver extends AbstractResourceResolver {

    private final static Logger logger = LoggerFactory.getLogger(PluginResourceWebMvcResolver.class);

    private final static String RESOLVED_RESOURCE_CACHE_KEY_PREFIX = "resolvedPluginResource:";

    PluginResourceWebMvcResolver() {
    }

    @Override
    protected Resource resolveResourceInternal(HttpServletRequest request, String requestPath,
        List locations, ResourceResolverChain chain) {

        int startOffset = (requestPath.startsWith("/") ? 1 : 0);
        int endOffset = requestPath.indexOf('/', 1);
        if (endOffset != -1) {
            String pluginId = requestPath.substring(startOffset, endOffset);
            String partialPath = requestPath.substring(endOffset + 1);
            PluginStaticResource pluginResource = PluginResourceResolvers.getPluginStaticResource(pluginId);

            if (pluginResource == null) {
                return null;
            }

            String key = computeKey(request, requestPath);
            /*先判断缓存中是否存在。*/
            Resource resource = pluginResource.getCacheResource(key);
            if (resource != null) {
                return resource;
            }

            /*从classpath 获取资源*/
            resource = resolveClassPath(pluginResource, partialPath);
            if (resource != null) {
                pluginResource.putCacheResource(key, resource);
                return resource;
            }

            /*从外置文件路径获取资源*/
            resource = resolveFilePath(pluginResource, partialPath);
            if (resource != null) {
                pluginResource.putCacheResource(key, resource);
                return resource;
            }
            return null;
        }
        return chain.resolveResource(request, requestPath, locations);
    }

    @Override
    protected String resolveUrlPathInternal(String resourceUrlPath, List locations,
        ResourceResolverChain chain) {
        return super.resolveUrlPath(resourceUrlPath, locations, chain);
    }

    /**
     * 

计算key。

* * @param request request * @param requestPath 请求路径 * @return 返回key */ protected String computeKey(HttpServletRequest request, String requestPath) { StringBuilder key = new StringBuilder(RESOLVED_RESOURCE_CACHE_KEY_PREFIX); key.append(requestPath); if (request != null) { String codingKey = getContentCodingKey(request); if (StrUtil.isNotBlank(codingKey)) { key.append("+encoding=").append(codingKey); } } return key.toString(); } /** *

解决 ClassPath 的资源文件。也就是插件中定义的classpath:/xx/xx/配置。

* * @param pluginResource 插件资源配置Bean * @param partialPath 部分路径 * @return 资源。没有发现则返回null */ private Resource resolveClassPath(PluginStaticResource pluginResource, String partialPath) { Set classPaths = pluginResource.getClassPaths(); if (classPaths == null || classPaths.isEmpty()) { return null; } PluginRegistryInfo pluginRegistryInfo = pluginResource.getPluginRegistryInfo(); BasePlugin basePlugin = pluginRegistryInfo.getBasePlugin(); if (basePlugin == null) { return null; } ClassLoader pluginClassLoader = pluginRegistryInfo.getPluginClassLoader(); for (String classPath : classPaths) { try { PluginResource resource = new PluginResource(classPath + partialPath, pluginRegistryInfo); resource.setClassLoader(pluginClassLoader); if (resource.exists()) { return resource; } } catch (Exception e) { logger.debug("Get static resources of classpath '{}' error.", classPath, e); } } return null; } /** *

解决插件中配置的绝对文件路径的文件资源。也就是插件中定义的file:D://xx/xx/配置。

* * @param pluginResource 插件资源配置Bean * @param partialPath 部分路径 * @return 资源。没有发现则返回null */ private Resource resolveFilePath(PluginStaticResource pluginResource, String partialPath) { Set filePaths = pluginResource.getFilePaths(); if (filePaths == null || filePaths.isEmpty()) { return null; } for (String filePath : filePaths) { Path fullPath = Paths.get(filePath + partialPath); if (!Files.exists(fullPath)) { continue; } try { FileUrlResource fileUrlResource = new FileUrlResource(fullPath.toString()); if (fileUrlResource.exists()) { return fileUrlResource; } } catch (Exception e) { logger.debug("Get static resources of path '{}' error.", fullPath, e); } } return null; } /** *

根据请求获取内容code key。

* * @param request request * @return key */ private String getContentCodingKey(HttpServletRequest request) { String header = request.getHeader(HttpHeaders.ACCEPT_ENCODING); if (StrUtil.isBlank(header)) { return null; } return Arrays.stream(StringUtils.tokenizeToStringArray(header, StringPool.COMMA)).map(token -> { int index = token.indexOf(CharPool.SEMICOLON); return (index >= 0 ? token.substring(0, index) : token).trim().toLowerCase(); }).sorted().collect(Collectors.joining(StringPool.COMMA)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy