GVKun编程网logo

将外部资源文件夹添加到Spring Boot(如何将外部文件导入eclipse)

21

本文将介绍将外部资源文件夹添加到SpringBoot的详细情况,特别是关于如何将外部文件导入eclipse的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一

本文将介绍将外部资源文件夹添加到Spring Boot的详细情况,特别是关于如何将外部文件导入eclipse的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于55.springboot引入资源文件、Jawr & Springboot - 资源文件夹未解析、NutzBoot 读取外部资源文件功能的诞生、Spring boot 国际化自动加载资源文件问题的知识。

本文目录一览:

将外部资源文件夹添加到Spring Boot(如何将外部文件导入eclipse)

将外部资源文件夹添加到Spring Boot(如何将外部文件导入eclipse)

我想相对于jar的位置添加一个资源文件夹(除了jar中的打包资源),例如:

/Directory    Application.jar    /resources        test.txt

我尝试了以下方法:

@Overridepublic void addResourceHandlers(final ResourceHandlerRegistry registry) {    registry.addResourceHandler("/resources/**")            .addResourceLocations("/resources/", "file:/resources/");}

我也尝试过:

.addResourceLocations("/resources/", "file:resources/");

http://localhost:8080/resources/test.txt使用任何一种设置进行访问都会导致出现白标错误页面。我该如何解决?

答案1

小编典典

您的第二种方法可行:

@Overridepublic void addResourceHandlers(final ResourceHandlerRegistry registry) {    registry.addResourceHandler("/resources/**")            .addResourceLocations("/resources/", "file:resources/");}

当您从启动Spring Boot时/Directory,因为file:resources/它是相对路径。

cd Directoryjava -jar Application.jar

如果可以将所有内容打包到jar中,这很好,但是如果必须引用外部资源,则应该使用绝对路径来避免此类问题。

55.springboot引入资源文件

55.springboot引入资源文件

1.效果

2.应用

参考:

https://www.cnblogs.com/grasp/p/11473826.html

https://blog.csdn.net/happyblueice/article/details/86538843

启动命令spring.profiles.active指定文件中的值 > 文件中spring.profiles.active指定的文件列表中最后一次出现的值 > 文件中spring.profiles.include指定的文件列表中最后一次出现的值

应用:开发 生产 环境切换

         配置静态资源

 

2.注意问题

要引入静态资源文件 就别用 @AllArgsConstructor了 否则影响@Value注解

 

Jawr & Springboot - 资源文件夹未解析

Jawr & Springboot - 资源文件夹未解析

如何解决Jawr & Springboot - 资源文件夹未解析?

我的问题是 css & js 文件包没有解决。

我正在将我的 WAR 应用程序迁移到 Spring Boot 应用程序。

这是jawr 的servlet 3.0 配置:

@Configuration
public class WebJawrConfiguration {

    private final Properties properties;

    public WebJawrConfiguration(final WebSelfiscProperties webProperties) {
        this.properties = new Properties();
        this.properties.putAll(webProperties.getJawr().entrySet().stream().collect(Collectors.toMap(e -> "jawr." + e.getKey(),Entry::getValue)));
    }

    @Bean
    public JawrSpringController jawrBinaryController() {
        final JawrSpringController jawrBinaryController = new JawrSpringController();
        jawrBinaryController.setConfiguration(properties);
        jawrBinaryController.setType(JawrConstant.BINARY_TYPE);
        return jawrBinaryController;
    }

    @Bean
    @DependsOn("jawrBinaryController")
    public JawrSpringController jawrCssController() {
        final JawrSpringController jawrCssController = new JawrSpringController();
        jawrCssController.setConfiguration(properties);
        jawrCssController.setType(JawrConstant.CSS_TYPE);
        // jawrCssController.setMapping("/public/bundles/css");
        return jawrCssController;
    }

    @Bean
    @DependsOn("jawrCssController")
    public JawrSpringController jawrJsController() {
        final JawrSpringController jawrJsController = new JawrSpringController();
        jawrJsController.setConfiguration(properties);
        jawrJsController.setType(JawrConstant.JS_TYPE);
        // jawrJsController.setMapping("/public/bundles/js");
        return jawrJsController;
    }

    @Configuration
    @ConditionalOnMissingBean(name = "jawrHandlerMapping")
    @DependsOn("jawrJsController")
    public class jawrHandlerMappingConfiguration {

        private final JawrSpringController jawrJsController;
        private final JawrSpringController jawrCssController;
        private final JawrSpringController jawrBinaryController;

