• 网站的静态资源怎么获取?


    功能需求如下:

    1. 现有一个后端应用,默认访问方式如下:summo-sbmy-front

    2. 用电脑、平板、手机等设备都可以访问,且不同的设备样式要适配,前端做了两套,但是访问接口都是同一个;

    3. 由于没有使用cdn,界面渲染的时候需要用到的字体库、图标库和一些图片也放在了后端应用;

    光文字讲需求可能不太直观,我放一些图片就好理解了,如下:

    使用电脑访问summo-sbmy-front出现的界面

    使用手机或平板访问summo-sbmy-front出现的界面

    可以看到这两个的样式不一样,组件也不一样,但是接口都是同一个。

    前端的资源如下

    文件有html、js、css,还有一些特殊的文件如字体,文件类型还是比较丰富的,且这样的资源有两份,一份是电脑端,一份是移动端。由于没有使用cdn,我们需要通过后端服务来访问这些资源。那么说到这里不知道大家有没有理解这个需求呢?其实简单理解就是SpringBoot的接口访问静态资源,下面就开始讲一下我是如何实现这个功能的。

    一、功能实现

    1. 从访问一个index.html开始

    (1)创建一个SpringBoot项目

    这个我就不啰嗦了,使用ide或者https://start.spring.io/网站创建一个即可。

    (2)引入SpringBoot模板引擎— Thymeleaf

    pom.xml引入

    1. <!-- thymeleaf -->
    2. <dependency>
    3. <groupId>org.springframework.boot</groupId>
    4. <artifactId>spring-boot-starter-thymeleaf</artifactId>
    5. </dependency>

    (3)在resources目录下创建一个static文件夹,在static文件夹创建一个index.html

    (4)application.properties添加如下配置

    1. spring.thymeleaf.prefix=classpath:/static/
    2. spring.thymeleaf.suffix=.html
    3. spring.thymeleaf.mode=HTML

    (5)写一个IndexController.java

    1. package com.summo.file.controller;
    2. import org.springframework.stereotype.Controller;
    3. import org.springframework.web.bind.annotation.GetMapping;
    4. @Controller
    5. public class IndexController {
    6. @GetMapping("/")
    7. public String index() {
    8. return "index";
    9. }
    10. }

    (6)访问一下index.html

    这个还是比较简单的,我已经成功了,大家成功了吗?如果发现返回的不是HTML而是字符串,检查一下IndexController的注解,是@Controller而不是@RestController,方法上也不要加 @ResponseBody。

    2. 判断当前的请求来自于电脑还是手机

    (1)判断逻辑分析

    这个听起来很难,其实很简单,前端在访问后端接口的时候,会携带一个USER-AGENT的请求头,通过这个USER-AGENT请求头就可以区分访问来源,判断逻辑代码如下:

    1. /**
    2. * 校验是否手机端
    3. *
    4. * @param request
    5. * @return
    6. */
    7. public static boolean isFromMobile(HttpServletRequest request) {
    8. //1. 获得请求UA
    9. String userAgent = request.getHeader("USER-AGENT").toLowerCase();
    10. //2.声明手机和平板的UA的正则表达式
    11. // \b 是单词边界(连着的两个(字母字符 与 非字母字符) 之间的逻辑上的间隔),
    12. // 字符串在编译时会被转码一次,所以是 "\\b"
    13. // \B 是单词内部逻辑间隔(连着的两个字母字符之间的逻辑上的间隔)
    14. String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i" + "|windows (phone|ce)|blackberry"
    15. + "|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp" + "|laystation portable)|nokia|fennec|htc[-_]"
    16. + "|mobile|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
    17. String tableReg = "\\b(ipad|tablet|(Nexus 7)|up.browser" + "|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
    18. // 3.移动设备正则匹配:手机端、平板
    19. Pattern phonePat = Pattern.compile(phoneReg, Pattern.CASE_INSENSITIVE);
    20. Pattern tablePat = Pattern.compile(tableReg, Pattern.CASE_INSENSITIVE);
    21. if (null == userAgent) {
    22. userAgent = "";
    23. }
    24. // 4.匹配
    25. Matcher matcherPhone = phonePat.matcher(userAgent);
    26. Matcher matcherTable = tablePat.matcher(userAgent);
    27. if (matcherPhone.find() || matcherTable.find()) {
    28. //来自手机或者平板
    29. return true;
    30. } else {
    31. //来自PC
    32. return false;
    33. }
    34. }

    2)新建两个文件夹,将手机端和电脑端的index界面区分开来

    (3)IndexController代码改一下

    1. import java.util.regex.Matcher;
    2. import java.util.regex.Pattern;
    3. import javax.servlet.http.HttpServletRequest;
    4. import org.springframework.stereotype.Controller;
    5. import org.springframework.web.bind.annotation.GetMapping;
    6. @Controller
    7. public class IndexController {
    8. @GetMapping("/")
    9. public String index(HttpServletRequest request) {
    10. if (isFromMobile(request)) {
    11. return "mp/index";
    12. } else {
    13. return "web/index";
    14. }
    15. }
    16. /**
    17. * 校验是否手机端
    18. *
    19. * @param request
    20. * @return
    21. */
    22. public static boolean isFromMobile(HttpServletRequest request) {
    23. //1. 获得请求UA
    24. String userAgent = request.getHeader("USER-AGENT").toLowerCase();
    25. //2.声明手机和平板的UA的正则表达式
    26. // \b 是单词边界(连着的两个(字母字符 与 非字母字符) 之间的逻辑上的间隔),
    27. // 字符串在编译时会被转码一次,所以是 "\\b"
    28. // \B 是单词内部逻辑间隔(连着的两个字母字符之间的逻辑上的间隔)
    29. String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i" + "|windows (phone|ce)|blackberry"
    30. + "|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp" + "|laystation portable)|nokia|fennec|htc[-_]"
    31. + "|mobile|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
    32. String tableReg = "\\b(ipad|tablet|(Nexus 7)|up.browser" + "|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
    33. // 3.移动设备正则匹配:手机端、平板
    34. Pattern phonePat = Pattern.compile(phoneReg, Pattern.CASE_INSENSITIVE);
    35. Pattern tablePat = Pattern.compile(tableReg, Pattern.CASE_INSENSITIVE);
    36. if (null == userAgent) {
    37. userAgent = "";
    38. }
    39. // 4.匹配
    40. Matcher matcherPhone = phonePat.matcher(userAgent);
    41. Matcher matcherTable = tablePat.matcher(userAgent);
    42. if (matcherPhone.find() || matcherTable.find()) {
    43. //来自手机或者平板
    44. return true;
    45. } else {
    46. //来自PC
    47. return false;
    48. }
    49. }
    50. }

    电脑端访问

    手机端访问

    到这里,一个接口区分电脑端和手机端的功能实现了,由于index.html引入了一些js、css、ttf、woff 等静态资源,这些文件如何访问呢?继续看。

    3. 其他类型的静态资源如何访问

    mp目录下文件结构如下

    index.html想要引入js和css目录下的文件,路径应该这样写

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset=utf-8>
    5. <meta name=viewport content="width=device-width,initial-scale=1">
    6. <title>summo-sbmy-front-mp</title>
    7. <link href=/mp/css/app.css rel=stylesheet>
    8. </head>
    9. <body>
    10. <div id=app></div>
    11. <script type=text/javascript src=/mp/js/manifest.js></script>
    12. <script type=text/javascript src=/mp/js/vendor.js></script>
    13. <script type=text/javascript src=/mp/js/app.js></script>
    14. </body>
    15. </html>

    这样就可以访问到指定目录的资源了

    整体逻辑其实很简单,我觉得最容易出问题的地方在路径的设置,有时候文件和代码都弄好了,但就是加载不出来,基本上就是路径设置错了。所以大家要是自己实现的话,尽量先按照我的文件路径来,先搞成功再说。

    二、扩展知识

    1. 给界面传递动态值

    在Spring MVC中,将变量传递到视图通常通过Model对象或使用ModelAndView对象进行,举个例子:IndexController.java代码如下

    1. package com.summo.file.controller;
    2. // 确保引入相关的包
    3. import org.springframework.ui.Model;
    4. @Controller
    5. public class IndexController {
    6. @GetMapping("/")
    7. public String index(HttpServletRequest request, Model model) {
    8. // 添加属性到model中
    9. model.addAttribute("message", "欢迎访问我们的网站!");
    10. // 设置一个版本号
    11. model.addAttribute("version", "1.0.0");
    12. // 根据客户端类型选择视图
    13. if (isFromMobile(request)) {
    14. return "mp/index"; // 返回移动端页面
    15. } else {
    16. return "web/index"; // 返回桌面端页面
    17. }
    18. }
    19. }

    index.html代码如下

    1. <!DOCTYPE html>
    2. <html xmlns:th="http://www.thymeleaf.org">
    3. <head>
    4. <title>首页</title>
    5. <script type="text/javascript" th:src="'/mp/js/manifest-' + ${version} + '.js'"></script>
    6. </head>
    7. <body>
    8. <h1>Hello World,我是电脑端</h1>
    9. <!-- 在Thymeleaf中使用的表达式 -->
    10. <p th:text="${message}"></p>
    11. </body>
    12. </html>

    访问之后可以看到参数已经替换掉了

    动态传值在实际开发中经常使用到,比如我们一般在配置文件中维护好js、css 的版本号,然后将版本号传给index.html达到动态控制前端版本。

    2. 项目打包静态资源没有打进去

    正常情况下,打完包后静态资源文件会在static文件夹下,但是上次我打包就发现静态资源文件没有打包进去,后来才知道需要在pom.xml文件里面配置一下,具体配置如下:

    1. <build>
    2. <finalName>summo-sbmy</finalName>
    3. <resources>
    4. <resource>
    5. <!-- 指定配置文件所在的resource目录 -->
    6. <directory>src/main/resources</directory>
    7. <includes>
    8. <include>**/*.html</include>
    9. <include>**/*.js</include>
    10. <include>**/*.css</include>
    11. </includes>
    12. <filtering>true</filtering>
    13. </resource>
    14. <resource>
    15. <!-- 指定配置文件所在的resource目录 -->
    16. <directory>src/main/resources</directory>
    17. <includes>
    18. <include>**/*.woff</include>
    19. <include>**/*.ttf</include>
    20. </includes>
    21. <filtering>false</filtering>
    22. </resource>
    23. </resources>
    24. </build>

    这里需要注意的是,.woff和.ttf这类文件比较特殊,需要单独开一块并且设置filtering为false。这个配置说明对这类文件不执行过滤,因为过滤可能破坏文件内容,字体文件应该以其原始形式包含在构建产物中。

    三、总结一下

    访问静态资源的接口大家接触的不多,主要是因为现在前后端分离了,前端自己使用CDN放资源,后端只用维护一个index.html文件,其他的资源都通过CDN访问,已经变得很简单了。但是有时候想要用却不知道从哪里开始,希望这篇文章可以给大家一个大概的思路,还有就是处理静态资源的框架很多,最常见的就是Thymeleaf、Velocity,这两个都可以实现上面的效果,但建议不要混用。

    文章转载自:sum墨 

    原文链接:https://www.cnblogs.com/wlovet/p/18143730

    体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

  • 相关阅读:
    【MATLAB】【函数介绍】cp2tform函数从控制点对推断空间变换
    优化理论06-----非线性共轭梯度法: HS、FR-CG、PR-CG、PR+-CG
    WINDOWS核心编程--Windows程序内部运行机制
    Flink分区之Flink分区策略整理
    C#WPFPrism框架模块化应用实例
    [python] 使用 Selenium 和 chromedirver 抓取网页
    SpringBoot线上服务假死解决,CPU内存正常
    如何在网页中实现动画效果
    正则表达式
    React 入门:使用脚手架创建应用
  • 原文地址:https://blog.csdn.net/dsgdauigfs/article/details/137956260