How to get absolute path basePath from freemarker page

Source: https://segmentfault.com/a/1190000002967105

Traditional Relative Path Approach

1. freemarker acquisition system relative path mode

Configuration in spring-mvc.xml

<!-- FreeMarker View parsing such as return userinfo. . Configure the suffix name here ftl And view parser. -->
<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>

Among them, <property name="requestContextAttribute" value="request"/> is the key.

Settings in ftl pages

<#assign base=request.contextPath />
<!DOCTYPE html>
<html lang="zh">
<head>
    <base id="base" href="${base}">
    <title>home page</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>

Getting path in js file

var base = document.getElementById("base").href;
// Interacting with the background
_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);
        }
    });
};

You can get the path with the project name, but the path is the relative path, which is entered by the browser. http://localhost:8080/test-web/index.html Visit, all OK.

Use absolute path

1. Sources of the problem

Use domain name to access the system directly, modify the use of Tomcat 7 configuration file http://localhost/index.html The default port 80 and virtual project name are configured to be empty.

server.xml configuration

<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 &quot;%r&quot; %s %b" />

    <Context path="" docBase="test-web" reloadable="true"/>

  </Host>

The modified var base = document.getElementById("base").href; the base value obtained is http://localhost/index.html But < base id = "base" href = "${base}"> here href = "" causes the request url of ajax Base +'/'+ url, there is a problem.

2. Solutions

Add spring interceptor, get HttpServletRequest, assemble absolute path and put it in attributes attribute of request. Just take the value of ${basePath} directly in ftl file. Static file <link href="${basePath}/ static/bower_components/bootstrap/dist/css/bootstrap.min.css" rel= "stylesheet"> hidden form in dybody <input type= "hidden" id= "base" Value="${basePath}"/>, js can also get var base = $(' base'). val () by hiding the form.

Interceptor code

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;
    }

}

Interceptors are configured in spring-mvc.xml, and the order of interception is top-down

<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>

When absolute paths are used, many problems caused by reference paths are avoided.

Reference to the above ideas http://www.oschina.net/question/860595_140510 Solution, by inheriting the FreeMarker view parsing class org. spring framework. web. servlet. view. freemarker. FreeMarkerView, rewriting the exposeHelpers method, configuring its own FreeMarker view parser in spring, can be obtained in the template through ${base}.

MyFreeMarkerView code

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 configuration

<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <! - Customize FreeMarkerView to define the global path of the project
    <property name="viewClass" value="com.kyt.utils.MyFreeMarkerView" />
</bean>

Always asking for, but never giving, here's a little respect.

Keywords: FreeMarker Spring xml JSON

Added by mjr on Thu, 23 May 2019 23:39:05 +0300