• freemarker页面如何获取绝对路径basePath


    传统用相对路径方式

    1. freemarker获取系统相对路径方式

    spring-mvc.xml 中配置

    <!-- 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页面中设置

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

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

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

    修改后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();

    拦截器代码

    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中配置拦截器,拦截顺序至上而下

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

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

    <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <!-- 自定义FreeMarkerView,用来定义项目的全局路径 -->
        <property name="viewClass" value="com.kyt.utils.MyFreeMarkerView" />
    </bean>
  • 相关阅读:
    spring boot welcome-file-list
    spring boot web.xml listener
    Linkflow CDP
    连接数据,构建中台,Linkflow如何推动数据化浪潮 CDP
    客户全生命周期服务解决方案的提供商。
    自然语言处理的发展历史 发展方向 行业(法律)
    SpringBoot 设置 profiles 并在其他配置文件里面读取 pom.xml
    SpringBoot 配置文件无法解析占位符
    微服务 SaaS 低代码开发平台
    混沌工程与分布式系统
  • 原文地址:https://www.cnblogs.com/wshsdlau/p/4664616.html
Copyright © 2020-2023  润新知