最近一直在用SpringMVC这个框架,它基于注解的特点非常好用。Freemarker具有很多出色的内置方法,与js可以完美搭配使用,用作SpringMVC的view层感觉良好。这里写一篇文章简要说明如何整合SpringMVC与Freemarker,以及如何去使用它的自定义标签。
一、jar包准备
首先是Spring、SpringMVC的依赖jar包……
然后是Freemarker的依赖jar包,我使用的是freemarker-2.3.20.jar,如果使用maven的话可以直接在pom.xml中添加一段把它引进来:
- <groupId>org.freemarker</groupId>
- <artifactId>freemarker</artifactId>
- <version>2.3.20</version>
二、配置web.xml
- <?xml version="1.0" ?>
- <web-app xmlns="http://java./xml/ns/javaee" xmlns:xsi="http://www./2001/XMLSchema-instance"
- xsi:schemaLocation="http://java./xml/ns/javaee http://java./xml/ns/javaee/web-app_3_0.xsd"
- version="3.0">
- <!-- Spring 服务层的配置文件 -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:applicationContext.xml</param-value>
- </context-param>
-
- <!-- Spring 容器启动监听器 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
-
- <servlet>
- <servlet-name>springmvc</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <!--为DispatcherServlet建立映射 -->
- <servlet-mapping>
- <servlet-name>spring</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- </web-app>
三、配置spring-servlet.xml
这里只写上freemarker的配置部分,先配置视图解析器:
- <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
- <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>
- <property name="contentType" value="text/html; charset=utf-8"/>
- <property name="suffix" value=".ftl" /> <!-- 本行配置文件类型,freemarker文件类型标准是ftl -->
- <!-- 如果有多种解析器,添加下面这行,让freemarker解析器优先 -->
- <property name="order" value="0" />
- </bean>
接下来加上freemarker的配置
- <bean id="freemarkerConfig"
- class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
- <property name="templateLoaderPath">
- <value>/WEB-INF/t/</value> <!-- 你的模版文件的存放路径,我这里存放在WEB-INF目录下的t文件夹里 -->
- </property>
- <property name="defaultEncoding">
- <value>utf-8</value>
- </property>
- <property name="freemarkerSettings">
- <props>
- <prop key="template_update_delay">3600</prop> <!-- 模版更新间隔,开发时设为1,项目工作时建议设置为较大数字-->
- </props>
- </property>
- <!-- 假设你需要使用freemarker的自定义标签,这里还需要增加这一段 -->
- <property name="freemarkerVariables">
- <map>
- <entry key="XXDirective" value-ref="XXDirective"/>
- <!-- 这里配置的是自定义标签,建议命名为XXDirective,有多个就一起在这里配置 -->
- </map>
- </property>
- </bean>
- <!-- 使用自定义标签还需要配置自定义标签的bean,不使用自定义标签不用写 -->
- <bean id="XXDirective" class="..XXDirective"/>
四、编写Controller
- @RequestMapping(value = "/document/getArticle.action")
- public String getColumn( ModelMap root) throws Exception {
- root.put(“art_content”, “这是一篇文章”);
- return article;//与模版名称相对应
- }
五、在前面配置的模版路径下编写article.ftl
- <!DOCTYPE html>
- <html>
- <head>
- </head>
- <body>
- ${art_content}
- </body>
- </html>
那么访问getArticle.action则跳转到页面输出结果:这是一篇文章 六、自定义标签的使用
这里例举一个最简单的用法,我的数据库中有一个文章表(文章有很多属性title、content等),假设我需要在article.ftl的页面上指定我需要取id=5的这篇文章标题和内容,这时候,就可以用到自定义标签了。(用法很多,这里只简单介绍一下)
首先编写一个自定义标签类实现TemplateDirectiveModel接口:
- public class ArticleDirective implements TemplateDirectiveModel {
- public void execute(Environment env, Map params, TemplateModel[] loopVars,TemplateDirectiveBody body) throws TemplateException {
- Object paramValue = params.get("articleId"); //这里模版页面传进来的参数叫做articleId
- int id=0;
- if (paramValue instanceof TemplateNumberModel) {
- id = ((TemplateNumberModel) paramValue).getAsNumber().intValue();
- }
- <span style="white-space:pre"> </span>/* Freemarker自定义标签不能直接识别传过来的数据类型参数,例如参数是字符串类型的参数,则用到SimpleScalar,比方说参数param是一个String,那么要先将参<span style="white-space:pre"> </span>数强转为SimpleScalar类型再使用其getAsString方法。
- String id= (SimpleScalar) params.get("param").getAsString();
- 参数还可以是集合、数组类型、这里不一一介绍 */
- Article article = ArticleService.getArticleById(id); //然后这里调用service,通过id取得需要的文章article
- env.setVariable("article", DEFAULT_WRAPPER.wrap(article)); /*使用env.setVariable方法设置变量article(这个就是要返回给页面的数据),注意需要使用freemarker中的静态成员变量DEFAULT_WRAPPER把article处理一下 */
- body.render(env.getOut()); //最后使用body.render(env.getOut())将数据交给模版页面
- }
- }
然后编写Controller
- @RequestMapping(value = "/document/getArticle.action")
- public String getColumn( ModelMap root) throws Exception {
- root.put(“article_d”, new ArticleDirective()); /*把标签加进去,我的标签名为article_d,方便区分数据,注意命名不要与变量名一样,否则会出问题 */
- return article;
- }
那么article.ftl这样编写:
- <pre name="code" class="html"><!DOCTYPE html>
- <html>
- <head>
- </head>
- <body>
- <@article articleId = 5> <#-- 使用自定义标签,传入的参数与自定义标签类保持一致 -->
- 文章的标题是${article.title},文章的内容是${article.content}
- </@article>
- </body>
- </html>
那么访问getArticle.action则跳转到页面输出结果:文章的标题是:...,文章的内容是...。如果我访问这个页面时需要输出第六篇文章,那么只需要在模版上把articleId设定为6就可以啦。
好了,这就是最简单的整合流程了。
|