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>高级搜索&nbsp;&nbsp;<a href="#"><i class="fa fa-search fa-lg"></i></a></span></div><a href="#">邮箱登陆1</a><span>&emsp;|&emsp;</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)

返回的静态页效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/892273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GetMaterialApp组件的功能与用法

文章目录 1. 知识回顾2. 使用方法2.1 源码分析2.2 常用属性3. 示例代码4. 内容总结我们在上一章回中介绍了"Get包简介"相关的内容,本章回中将介绍GetMaterialApp组件.闲话休提,让我们一起Talk Flutter吧。 1. 知识回顾 我们在上一章回中已经介绍过GetMaterialApp组…

插入实体自增主键太长,mybatis-plaus自增主键

1、问题 spring-boot整合mybtais执行insert语句时&#xff0c;主键id为长文本数据。 2、分析问题 1)数据库主键是否自增 2&#xff09;数据库主键的种子值设置的多少 3、解决问题 1&#xff09;数据库主键设置的时自增 3&#xff09;种子值是1 所以排查是数据库的问题 4、继…

【嵌入式硬件】嵌入式显示屏接口

数字显示串行接口&#xff08;Digital Display Serial Interface&#xff09; SPI 不过多赘述。 I2C-bus interface 不过多赘述 MIPI DSI MIPI (Mobile Industry Processor Interface) Alliance, DSI (Display Serial Interface) 一般用于移动设备&#xff0c;下面是接口…

(STM32笔记)十二、DMA的基础知识与用法 第三部分

我用的是正点的STM32F103来进行学习&#xff0c;板子和教程是野火的指南者。 之后的这个系列笔记开头未标明的话&#xff0c;用的也是这个板子和教程。 DMA的基础知识与用法 三、DMA程序验证1、DMA 存储器到存储器模式实验&#xff08;1&#xff09;DMA结构体解释&#xff08;2…

MySQL 如何赶上 PostgreSQL 的势头?

原文地址 我与 MySQL 社区的前辈交谈时&#xff0c;经常遇到这个问题&#xff1a;「为什么 MySQL 这么棒&#xff0c;而且&#xff08;至少根据 DB-Engines 的计算&#xff09;仍然比 PostgreSQL 更流行&#xff1b;但它的地位在下降&#xff0c;PostgreSQL 却势不可挡地越来越…

完全二叉树的删除

&#xff08;1&#xff09;删除叶子节点 找到要删除的节点 targetNode找到要删除节点的父节点parent&#xff08;父节点是否存在&#xff09;要删除的节点是父节点的左子树还是右子树如果是左子树&#xff0c;则parent.leftnull;如果是右子树则parent.rightnull。 &#xff08;…

Docker入门之docker基本命令

Docker入门之docker基本命令 官方网站&#xff1a;https://www.docker.com/ 1. 拉取官方镜像并创建容器&#xff08;以redis为例&#xff09; 拉取官方镜像 docker pull redis# 如果不需要添加到自定义网络使用这个命令&#xff0c;如需要&#xff0c;直接看第二步 docker r…

玩转大语言模型——ollama导入huggingface下载的模型

ollama导入huggingface模型 前言gguf模型查找相关模型下载模型 导入Ollama配置参数文件导入模型查看导入情况 safetensfors模型下载模型下载llama.cpp配置环境并转换 前言 ollama在大语言模型的应用中十分的方便&#xff0c;但是也存在一定的问题&#xff0c;比如不能使用自己…

DFS之迭代加深、双向DFS、IDA*

迭代加深 迭代加深&#xff1a; 170. 加成序列 满足如下条件的序列 X X X&#xff08;序列中元素被标号为 1 、 2 、 3 … m 1、2、3…m 1、2、3…m&#xff09;被称为“加成序列”&#xff1a; X [ 1 ] 1 X[1]1 X[1]1 X [ m ] n X[m]n X[m]n X [ 1 ] < X [ 2 ] < …

Ansible之批量管理服务器