        /**
         * Constructeur
         *
         * @param jawrJsController
         * @param jawrCssController
         * @param jawrBinaryController
         */
        public jawrHandlerMappingConfiguration(final JawrSpringController jawrJsController,final JawrSpringController jawrCssController,final JawrSpringController jawrBinaryController) {
            super();
            this.jawrJsController = jawrJsController;
            this.jawrCssController = jawrCssController;
            this.jawrBinaryController = jawrBinaryController;
        }

        @Bean
        public HandlerMapping jawrHandlerMapping() {
            final SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
            handlerMapping.setorder(Ordered.HIGHEST_PRECEDENCE);

            final Map<String,Object> urlMap = new HashMap<>();
            urlMap.put("**/*.css",jawrCssController);
            urlMap.put("**/*.eot",jawrBinaryController);
            urlMap.put("**/*.gif",jawrBinaryController);
            urlMap.put("**/*.ico",jawrBinaryController);
            urlMap.put("**/*.jpg",jawrBinaryController);
            urlMap.put("**/*.jpeg",jawrBinaryController);
            urlMap.put("**/*.js",jawrJsController);
            urlMap.put("**/*.png",jawrBinaryController);
            urlMap.put("**/*.ttf",jawrBinaryController);
            urlMap.put("**/*.woff",jawrBinaryController);
            urlMap.put("**/*.woff2",jawrBinaryController);
            urlMap.put("**/*.svg",jawrBinaryController);
            handlerMapping.setUrlMap(urlMap);

            return handlerMapping;
        }
    }
}

可能 application.properties 的一部分:

# Common properties
jawr.debug.on=false
jawr.gzip.on=false
jawr.gzip.ie6.on=false
jawr.charset.name=UTF-8

jawr.css.bundle.base.id=/base.css
jawr.css.bundle.base.mappings=/public/css/blue-theme.css,/public/css/main.css

以及它是如何在我的 JSP 中声明的

<jawr:style src="/base.css" />

如果我设置了jawr.debug.on=true 一切正常:

<link rel="stylesheet" type="text/css" media="screen" href="/sel/public/css/blue-theme.css?d=1136145833">
<link rel="stylesheet" type="text/css" media="screen" href="/sel/public/css/main.css?d=762931402">

如果我设置了jawr.debug.on=false 一个哈希前缀链接到版本它。但是id不再解析。

<link rel="stylesheet" type="text/css" media="screen" href="/2096063500/base.css">

一个多星期以来,我一直在努力解决这个问题。没有成功。

有人遇到过这个问题吗? 谢谢。

解决方法

我解决了我的问题。

这是我的新配置:

@Configuration
public class WebJawrConfiguration {

    private final Properties properties;

    /**
     * Constructor
     *
     * @param webProperties
     */
    public WebJawrConfiguration(final WebSelfiscProperties webProperties) {
        this.properties = new Properties();
        this.properties.putAll(webProperties.getJawr().entrySet().stream().collect(Collectors.toMap(e -> "jawr." + e.getKey(),Entry::getValue)));
    }

    @Bean
    @DependsOn("jawrBinaryController")
    public JawrSpringController jawrCssController() {
        final JawrSpringController jawrCssController = new JawrSpringController();
        final Properties propertiesCss = new Properties();
        propertiesCss.putAll(properties.entrySet().stream().filter(e -> !e.getKey().toString().contains("jawr.js"))
                .collect(Collectors.toMap(Entry::getKey,Entry::getValue)));
        jawrCssController.setConfiguration(propertiesCss);
        jawrCssController.setType(JawrConstant.CSS_TYPE);
        return jawrCssController;
    }

    @Bean
    @DependsOn("jawrCssController")
    public JawrSpringController jawrJsController() {
        final JawrSpringController jawrJsController = new JawrSpringController();
        final Properties propertiesJs = new Properties();
        propertiesJs.putAll(properties.entrySet().stream().filter(e -> !e.getKey().toString().contains("jawr.css"))
                .collect(Collectors.toMap(Entry::getKey,Entry::getValue)));
        jawrJsController.setConfiguration(propertiesJs);
        jawrJsController.setType(JawrConstant.JS_TYPE);
        return jawrJsController;
    }

    @Configuration
    @DependsOn("jawrJsController")
    public class jawrHandlerMappingConfiguration {

        private final JawrSpringController jawrJsController;
        private final JawrSpringController jawrCssController;


