使用RESTful风格,故需要额外注意DispatcherServlet的url-pattern和applicationContext.xml中的配置。
<mvc:default-servlet-handler/>
【1】applicationContext.xml配置
applicationContext.xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="com" /> <mvc:annotation-driven /> <mvc:default-servlet-handler/> <!-- 配置freemarker --> <bean id="freemarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/views/" /> <!--<property name="freemarkerSettings" ref="freemarkerConfiguration"/> --> <property name="freemarkerSettings"> <props> <!-- 禁用freemarker缓存 --> <prop key="template_update_delay">0</prop> <prop key="default_encoding">UTF-8</prop> <prop key="url_escaping_charset">UTF-8</prop> <prop key="locale">zh_CN</prop> <prop key="localized_lookup">false</prop> <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop> <prop key="date_format">yyyy-MM-dd</prop> <prop key="time_format">HH:mm:ss</prop> <prop key="boolean_format">true,false</prop> <prop key="number_format">#.##</prop> //设置数字格式化,不被逗号隔开 </props> </property> <!--这里设置需要配置的变量--> <property name="freemarkerVariables"> <map> <entry key="xml_escape" value-ref="fmXmlEscape" /> </map> </property> </bean> <!--这里配置xml转译工具类--> <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" /> <!-- 如果属性配置在properties文件中,可使用如下代码(上面的freemarkerSettings可配置在properties文件中) --> <!-- <bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="location" value="classpath:freemarker.properties" /> </bean> --> <!-- freemarker配置视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <!-- 禁用SpringMVC缓存 --> <property name="cache" value="false" /> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/> <!-- 扫描路径內所有以ftl結尾的文件 viewNames 和suffix 只能存在一个 --> <!-- <property name="viewNames"> --> <!-- <array> --> <!-- <value>*.ftl</value> --> <!-- </array> --> <!-- </property> --> <property name="suffix" value=".ftl" /> <property name="contentType" value="text/html;charset=UTF-8"/> <property name="requestContextAttribute" value="request" /> <property name="exposeSpringMacroHelpers" value="true" /> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> </bean> </beans>
【2】web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>hh-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>namespace</param-name> <param-value>hh-mvc</param-value> </init-param> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext.xml</param-value> </init-param> <init-param> <param-name>publishContext</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hh-mvc</servlet-name> <!-- 注意这里 --> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
【3】测试实例
① 后台代码
package com.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @RequestMapping("/data") @Controller public class DataController { @RequestMapping("/hello") public ModelAndView hello(){ ModelAndView mv = new ModelAndView(); mv.addObject("msg", "hello world !"); mv.setViewName("hello"); return mv; } }
② FTL模板
<#assig<#assign base=request.contextPath/> <!DOCTYPE html> <html> <head> <base id="base" href="${base}"> <meta charset="UTF-8"> <title>hello ftl</title> <script type="text/javascript"> var base = document.getElementById("base").href; console.log(base); </script> </head> <body> ${msg} </body> </html>
【4】XmlEscape
对给定的模板片段执行XML转义,此转换的实例最初作为共享变量xml_escape
可见。即,其他地方使用xml_escape
变量来引用该实例。
其源码如下:
package freemarker.template.utility; import java.io.IOException; import java.io.Writer; import java.util.Map; import freemarker.template.TemplateTransformModel; /** * Performs an XML escaping of a given template fragment. Specifically, * <tt><</tt> <tt>></tt> <tt>"</tt> <tt>'</tt> and <tt>&</tt> are all turned into entity references. * * <p>An instance of this transform is initially visible as shared * variable called <tt>xml_escape</tt>.</p> */ public class XmlEscape implements TemplateTransformModel { private static final char[] LT = "<".toCharArray(); private static final char[] GT = ">".toCharArray(); private static final char[] AMP = "&".toCharArray(); private static final char[] QUOT = """.toCharArray(); private static final char[] APOS = "'".toCharArray(); public Writer getWriter(final Writer out, Map args) { return new Writer() { public void write(int c) throws IOException { switch(c) { case '<': out.write(LT, 0, 4); break; case '>': out.write(GT, 0, 4); break; case '&': out.write(AMP, 0, 5); break; case '"': out.write(QUOT, 0, 6); break; case '\'': out.write(APOS, 0, 6); break; default: out.write(c); } } public void write(char cbuf[], int off, int len) throws IOException { int lastoff = off; int lastpos = off + len; for (int i = off; i < lastpos; i++) { switch (cbuf[i]) { case '<': out.write(cbuf, lastoff, i - lastoff); out.write(LT, 0, 4); lastoff = i + 1; break; case '>': out.write(cbuf, lastoff, i - lastoff); out.write(GT, 0, 4); lastoff = i + 1; break; case '&': out.write(cbuf, lastoff, i - lastoff); out.write(AMP, 0, 5); lastoff = i + 1; break; case '"': out.write(cbuf, lastoff, i - lastoff); out.write(QUOT, 0, 6); lastoff = i + 1; break; case '\'': out.write(cbuf, lastoff, i - lastoff); out.write(APOS, 0, 6); lastoff = i + 1; break; } } int remaining = lastpos - lastoff; if(remaining > 0) { out.write(cbuf, lastoff, remaining); } } public void flush() throws IOException { out.flush(); } public void close() { } }; } }