【问题标题】:How to specify ObjectWrapper Freemarker如何指定 ObjectWrapper Freemarker
【发布时间】:2018-02-23 20:25:18
【问题描述】:

请帮帮我。我的网络应用程序使用 Spring MVC 和 Freemarker 2.3.23。当我启动我的应用程序时,我有:“警告:不会加载自定义 EL 函数,因为没有指定 ObjectWrapper”。我尝试通过以下几种方式指定 ObjectWrapper:

@Configuration
public class CustomFreemarkerConfiguration extends WebMvcConfigurerAdapter {
@Bean
@Autowired
public TaglibFactory taglibFactory(ServletContext servletContext) throws 
 IOException, TemplateException {
    DefaultObjectWrapperBuilder owb = new 
DefaultObjectWrapperBuilder(freemarker.template.
Configuration.VERSION_2_3_23);
    owb.setForceLegacyNonListCollections(false);
    owb.setDefaultDateType(TemplateDateModel.DATETIME);
    DefaultObjectWrapper build = owb.build();
    TaglibFactory taglibFactory = new TaglibFactory(servletContext);
    taglibFactory.setObjectWrapper(build);
    return taglibFactory;
}
}

@Configuration
public class CustomFreemarkerConfiguration extends WebMvcConfigurerAdapter {
@Bean
public    DefaultObjectWrapper getDefaultObjectWrapper() {
    DefaultObjectWrapperBuilder defaultObjectWrapperBuilder = new 
DefaultObjectWrapperBuilder(freemarker.template.
Configuration.VERSION_2_3_23);
    defaultObjectWrapperBuilder.setExposeFields(true);
    DefaultObjectWrapper defaultObjectWrapper = 
defaultObjectWrapperBuilder.build();
    return defaultObjectWrapper;
}
}

@Configuration
public class CustomFreemarkerConfiguration extends WebMvcConfigurerAdapter {
...
@Bean
@Autowired
public TaglibFactory taglibFactory(ServletContext servletContext) throws 
IOException, TemplateException {
    FreeMarkerConfigurer freemarkerConfig = 
configFreeMarkerConfigurer(servletContext);

    TaglibFactory taglibFactory = freemarkerConfig.getTaglibFactory();

taglibFactory.setObjectWrapper(freemarker.template.Configuration.
getDefaultObjectWrapper(freemarker.template.Configuration.getVersion()));

    return taglibFactory;
}
...
}

但没有成功。也许有人有工作示例代码来指定 ObjectWrapper?

【问题讨论】:

  • 您确定 Spring Boot 甚至会尝试将这些 bean 注入“自身”吗?我已经看到其他人定义了一个 org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer bean ......所以它可能至少被它使用了。这也是在 Spring 中坏掉的类;当TemplateContextConfiguration 都准备好时,它应该创建和设置TaglibFactory,然后它应该调用taglibFactory.setObjectWrapper(configuration.getObjectWrapper())
  • 我的意思是ServletContext 我说的是TemplateContext...
  • 我试图在我的 FreeMarkerConfigurer 中这样做:@Bean public FreeMarkerConfigurer getFreeMarkerConfigurer() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); configurer.setTemplateLoaderPaths("/", "/WEB-INF/views"); TaglibFactory taglibFactory = new TaglibFactory(servletContext); taglibFactory.setObjectWrapper(defaultObjectWrapper);返回配置器;} 但它不起作用。我仍然有警告。请给我一个代码示例。
  • 好的,看看我的 guess 作为答案...但是上面评论中的代码肯定不起作用,因为您没有通过您创建的TaglibFactory任何东西,所以你只是用它来喂 GC。
  • 顺便说一句,FreeMarker 2.3.23 是旧的;升级它。不过,这与您的问题无关。

标签: spring freemarker


【解决方案1】:

查看FreeMarkerConfigurer的源代码:它在收到ServletContext时重新创建TaglibFactory,但没有设置它的ObjectWrapper。所以你需要重写那个方法,然后调用taglibFactory.setObjectWrapper(configuration.getObjectWrapper())。请注意,我假设 configuration 始终是最终的;我还没有检查过。 (我不建议使用另一个ObjectWrapper,而是Configuration 包含的那个。所以你需要最后的Configuration。)

创建一个FreeMarkerConfigurer 子类的实例,作为@Bean,让我们看看Spring MVC 是否选择了它。 (不知道,没试过。)

如果有效,则应在 Spring Jira 中报告此修复。

【讨论】:

    【解决方案2】:

    谢谢@ddekany 的回答,现在我的 WebConfig 看起来像这样:

     @Configuration
        @EnableWebMvc
        @ComponentScan(basePackages = "aquaplant")
        public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Autowired
        public FreeMarkerConfigurer freeMarkerConfigurer;
    
        @Autowired
        public DefaultObjectWrapper defaultObjectWrapper;
    
        @Bean
        public ViewResolver getViewResolver() {
            FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
            resolver.setOrder(1);
            resolver.setSuffix(".ftl");
            resolver.setPrefix("");
            resolver.setExposeSpringMacroHelpers(true);
            resolver.setExposeRequestAttributes(true);
            resolver.setExposeSessionAttributes(true);
            resolver.setRequestContextAttribute("request");
            return resolver;
        }
    
        @Bean
        public FreeMarkerConfigurer getFreeMarkerConfigurer() {
            FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
            configurer.setTemplateLoaderPaths("/", "/WEB-INF/views");
            return configurer;
        }
        @Bean
        public DefaultObjectWrapper defaultObjectWrapper(){
            DefaultObjectWrapperBuilder owb=new DefaultObjectWrapperBuilder
                    (freemarker.template.Configuration.VERSION_2_3_23);
            owb.setForceLegacyNonListCollections(false);
            DefaultObjectWrapper objectWrapper = owb.build();
            return objectWrapper;
        }
        @Bean
        @Autowired
        public TaglibFactory taglibFactory(ServletContext servletContext) throws
                IOException, TemplateException {
            freeMarkerConfigurer.setServletContext(servletContext);
            TaglibFactory taglibFactory = freeMarkerConfigurer.getTaglibFactory();
            taglibFactory.setObjectWrapper(defaultObjectWrapper);
            return taglibFactory;
        }
    
        }
    

    我没有任何“警告”,但在我的注册页面上我无法收到错误消息。这条鳕鱼不起作用:

      <div class="form-group">
            <@spring.bind "userForm"/>
              <#if spring.status.error>
                <div class="alert alert-danger" role="alert">
                  <#list spring.status.errorMessages as error>
                   <li>${error}</li>
                  </#list>
                </div>
            </#if>
            <label for="username">Username</label>
            <input type="text" class="form-control" id="username" 
                placeholder="Username" name="username">    
      </div>
    

    我在哪里做错了?

    【讨论】:

    • 我不知道,我对 Spring MVC 表单不熟悉。但这是一个新问题,所以打开一个新问题。而且您必须提供更具体的细节(我猜您的 Controller 方法是相关的,如果您收到错误消息等)。
    【解决方案3】:

    最后,我只是覆盖了 getTaglibFactory():

    import freemarker.ext.jsp.TaglibFactory;
    import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
    
    public class DefaultFreeMarkerConfigurer extends FreeMarkerConfigurer{
        @Override
        public TaglibFactory getTaglibFactory() {
            TaglibFactory tagLibFactory = super.getTaglibFactory();
            if (tagLibFactory.getObjectWrapper()==null) {
                tagLibFactory.setObjectWrapper(super.getConfiguration().getObjectWrapper());
            }
            return tagLibFactory;
        }
    }
    

    它似乎正在工作。

    【讨论】:

      猜你喜欢
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多