freemarker页面如何获取绝对路径basePath
传统用相对路径方式
1、freemarker获取系统相对路径方式
spring-mvc.xml 中配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | <!-- FreeMarker视图解析 如返回userinfo。。在这里配置后缀名ftl和视图解析器。。 --> <bean id="viewResolverFtl"     class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">     <property name="viewClass"         value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />     <property name="suffix" value=".ftl" />     <property name="contentType" value="text/html;charset=UTF-8" />     <property name="exposeRequestAttributes" value="true" />     <property name="exposeSessionAttributes" value="true" />     <property name="exposeSpringMacroHelpers" value="true" />     <property name="requestContextAttribute" value="request" />     <property name="cache" value="true" />     <property name="order" value="0" /> </bean>
 
   | 
 
其中<property name="requestContextAttribute" value="request" />是关键。
ftl页面中设置
1 2 3 4 5 6 7 8 9 10
   | <#assign base=request.contextPath /> <!DOCTYPE html> <html lang="zh"> <head>     <base id="base" href="${base}">     <title>首页</title>     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">     <link href="${base}/static/bootstrap-3.3.4/css/bootstrap.min.css" rel="stylesheet">     <script src="${base}/static/bootstrap-3.3.4/js/bootstrap.min.js"></script>
 
   | 
 
js文件中获取path
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | var base = document.getElementById("base").href; // 与后台交互 _send = function(async, url, value, success, error) {     $.ajax({         async : async,         url : base + '/' + url,         contentType : "application/x-www-form-urlencoded; charset=utf-8",         data : value,         dataType : 'json',         type : 'post',         success : function(data) {             success(data);         },         error : function(data) {             error(data);         }     }); };
 
  | 
 
即可获取带项目名的路径,但这路径是相对路径,浏览器输入http://localhost:8080/test-web/index.html访问,一切OK。
使用绝对路径方式
1. 问题来源
用域名直接访问系统,修改tomcat7配置文件使用http://localhost/index.html方式,即配置默认80端口和虚拟项目名称为空。
server.xml配置
1 2 3 4 5 6 7 8 9 10 11
   | <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Host name="localhost"  appBase="webapps"         unpackWARs="true" autoDeploy="true">     <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"            prefix="localhost_access_log." suffix=".txt"            pattern="%h %l %u %t "%r" %s %b" />
      <Context path="" docBase="test-web" reloadable="true"/>
    </Host>
 
   | 
 
修改后var base = document.getElementById("base").href;获取的base值是http://localhost/index.html但<base id="base" href="${base}">这里的href=””所以导致ajax的请求url : base + '/' + url,出现了问题。
2. 解决方案
增加spring拦截器,获取HttpServletRequest,拼装绝对路径放在request的attribute属性中,ftl文件中直接${basePath}取值就可以了,静态文件<link href="${basePath}/static/bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> body中的隐藏表单<input type="hidden" id="base" value="${basePath}" />,js获取path也可以通过隐藏表单获取var base = $('#base').val();
拦截器代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | public class BasePathInterceptor extends HandlerInterceptorAdapter {
  private static Logger logger = Logger.getLogger(BasePathInterceptor.class);
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {         String scheme = request.getScheme();         String serverName = request.getServerName();         int port = request.getServerPort();         String path = request.getContextPath();         String basePath = scheme + "://" + serverName + ":" + port + path;         logger.info(basePath);         request.setAttribute("basePath", basePath);         return true;     }
  }
 
  | 
 
spring-mvc.xml中配置拦截器,拦截顺序至上而下
1 2 3 4 5 6 7 8 9 10 11 12 13
   | <mvc:interceptors>     <mvc:interceptor>         <mvc:mapping path="/**"/>         <bean class="com.test.interceptor.BasePathInterceptor"></bean>     </mvc:interceptor>     <mvc:interceptor>         <mvc:mapping path="/**"/>         <mvc:exclude-mapping path="/login.html"/>         <!-- <mvc:exclude-mapping path="/*/ajax/**"/> -->         <bean class="com.test.interceptor.LoginInterceptor"></bean>     </mvc:interceptor> </mvc:interceptors>
 
   | 
 
用上绝对路径之后,就会避免很多因为引用路径上带来的问题。
以上思路参考http://www.oschina.net/question/860595_140510的解决方案,通过继承freemarker视图解析类org.springframework.web.servlet.view.freemarker.FreeMarkerView,重写exposeHelpers方法,在spring里配置自己的freemarker的视图解析器,在模板中就可以通过${base}获取。
MyFreeMarkerView 代码
1 2 3 4 5 6 7 8 9 10 11
   | public class MyFreeMarkerView extends FreeMarkerView {     private static final String CONTEXT_PATH = "base";      @Override     protected void exposeHelpers(Map<String, Object> model,         HttpServletRequest request) throws Exception {         model.put(CONTEXT_PATH, request.getContextPath());         super.exposeHelpers(model, request);     }
  }
 
  | 
 
spring-mvc.xml配置
1 2 3 4 5
   | <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">     <!-- 自定义FreeMarkerView,用来定义项目的全局路径 -->     <property name="viewClass" value="com.kyt.utils.MyFreeMarkerView" /> </bean>
 
   |