01、概述

在单体的Web架构项目中,如果你使用freemarker和 thymeleaf的话肯定就处理静态资源和路径的问题。静态和路径的处理,在SpringBoot是如何处理的。

对于一个WEB开发项目来是哦,如果不是采用前后端分离的模式。而是将imgs,js和css等一些静态资源打包的jar 包中,那么springboot是如何把它们放入到项目中呢?

02、springboot实现静态资源映射

第一步:在pom.xml中引入web和freemarker

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

第二步:在application.yml文件配置freemarker

server:
  port: 8086

spring:
  freemarker:
    # freemarker页面不需要缓存
    cache: false
    suffix: .html

第三步:在application.yml文件配置静态资源映射路径

映射模板路径

是交由freemarker和thymeleaf做,也就配置templates路径,如下:

spring:
  freemarker:
    # freemarker页面不需要缓存
    cache: false
    suffix: .html
    # 配置freemarker页面存储的路径,
    template-loader-path: classpath:/templates/
  • 放在templates下面的动态页面,是不能直接在浏览器访问,你应该把这个路径当成以前:WEB-INF。放在这里的页面是安全的,只能通过springmvc去跳转。然后让freemarker和thymeleaf渲染以后,然后用Response对象输出给浏览器。浏览器然后解析呈现。
映射资源路径
spring:
  freemarker:
    # freemarker页面不需要缓存
    cache: false
    suffix: .html
    # 配置freemarker页面存储的路径,
    template-loader-path: classpath:/templates/
  web:
    resources:
      # 静态资源路径的配置
      static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/



第四步:定义IndexController.java跳转index.html

package com.kuangstudy.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * Description:
 * Author: yandi Administrator
 * Version: 1.0
 * Create Date Time: 2021/12/11 21:25.
 * Update Date Time:
 *
 * @see
 */
@Controller
public class IndexController {

    @GetMapping("/index")
    public String index() {
        return "index";
    }
}

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>我是首页</title>
    <link rel="stylesheet" href="/css/app.css">
</head>
<body>
<h1>我是首页</h1>
<img src="/imgs/1.png" alt="">
<script src="/js/app.js"></script>
</body>
</html>

第五步:在index.html引入css,img,js查看效果

访问:http://localhost:8086/index

spring boot 资源path Path springboot配置资源路径_html

解答问题1:在开发中我们需要不需要配置这个路径:

spring:
  freemarker:
    # freemarker页面不需要缓存
    cache: false
    suffix: .html
    # 配置freemarker页面存储的路径,
    template-loader-path: classpath:/templates/
  • 不需要,因为默认就是: classpath:/templates/
  • 为什么还要去指定一下:告诉你一个道理。你可以去修改。但是不建议。

解答问题2:为什么在引入的css js 和图片时候不加/static

spring:
  web:
    resources:
      # 静态资源路径的配置
      static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
  • springboot默认的静态资源处理。内部自动增加/static,上面classpath:/static/ 也就说你页面上编写,底层自动增加上去,如果你在引入过程还增加,路径变成:classpath:/static/static/css/app.css 就是错误的。
  • 为什么在引入的时候,每个css img 和 js前面增加 / 。原因:springboot做了处理自动资源路径推到静态配置路径 。这样就不会受到相对路径的问题。
  • 如果未来页面中访问的静态资源是404,不是加static,而是去查看target目录下的static目录有生成,里面有没有你想要的静态文件。如果没有有还不能访问。那就说明你文件名写错了、或者没有增加/。

03、相对路径问题?

访问页面的时候,页面中的css , js 和图片,如果你不是使用绝对路径,那么默认情况:浏览器内部的静态资源都是根据访问路径来生成和访问:规则如下:

比如:访问路径分别是:

http://localhost:8086/index ----- css/app.css----http://localhost:8086/css/app.css

http://localhost:8086/a/b ----- css/app.css-----http://localhost:8086/a/css/app.css

http://localhost:8086/a/b/c ----- css/app.css----http://localhost:8086/a/b/css/app.css

解决方案1 :

给每个静态资源增加 / 即可。springboot做了默认处理

解决方案2:

绝对路径

04、绝对路径

http://开头定义的css .js 和图片,就直接去下载和渲染比如:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>我是首页</title>
    <link rel="stylesheet" href="http://localhost:8086/css/app.css">
</head>
<body>
    <h1>我是首页</h1>
    <img src="http://localhost:8086/imgs/1.png" alt="">
    <script src="http://localhost:8086/js/app.js"></script>
</body>
</html>

这种路径不会收到你访问路径的影响。很多企业其实也会采用绝对路径。

  • 上面会存在一个问题,绝对路径是写死的,在开发环境是没问题
  • 如果团队开发是多人,每个用户端口是不一样,可能造成冲突
  • 但是在生产环境,就出现问题映射不上

结论:

http://localhost:8086 这部分肯定不能写死,一定动态的。

05、拦截器做统一路由处理

定义拦截器

package com.kuangstudy.intercetor.path;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Description:
 * Author: yandi Administrator
 * Version: 1.0
 * Create Date Time: 2021/12/16 23:30.
 * Update Date Time:
 *
 * @see
 */
public class RootPathInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.setAttribute("ctx", getRootPath(request));
        return true;
    }

    private String getRootPath(HttpServletRequest request) {
        //复习一下request 的常用方法:
		//request.getSchema()可以返回当前页面使用的协议,http 或是 https;
		//request.getServerName()可以返回当前页面所在的服务器的名字;
		//request.getServerPort()可以返回当前页面所在的服务器使用的端口,就是80;
		//request.getContextPath()可以返回当前页面所在的应用的名字;
        String scheme = request.getScheme();
        String serverName = request.getServerName();
        int port = request.getServerPort();
        String path = request.getContextPath();
        String homeUrl = null;
        if (port == 80 || port == 443) {
            homeUrl = scheme + "://" + serverName + path;
        } else {
            homeUrl = scheme + "://" + serverName + ":" + port + path;
        }
        return homeUrl;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

注册拦截器

package com.kuangstudy.config;

import com.kuangstudy.intercetor.path.RootPathInterceptor;
import org.springframework.boot.SpringBootConfiguration;
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.WebMvcConfigurer;

/**
 * Description:
 * Author: yandi Administrator
 * Version: 1.0
 * Create Date Time: 2021/12/16 23:33.
 * Update Date Time:
 *
 * @see
 */
@SpringBootConfiguration
public class WebmvcConfiguration implements WebMvcConfigurer {

    @Bean
    public RootPathInterceptor getRootPathInterceptor() {
        return new RootPathInterceptor();
    }

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

页面使用

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>我是首页</title>
    <link rel="stylesheet" href="${ctx}/css/app.css">
</head>
<body>
<h1>我是首页</h1>
<img src="${ctx}/imgs/1.png" alt="">
<script src="${ctx}/js/app.js"></script>
</body>
</html>