        /**
         * Constructor
         *
         * @param jawrJsController
         * @param jawrCssController
         */
        public jawrHandlerMappingConfiguration(final JawrSpringController jawrJsController,final JawrSpringController jawrCssController) {
            super();
            this.jawrJsController = jawrJsController;
            this.jawrCssController = jawrCssController;
        }

        @Bean
        @DependsOn("jawrJsController")
        public HandlerMapping jawrHandlerMapping() {
            final SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
            handlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);

            final Map<String,Object> urlMap = new HashMap<>();
            urlMap.put("**/*.css",jawrCssController);
            urlMap.put("**/*.js",jawrJsController);
            handlerMapping.setUrlMap(urlMap);

            return handlerMapping;
        }
    }
}

并使用 *.css、*.js 映射我的 servlet 调度程序

NutzBoot 读取外部资源文件功能的诞生

NutzBoot 读取外部资源文件功能的诞生

前因

Nutz 接触时间了,最近使用 NutzBoot 开发了个微服务,在准备部署的时候遇上一个问题,NutzBoot 在发布时,会将配置文件、模板文件都打包进 jar 包,那么在后期做细微调整时将涉及到重新发包,本人强伯症,受不了这个,如果项目只是需要对配置做些修改,或者模板做些修改,完全没必要重新打包发布,故而发生了之后的事情 - 改造

过程

怎样把配置文件打包到 jar 包外面?

修改 pom.xml <build>...</build> 标签内加入配置,过滤 resources 目录

<resources>
	<resource>
		<directory>src/main/resources</directory>
		<excludes>
			<exclude>**/*</exclude>
		</excludes>
		<filtering>true</filtering>
	</resource>
</resources>

<build><plugins>...</plugins></build> 标签内加入配置,将配置资源目录编译到 jar 包外

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<executions>
		<execution>
			<id>copy-resources</id>
			<phase>package</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<encoding>UTF-8</encoding>
				<outputDirectory>
					${project.build.directory}
				</outputDirectory>   <!-- 表示把配置文件拷到和jar包同一个路径下 -->
				<resources>
					<resource>
						<directory>src/main/resources/</directory>
					</resource>
				</resources>
			</configuration>
		</execution>
	</executions>
</plugin>

此时执行 mvn clean;mvn compile;mvn package; 已经可以将资源文件打包到 jar 包外部了。


那么问题来了,项目如何读取外部资源

首先我是想办法解决 beetl 模板文件的读取,因为 NutzBoot 项目没有考虑过外部读取的情况,所以必须经过改造,与 @wendal 进行讨论后,采取从 Setup 的 init 方法着手,手动指定模板读取路径,实现如下:

public class MainSetup implements Setup {
    @Override
    public void init(NutConfig nc) {
        for(ViewMaker maker: nc.getViewMakers()) {
            if(maker.getClass() == BeetlViewMakerStarter.class) {
                // 获取BeetlViewMaker对象
                BeetlViewMaker beetlViewMaker = (BeetlViewMaker)maker;
                // 生成FileResourceLoader 从文件系统取资源
                FileResourceLoader fileResourceLoader = new FileResourceLoader();
                fileResourceLoader.setCharset("UTF-8");
                // 设置jar包外部模板目录
                fileResourceLoader.setRoot(getBasePath() + File.separator + "template");
                // 配置beetlViewMaker使用外部目录读取模板
                beetlViewMaker.groupTemplate.setResourceLoader(fileResourceLoader);
            }
        }
    }

    @Override
    public void destroy(NutConfig nc) {

    }
    
    // 获取jar包当前目录
    static String getBasePath() {
        String basePath = MainSetup.class.getProtectionDomain().getCodeSource().getLocation().getPath();
        int lastIndex = basePath.lastIndexOf(File.separator);
        basePath = basePath.substring(0, lastIndex);
        try {
            basePath = java.net.URLDecoder.decode(basePath, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return basePath;
    }
}

外部模板读取问题解决,就剩下读取外部配置文件,于是跟 @wendal 又进行各种沟通,最后决定修改源码让 NutzBoot 支持读取外部配置文件,顺便实现了指定配置文件目录自动扫描,详细步骤就不写了,如有兴趣可关注 论坛讨论贴 NutzBoot 如何打包发布

经过修改后,现在 NutzBoot 支持外部配置方式,比如将 application.properties 放在 jar 包同级目录。 另外 application.properties 新增支持配置读取其他配置文件, 如:

nutz.boot.configure.properties.dir=config
// 系统将自动扫描jar包同级config目录下所有properties文件进行参数读取

结束语

到此我外部读取参数和模板的需求算是圆满解决,也特别感谢 @wendal 给予的支持,特此记录

Spring boot 国际化自动加载资源文件问题

Spring boot 国际化自动加载资源文件问题

  最近正在把以前的一个Spring项目整改为基于Spring boot配置的项目。中间遇到一个国际化资源加载的问题,正常来说只要在application.properties文件中定义正确的资源文件路径,Spring boot就启动时就会自动加载资源。

spring.messages.basename=i18n/message

  但是我的项目修改后获取消息时系统报错,找不到对应语言的资源配置。于是试图找到原因。Google好久都没找到,简直好像就我一个人遇到这鬼问题一样?。只好自己一步一步去调试。

  调试中首先发现系统在调用MessageSource的地方注入的不是MessageSourceAutoConfiguration中定义的ResourceBundleMessageSource对象,而是一个DelegatingMessageSource对象,而且这个对象是空的什么都没有。MessageSourceAutoConfiguration中的定义如下:

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        if (StringUtils.hasText(this.basename)) {
            messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(
                    StringUtils.trimAllWhitespace(this.basename)));
        }
        if (this.encoding != null) {
            messageSource.setDefaultEncoding(this.encoding.name());
        }
        messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale);
        messageSource.setCacheSeconds(this.cacheSeconds);
        messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat);
        return messageSource;
    }

  调试Spring boot 启动过程找到了 DelegatingMessageSource 对象来源, 在启动过程中如果Spring没有找到messageSource定义,就会自动创建一个 DelegatingMessageSource 对象提供给SpringContext。也就是说 MessageSourceAutoConfiguration 根本没有被加载。打断点在 MessageSourceAutoConfiguration 中也确定了Spring boot启动时根本没有执行 MessageSourceAutoConfiguration 的定义。

    /**
     * Initialize the MessageSource.
     * Use parent''s if none defined in this context.
     */
    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            // Make MessageSource aware of parent MessageSource.
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    // Only set parent context as parent MessageSource if no parent MessageSource
                    // registered already.
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {
            // Use empty MessageSource to be able to accept getMessage calls.
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate MessageSource with name ''" + MESSAGE_SOURCE_BEAN_NAME +
                        "'': using default [" + this.messageSource + "]");
            }
        }
    }

  继续调试发现 MessageSourceAutoConfiguration 上有 @Conditional(ResourceBundleCondition.class) 这么个注解,@Conditional 官方介绍 Indicates that a component is only eligible for registration when all specified conditions match. 大概意思就是只有满足所有条件才会被注册。继续去看ResourceBundleCondition.class的实现。