文章目录 背景第一步、安装第二步、配置免密登录2.1 生成密钥2.2 分发公钥2.3 测试无密连接 背景 Ansible是Python强大的服务器批量管理 第一步、安装 首先要拉取epel数据源&#xff0c;执行以下命令 yum -y install epel-release安装完毕如下所示。 使用 yum 命令安装 an…

【Linux网络编程】第二十二弹---深入理解 I/O 多路转接之 epoll:系统调用、工作原理、代码演示及应用场景

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【Linux网络编程】 目录 1、I/O 多路转接之 epoll 1.1、epoll 初识 1.2、epoll 的相关系统调用 1.2.1、epoll_create 1.2.2、epol…

双向列表的实现(C++)

一.实现思路 主要是一个空间存储一个数值&#xff0c;然后为了索引后面的数据单元和前面的数据单元&#xff0c;所以在每个空间里面还要存储前面和后面数据单元的指针&#xff0c;就形成了每个数据单元 后面就是要管理的是双向列表的头结点和尾节点&#xff0c;方便实现后面的头…

国产信创实践(国能磐石服务器操作系统CEOS +东方通TongHttpServer)

替换介绍&#xff1a; 国能磐石服务器操作系统CEOS 对标 Linux 服务器操作系统&#xff08;Ubuntu, CentOS&#xff09; 东方通TongHttpServer 对标 Nginx 负载均衡Web服务器 第一步&#xff1a; 服务器安装CEOS映像文件&#xff0c;可直接安装&#xff0c;本文采用使用VMware …

Linux——修改USB网卡设备节点名称

修改驱动&#xff1a; 测试&#xff1a; 参考资料&#xff1a; https://blog.csdn.net/ablexu2018/article/details/144868950

上手体验微软全新整合的王炸平台Fabric

体验确实不错&#xff0c;微软强大的生态能力。 把可视化&#xff0c;数仓&#xff0c;数据胡&#xff0c;数据工厂&#xff0c;机器学习&#xff0c;数据监控等技术都整合到一个平台了。所有数据全都存储在统一的one lake数据中心&#xff0c;消除数据孤岛问题。而且不同角色可…

浅析PCIe链路均衡技术原理与演进

在现代计算机硬件体系的持续演进中&#xff0c;PCIe技术始终扮演着核心角色&#xff0c;其作为连接 CPU 与各类周边设备的关键高速通信链路&#xff0c;不断推动着计算机性能边界的拓展。而 PCIe Link Equalization均衡技术&#xff0c;作为保障数据在高速传输过程中准确性与稳…

东京大学联合Adobe提出基于指令的图像编辑模型InstructMove,可通过观察视频中的动作来实现基于指令的图像编辑。

东京大学联合Adobe提出的InstructMove是一种基于指令的图像编辑模型&#xff0c;使用多模态 LLM 生成的指令对视频中的帧对进行训练。该模型擅长非刚性编辑&#xff0c;例如调整主体姿势、表情和改变视点&#xff0c;同时保持内容一致性。此外&#xff0c;该方法通过集成蒙版、…

Wireshark 学习笔记1

1.wireshark是什么 wireshark是一个可以进行数据包的捕获和分析的软件 2.基本使用过程 &#xff08;1&#xff09;选择合适的网卡 &#xff08;2&#xff09;开始捕获数据包 &#xff08;3&#xff09;过滤掉无用的数据包 &#xff08;4&#xff09;将捕获到的数据包保存为文件…

学习threejs,导入babylon格式的模型

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.BabylonLoader babyl…

Redis缓存穿透、缓存击穿、缓存雪崩

缓存穿透 定义&#xff1a; 查询一个不存在的数据&#xff0c;mysql查询不到数据也不会直接写入缓存&#xff0c;就会导致每次请求都查数据库 例子&#xff1a; 一个get请求&#xff1a;api/news/getById/-1 解决方案 方案一&#xff1a;缓存空数据 缓存空数据&#xff0c;查…