SpringBoot项目实战(39)--Beetl网页HTML文件中静态图片及CSS、JS文件的引用和展示
使用Beetl开发网页时,在网页中使用的CSS、JS、图片等静态资源需要进行适当的配置才可以展示。大致的过程如下:
(1)首先Spring Security框架需要允许js、css、图片资源免授权访问。
(2)网站开发时,如果网页文件不放在SpringBoot工程内部打包,单独指定了文件目录,需要在Config文件中加载文件系统中的网页目录。
(3)网页文件中引用静态文件的路径不能使用相对路径,需要使用绝对路径。
(4)如果使用了Nginx,静态资源文件路径还要加上 Nginx反向代理的路径。
下面是实现过程:
首先贴一下之前openjweb-sys工程的WebSecurityConfig文件,增加了js目录、css目录、images目录的免授权访问:
package opackage org.openjweb.sys.config;import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.openjweb.core.service.CommUserService;
import org.openjweb.sys.auth.security.AESPasswordEncoder;
import org.openjweb.sys.auth.security.MD5PasswordEncoder;
import org.openjweb.sys.auth.security.MyAccessDecisionManager;
import org.openjweb.sys.auth.security.MyFilterInvocationSecurityMetadataSource;
import org.openjweb.sys.entry.JwtAuthenticationEntryPoint;
import org.openjweb.sys.filter.JwtAuthenticationFilter;
import org.openjweb.sys.handler.JWTLogoutSuccessHandler;
import org.openjweb.sys.handler.JwtAccessDeniedHandler;
import org.openjweb.sys.handler.LoginFailureHandler;
import org.openjweb.sys.handler.LoginSuccessHandler;
import org.openjweb.sys.provider.MyAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;@Slf4j
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@AutowiredCommUserService userDetailService;@Beanpublic PasswordEncoder passwordEncoder(){return new AESPasswordEncoder();}@AutowiredLoginSuccessHandler loginSuccessHandler;@AutowiredLoginFailureHandler loginFailureHandler;@AutowiredJwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;@AutowiredJwtAccessDeniedHandler jwtAccessDeniedHandler;@AutowiredJWTLogoutSuccessHandler jwtLogoutSuccessHandler;@Value("${oauth2.server}")private boolean isOAuth2Server = false;private static final String[] ALLOW_URL_LIST = {//"/login","/logout","/captcha","/favicon.ico",//"/api/jwt/**","/api/cms/**","/api/b2c/**","/api/b2b2c/**","/api/sns/**","/api/comm/**","/api/cms1/**","/api/store/**","/demo/**","/oauth/**", //允许oauth认证的路径"/webjars/**", //webjars js允许的路径"/testduoyu","/i18n/**","/**/*.html", //swagger"/api/comm/user/login","/api/weixin/login","/api/weixin/getVueMenu","/api/comm/user/getUserInfo2","/front/**","/**/js/**","/**/images/**","/**/css/**"};//作用???暴露AuthenticationManager给其他Bean使用@Bean@Overrideprotected AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();//return super.authenticationManagerBean();}//这个和上面的是什么区别?能一起用吗?/*@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception{return super.authenticationManagerBean();}*/@Overrideprotected void configure(HttpSecurity http) throws Exception {//下面注释掉的是第一阶段的示例/* http.cors().and().csrf().disable()//登录表单.formLogin().and().authorizeRequests().antMatchers(ALLOW_URL_LIST).permitAll().anyRequest().authenticated();*///下面是第二阶段整合了数据库权限控制的示例log.info("是否配置了oauth2 server:::::");log.info(String.valueOf(this.isOAuth2Server));if(this.isOAuth2Server){log.info("OAUTH2模式...........");http.formLogin()//.loginPage("/login.html").loginProcessingUrl("/login").and().authorizeRequests().antMatchers("/login.html", "/img/**","/demo/**","/webjars/**", "/testduoyu","/i18n/**","/api/b2c/b2carea/**","/api/store/**","/**/*.html", "/api/comm/user/login","/api/weixin/login","/api/weixin/getVueMenu","/api/comm/user/getUserInfo2", "/front/**","/**/js/**", "/**/images/**", "/**/css/**").permitAll().anyRequest().authenticated().and().csrf().disable();}else {log.info("非OAUTH2模式............");http.authorizeRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {@Overridepublic <O extends FilterSecurityInterceptor> O postProcess(O object) {object.setSecurityMetadataSource(cfisms());object.setAccessDecisionManager(cadm());return object;}}).and().formLogin()//先注掉这个检查oauth认证//.successHandler(loginSuccessHandler) //登录成功处理.failureHandler(loginFailureHandler) //登录失败处理.loginProcessingUrl("/login").permitAll()//.loginProcessingUrl("/demo/jwt/login").permitAll().and().logout().logoutSuccessHandler(jwtLogoutSuccessHandler)// 禁用session.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)// 配置拦截规则.and().authorizeRequests().antMatchers(ALLOW_URL_LIST).permitAll().anyRequest().authenticated()// 异常处理器.and().exceptionHandling()//接口登录模式打开这个//.authenticationEntryPoint(jwtAuthenticationEntryPoint) //这个影响登录,会导致/login登录蔬菜.accessDeniedHandler(jwtAccessDeniedHandler)// 配置自定义的过滤器//这个jwtAuthenticationFilter 不加也执行了,是否增加了会调整多个过滤器的执行顺序.and().addFilter(jwtAuthenticationFilter()).logout().permitAll().and().csrf().disable();}}/*@BeanPasswordEncoder PasswordEncoder() {//return md5PasswordEncoder;//return aesPasswordEncoder;//这个不行return new AESPasswordEncoder();//return new BCryptPasswordEncoder();//return new Md5PasswordEncoder();}*//*@AutowiredMD5PasswordEncoder md5PasswordEncoder;@AutowiredAESPasswordEncoder aesPasswordEncoder;*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {if(true){//如果自定义AuthenticationProvider 则不使用这个//auth.userDetailsService(userDetailService).passwordEncoder(aesPasswordEncoder);//auth.userDetailsService(userDetailService).passwordEncoder(new BCryptPasswordEncoder());DaoAuthenticationProvider provider = new DaoAuthenticationProvider();provider.setUserDetailsService(userDetailService);provider.setPasswordEncoder(passwordEncoder());auth.authenticationProvider(provider);}else{//自定义AuthenticationProviderauth.authenticationProvider(new MyAuthenticationProvider(userDetailService));}}@BeanMyAccessDecisionManager cadm() {//System.out.println("加载角色权限设置。。。。。。。。。。。。");return new MyAccessDecisionManager();}@BeanMyFilterInvocationSecurityMetadataSource cfisms() {//System.out.println("加载权限设置。。。。。。。。。。。。");return new MyFilterInvocationSecurityMetadataSource();}@Bean@ConditionalOnExpression("'${oauth2.server}'=='false'")JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());return jwtAuthenticationFilter;}
}
然后在openjweb-core工程的WebMvcConfig中增加文件系统中静态资源目录:
package org.openjweb.core.config;import lombok.extern.slf4j.Slf4j;
import org.beetl.core.GroupTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;import java.util.HashMap;
import java.util.Map;@Configuration
@Slf4j
public class WebMvcConfig implements WebMvcConfigurer {@Value("${beetl.fileTemplatesPath:}") String fileTemplatesPath;@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/testduoyu").setViewName("testduoyu");//不能命名testlocale 可能locale有冲突}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("fileTemplatePath::");log.info(fileTemplatesPath);if(!fileTemplatesPath.endsWith("/"))fileTemplatesPath+="/";//D:/tmp/beetl/templatesregistry.addResourceHandler("/**").addResourceLocations("file:"+fileTemplatesPath).addResourceLocations("classpath:/static/");}@Overridepublic void addInterceptors(InterceptorRegistry registry) {log.info("设置国际化参数lang...........");//默认拦截器 其中lang表示切换语言的参数名 LocaleChangeInterceptor 指定切换国际化语言的参数名。// 例如?lang=zh_CN 表示读取国际化文件messages_zh_CN.properties。//System.out.println("增加国际化拦截器...........");LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();localeInterceptor.setParamName("lang");// 指定设置国际化的参数registry.addInterceptor(localeInterceptor);}
}
在上面的代码中,增加了addResourceHandlers方法,此方法加载了文件系统fileTemplatePath目录的静态资源,在开发环境中,application-dev.yml中指定的fileTemplatePath是d:\tmp\beetl\templates。
项目的静态网页:
假设项目的静态网页路径是D:\tmp\beetl\templates\cms\site\wenhua,在此路径下有js、css、images目录以及html文件,下面截取了局部的HTML文件:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<title>中国文化网</title>
<meta name="keywords" content="中国文化网">
<meta name="description" content="中国文化网">
<link href="/clouds/cms/site/wenhua/css/common.css" rel="stylesheet" type="text/css" />
<link href="/clouds/cms/site/wenhua/css/font-awesome/css/font-awesome.min.css" rel="stylesheet"/>
<link href="/clouds/cms/site/wenhua/css/index.css" rel="stylesheet" type="text/css" />
<link href="/clouds/cms/site/wenhua/css/focus1.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="/clouds/cms/site/wenhua/js/jquery.1.7.2.min.js"></script>
<script type="text/javascript" src="/clouds/cms/site/wenhua/js/koala.min.1.5.js"></script>
<script type="text/javascript">$(function(){ var pw = $('#po-pic').width();var sw = $(window).width();var lw = (pw - sw)/2;$('#po-pic').attr('style','margin-left:-'+lw+'px');})
</script>
</head>
<body>
<div class="top"><div class="layout"><div class="fl logo"><a href="#"><img src="/clouds/cms/site/wenhua/images/logo.jpg" width="257" height="70" border="0" /></a></div><div class="fr top-nav"><div class="fr search"><input type="text" name="search" class="fr" /><span>高级搜索 <a href="#"><i class="fa fa-search fa-lg"></i></a></span></div><a href="#">邮箱登陆1</a><span> | </span></div><div class="clear"></div></div>
</div>
注意静态资源文件的引用:/clouds/cms/site/wenhua/css/common.css、/clouds/cms/site/wenhua/images/logo.jpg,其中clouds是使用Nginx反向代理将8001端口转发到了SpringBoot,如果没使用nginx,而是使用了localhost:8001,则不需要使用/clouds,后面/cms开头的路径则是针对模版文件跟路径下的相对路径,根路径为D:\tmp\beetl\templates。
现在我们开发一个控制层类,用于展示静态页面。在openjweb-cms内容管理模块增加一个控制层类:
package org.openjweb.cms.controller;import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.openjweb.cms.service.CmsInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.HashMap;
import java.util.Map;@Api(tags = "内容管理-前端查询")
@Slf4j
@Controller
@RequestMapping("/front") //public class CmsInfoController {@Autowiredprivate CmsInfoService cmsInfoService;@RequestMapping(value="/index")public String index( Model model) {return "cms/site/wenhua/index.html";//返回页面名}}
测试访问:http://localhost:8001/front/index (不使用nginx则html中静态资源不要加/clouds)
返回的静态页效果:

相关文章:
SpringBoot项目实战(39)--Beetl网页HTML文件中静态图片及CSS、JS文件的引用和展示
使用Beetl开发网页时,在网页中使用的CSS、JS、图片等静态资源需要进行适当的配置才可以展示。大致的过程如下: (1)首先Spring Security框架需要允许js、css、图片资源免授权访问。 (2)网站开发时࿰…...
ARIMA模型 (AutoRegressive Integrated Moving Average) 算法详解与PyTorch实现
ARIMA模型 (AutoRegressive Integrated Moving Average) 算法详解与PyTorch实现 目录 ARIMA模型 (AutoRegressive Integrated Moving Average) 算法详解与PyTorch实现1. ARIMA模型概述1.1 时间序列预测1.2 ARIMA的优势2. ARIMA的核心技术2.1 自回归 (AR)2.2 差分 (I)2.3 移动平…...
【Uniapp-Vue3】swiper滑块视图容器的用法
我们使用swiper标签就可以实现轮播图的效果。 一、swiper组件的结构 整体的轮播图使用swiper标签,轮播的每一页使用swiper-item标签。 <template><swiper class"swiper"><swiper-item><view class"swiper-item">111…...
allure报告修改默认语言为中文
1、项目根目录创建.py文件,把代码复制进去 import os from pathlib import Pathdef create_settings_js_file(directory"../pytest_mytt/reports/allures/", filenamesettings.js):# 创建或确认目录存在Path(directory).mkdir(parentsTrue, exist_okTrue…...
国产3D CAD将逐步取代国外软件
在工业软件的关键领域,计算机辅助设计(CAD)软件对于制造业的重要性不言而喻。近年来,国产 CAD 的发展态势迅猛,展现出巨大的潜力与机遇,正逐步改变着 CAD 市场长期由国外软件主导的格局。 国产CAD发展现状 …...
GolangWeb开发- net/http模块
文章目录 Golang开发-案例整理汇总一、net/http介绍二、HTTP客户端Get请求Post请求三、HTTP服务端总结Golang开发经典案例,点击下方链接 Golang开发-案例整理汇总 一、net/http介绍 Go语言内置的net/http包提供了HTTP客户端和服务端的实现。 文档链接: https://pkg.go.dev/n…...
Vue2中使用Echarts
1.安装echarts 在项目根目录下,使用npm或yarn安装ECharts: npm install echarts --save 或者 yarn add echarts 2.在相应的vue页面中引入echarts <script> import * as echarts from "echarts"; </script> 3.代码解析 <…...
AI赋能服装零售:商品计划智能化,化危机为转机
在服装零售这片竞争激烈的战场上,每一个细微的决策都可能成为品牌兴衰的关键。当市场波动、消费者口味变化、供应链挑战接踵而至时,许多品牌往往将危机归咎于外部环境。然而,真相往往更为深刻——“危机不是外部的,而是你的商品计…...
Spring AI ectorStore
Spring AI中的VectorStore是一种用于存储和检索高维向量数据的数据库或存储解决方案,它在AI应用中扮演着至关重要的角色。以下是对Spring AI VectorStore的详细解析: 一、VectorStore的基本概念 定义:VectorStore特别适用于处理那些经过嵌入…...
zig 安装,Hello World 示例
1. 安装 Zig 首先,你需要在你的计算机上安装 Zig 编译器。你可以从 Zig 官方网站 下载适合你操作系统的版本。 安装完成后,你可以在终端中运行以下命令来检查 Zig 是否安装成功: zig version如果一切正常,它会显示 Zig 的版本信…...
龙蜥Linux系统部署docker21.1.3版本
龙蜥系统配置docker环境 更新yum源 更新软件源中的包。 yum update安装底层工具 yum install -y yum-utils device-mapper-persistent-data lvm2添加阿里云仓库 # 添加阿里云的docker镜像仓库 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/c…...
django解决跨域问题
# 1.安装django-cors-headers 库 pip install django-cors-headers -i https://pypi.tuna.tsinghua.edu.cn/simple2.添加到应用程序中 添加 corsheaders 到你的 INSTALLED_APPS 设置中: INSTALLED_APPS [...corsheaders,... ]3.添加中间件 MIDDLEWARE [...cor…...
【蓝桥杯选拔赛真题60】C++寻宝石 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解
目录 C++寻宝石 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 五、运行结果 六、考点分析 七、推荐资料 C++寻宝石 第十四届蓝桥杯青少年创意编程大赛C++选拔赛真题 一、题目要求 1、编程实现 有N(1<N<100)个盒子排成一排,每个盒子都放…...
Git 从入门到精通
一、环境配置 下载地址:https://git-scm.com/downloads/ 二、用户配置 找到git bash git --version 查看当前版本 git config --global user.name szhipeng625 设置用户名 git config --global user.email szhipeng625gmail.com 设置邮箱 git config --global …...
vue3使用vue3-video-play播放m3u8视频
1.安装vue3-video-play npm install vue3-video-play --save2.在组件中使用 import vue3-video-play/dist/style.css; import VideoPlay from vue3-video-play;// 视频配置项 const options reactive({src: https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8, //视频源mute…...
使用API有效率地管理Dynadot域名,为文件夹中的域名统一设置电子邮件转发
关于Dynadot Dynadot是通过ICANN认证的域名注册商,自2002年成立以来,服务于全球108个国家和地区的客户,为数以万计的客户提供简洁,优惠,安全的域名注册以及管理服务。 Dynadot平台操作教程索引(包括域名邮…...
Java虚拟机(Java Virtual Machine,JVM)
一、Java 虚拟机 Java 虚拟机(Java Virtual Machine, JVM)是运行 Java 字节码的虚拟机。它是Java平台的核心组件之一,使得Java程序具有 一次编写,到处运行(Write Once, Run Anywhere) 的特性。 JVM 有针对…...
[免费]微信小程序(高校就业)招聘系统(Springboot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序(高校就业)招聘系统(Springboot后端Vue管理端),分享下哈。 项目视频演示 【免费】微信小程序(高校就业)招聘系统(Springboot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项目介绍…...
TCP Analysis Flags 之 TCP Retransmission
前言 默认情况下,Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态,并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时,会对每个 TCP 数据包进行一次分析,数据包按照它们在数据包列表中出现的顺序进行处理。可…...
#Phi-4:微软 14B 参数开源模型,性能匹敌 OpenAI GPT-4o-mini,现已登陆 Ollama
Phi-4:微软 14B 参数开源模型,性能匹敌 OpenAI GPT-4o-mini,现已登陆 Ollama 一、Phi-4 模型概述 (一)模型参数与规模 Phi-4 是微软推出的一款小型语言模型,拥有 140 亿参数。虽然参数量相对较小…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