private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context,
                String basename) {
            ConditionMessage.Builder message = ConditionMessage
                    .forCondition("ResourceBundle");
            for (String name : StringUtils.commaDelimitedListToStringArray(
                    StringUtils.trimAllWhitespace(basename))) {
                for (Resource resource : getResources(context.getClassLoader(), name)) {
                    if (resource.exists()) {
                        return ConditionOutcome
                                .match(message.found("bundle").items(resource));
                    }
                }
            }
            return ConditionOutcome.noMatch(
                    message.didNotFind("bundle with basename " + basename).atAll());
  }

  这个方法是根据basename(上面配置的“i18n/message”)存不存在返回是否满足条件,也就是去找classpath:i18n/message.properties文件,看了下目录确实没有这个文件(只有message_**.properties)。因为之前项目messageSource加载时自己配置的,所以并没有这个问题。但现在Spring boot中没有找到message.properties这个默认文件整个messageSource就不加载了。。?简直思密达。。。??总算是解决这个奇葩问题。 话说真的就只有我遇到这问题么,没搜到没搜到啊。。。。?

  最后总结Spring boot自动加载messageSource一定要有一个默认的资源文件。也就是basename.properties。好不科学啊,之前没有找到默认会默认取中文(没考虑过原理?),现在没有默认整个就不加载了。

今天关于将外部资源文件夹添加到Spring Boot如何将外部文件导入eclipse的分享就到这里,希望大家有所收获,若想了解更多关于55.springboot引入资源文件、Jawr & Springboot - 资源文件夹未解析、NutzBoot 读取外部资源文件功能的诞生、Spring boot 国际化自动加载资源文件问题等相关知识,可以在本站进行查询。

本文标签: