一、前言
前后端分离的项目,打包编译前端文件后直接放到spring boot后台下使用
二、引入 Freemarker 并且进行配置
1. pom引入
org.springframework.boot
spring-boot-starter-freemarker
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 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 filters = new HashMap<>();
filters.put("oauth2", new OAuth2Filter());
shiroFilter.setFilters(filters);
Map 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 [email protected]
* @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";
}
}
八、后记
仅作记录和参考,有错误欢迎交流