SpringBoot + Freemarker 进行前端模板加载

一、前言

前后端分离的项目,打包编译前端文件后直接放到spring boot后台下使用

 

二、引入 Freemarker 并且进行配置

1. pom引入
   <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-freemarker</artifactId>
   </dependency>


2. yml配置
  spring:
    freemarker:
    suffix: .html
    request-context-attribute: request
    content-type: text/html
    enabled: true
    cache: false #缓存配置
    template-loader-path: classpath:/static/ #模板加载路径 按需配置
    charset: UTF-8 #编码格式



三、我打包完后端静态文件,对应的文件层层级如下,外层对应上面的模板加载路径

 

四、自定义配置静态资源

package io.sf.modules.app.config;

import io.sf.modules.app.interceptor.AuthorizationInterceptor;
import io.sf.modules.app.resolver.LoginUserHandlerMethodArgumentResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * MVC配置
 *
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private AuthorizationInterceptor authorizationInterceptor;
    @Autowired
    private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authorizationInterceptor).addPathPatterns("/app/**");
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /**
         * 注册静态文件路径 配置外部的资源要使用file声明,配置jar包内部的使用classpath声明
         */
        // 首页
        registry.addResourceHandler("/index.html").addResourceLocations("classpath:/static/index.html");
        // 对应的 index.js
        registry.addResourceHandler("/config/**").addResourceLocations("classpath:/static/config/");
        // 其余静态文件的路径解析
        registry.addResourceHandler("/2005291458/static/**").addResourceLocations("classpath:/static/2005291458/static/");
    }
}

五、上面的请求前缀是根据你的js请求路径来配置的,我的node 10.x版本的index.js配置如下

/**
 * 生产环境
 */
;(function () {
  window.SITE_CONFIG = {};

  // api接口请求地址
  window.SITE_CONFIG['baseUrl'] = 'http://10.5.9.15:9090/';

  // cdn地址 = 域名 + 版本号
  window.SITE_CONFIG['domain']  = './'; // 域名
  window.SITE_CONFIG['version'] = '2005291458';   // 版本号(年月日时分)
  window.SITE_CONFIG['cdnUrl']  = window.SITE_CONFIG.domain + window.SITE_CONFIG.version;
})();

/**
 * 动态加载初始资源  
// 静态文件请求的路径就是 域名/2005291458/static/*** 
 */
;(function () {
  var resList = {
    icon: window.SITE_CONFIG.cdnUrl + '/static/img/favicon.ico',
    css: [
      window.SITE_CONFIG.cdnUrl + '/static/css/app.css'
    ],
    js: [
      // 插件, 放置业务之前加载, 以免业务需求依赖插件时, 还未加载出错
      // 插件 - echarts
      window.SITE_CONFIG.cdnUrl + '/static/plugins/echarts-3.8.5/echarts.common.min.js',
      // 插件 - ueditor
      window.SITE_CONFIG.cdnUrl + '/static/plugins/ueditor-1.4.3.3/ueditor.config.js',
      window.SITE_CONFIG.cdnUrl + '/static/plugins/ueditor-1.4.3.3/ueditor.all.min.js',
      window.SITE_CONFIG.cdnUrl + '/static/plugins/ueditor-1.4.3.3/lang/zh-cn/zh-cn.js',
      // 业务
      window.SITE_CONFIG.cdnUrl + '/static/js/manifest.js',
      window.SITE_CONFIG.cdnUrl + '/static/js/vendor.js',
      window.SITE_CONFIG.cdnUrl + '/static/js/app.js'
    ]
  };

  // 图标
  (function () {
    var _icon = document.createElement('link')
    _icon.setAttribute('rel', 'shortcut icon')
    _icon.setAttribute('type', 'image/x-icon')
    _icon.setAttribute('href', resList.icon)
    document.getElementsByTagName('head')[0].appendChild(_icon)
  })();

  // 样式
  (function () {
    document.getElementsByTagName('html')[0].style.opacity = 0
    var i = 0
    var _style = null
    var createStyles = function () {
      if (i >= resList.css.length) {
        document.getElementsByTagName('html')[0].style.opacity = 1
        return
      }
      _style = document.createElement('link')
      _style.href = resList.css[i]
      _style.setAttribute('rel', 'stylesheet')
      _style.onload = function () {
        i++
        createStyles()
      }
      document.getElementsByTagName('head')[0].appendChild(_style)
    }
    createStyles()
  })()

  // 脚本
  document.onreadystatechange = function () {
    if (document.readyState === 'interactive') {
      var i = 0
      var _script = null
      var createScripts = function () {
        if (i >= resList.js.length) {
          return
        }
        _script = document.createElement('script')
        _script.src = resList.js[i]
        _script.onload = function () {
          i++
          createScripts()
        }
        document.getElementsByTagName('body')[0].appendChild(_script)
      }
      createScripts()
    }
  }
})()

六、配置shiro或者spring security的路径过滤

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        shiroFilter.setLoginUrl("/login.html");
        shiroFilter.setUnauthorizedUrl("/");

        //oauth过滤
        Map<String, Filter> filters = new HashMap<>();
        filters.put("oauth2", new OAuth2Filter());
        shiroFilter.setFilters(filters);

        Map<String, String> filterMap = new LinkedHashMap<>();
       
        filterMap.put("/app/**", "anon");
        filterMap.put("/index.html", "anon");
        filterMap.put("/sys/login", "anon");
        filterMap.put("/captcha.jpg", "anon");
        filterMap.put("/2005291458/static/**", "anon");
        filterMap.put("/config/**", "anon");
     
        shiroFilter.setFilterChainDefinitionMap(filterMap);

        return shiroFilter;
    }

 

七、自定义跳转

package io.sf.modules.sys.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 系统页面视图
 * 
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2016年11月24日 下午11:05:27
 */
@Controller
public class SysPageController {
	
	@RequestMapping(value = {"/", "index.html"})
	public String index(){
		return "index";
	}

	@RequestMapping("login.html")
	public String login(){
                // 会自动拼上freemarker的后缀
		return "index";
	}

	@RequestMapping("404.html")
	public String notFound(){
		return "404";
	}

}

八、后记

仅作记录和参考,有错误欢迎交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值