go读取静态文件.html、css、js404问题

  • 简单项目的静态资源404问题
  • vue-element-template打包生成的静态资源404问题

本篇博客分两种情况来解决golang项目访问静态资源404问题,第一种是自己将静态页面手动创建或者复制到golang项目中。第二种情况是采用第三方框架vue-elementui-template打包生成的文件静态资源404问题

简单项目的静态资源404问题

问题

运行golang项目后,打开index.html页面后各种js、css加载404问题。不多比比,直接上代码。

test1.go

package mainimport ("fmt""html""html/template""log""net/http""time"
)func IndexHandler(w http.ResponseWriter, r *http.Request) {t, err := template.ParseFiles("index.html")if err != nil {log.Println(err)}err = t.Execute(w, nil)if err != nil {log.Println(err)}
}var count int = 1func Task(w http.ResponseWriter, r *http.Request) {fmt.Printf(" ------ here is Task[%d] ------- \n", count)defer r.Body.Close()// 模拟延时time.Sleep(time.Second * 2)fmt.Fprintf(w, "Response.No.%d: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))count++answer := `{"status:":"OK"}`w.Write([]byte(answer))
}func Task1(w http.ResponseWriter, r *http.Request) {fmt.Printf(" ------ here is Task1[%d] ------- \n", count)defer r.Body.Close()// 模拟延时time.Sleep(time.Second * 2)fmt.Fprintf(w, "Response.No[%d]: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))count++answer := `{"status:":"OK"}`w.Write([]byte(answer))
}func main() {// 调用后台接口http.HandleFunc("/hello/world", Task)http.HandleFunc("/hello/world1", Task1)// 启动静态文件服务http.Handle("/template/", http.StripPrefix("/template/", http.FileServer(http.Dir("template")))) http.Handle("/libs/", http.StripPrefix("/libs/", http.FileServer(http.Dir("libs"))))http.HandleFunc("/index", IndexHandler)fmt.Println("服务端口:8000") //控制台输出信息err := http.ListenAndServe(":8000", nil) //设置监听的端口if err != nil {log.Fatal("ListenAndServe: ", err)}
}

解释1:go语言中的http.HandleFunc("/index", IndexHandler)相当于,前端访问接口index,后端去调用方法IndexHandler。
相当于java的

@RequestMapping("/index")
public void IndexHandler() {// 在此,怀念我那逝去的java
}

等价于go中的

http.HandleFunc("/index", IndexHandler)

项目结构

index.html代码

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><!-- import CSS --><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><link rel="stylesheet" href="template/css/test.css">
</head>
<body><div id="app"><span class="mybtn">也无风雨、也无晴</span><el-button @click="httpGet1">get请求</el-button><el-button @click="openPage">Button</el-button><el-dialog :visible.sync="visible" title="Hello world"><p>Try Element</p></el-dialog></div>
</body><!-- import Vue before Element --><script src="https://unpkg.com/vue/dist/vue.js"></script><!--script src="./libs/axios-0.16.2.min.js"></script,不知道这个为啥不行,可以把下面这个直接下载下来,打包到项目里--><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="./libs/vue/vue-2.2.2.min.js"></script><script src="./libs/jquery/jquery.min.js"></script><!-- import JavaScript --><script src="https://unpkg.com/element-ui/lib/index.js"></script><script>new Vue({el: '#app',data: function() {return { visible: false }},methods:{openPage:function(){alert("sdfsdfs")window.open("./template/user/user.html")},httpGet1:function(){axios({method:'get',// 对链接前缀进行封装,后台使用的时候直接引用前缀即可url:'http://localhost:8000/hello/world'}).then(function(resp){console.log(resp.data);}).catch(resp => {console.log('请求失败:'+resp.status+','+resp.statusText);});}}})</script>
</html>

运行

go run test1.go

其中蓝色字体是为了验证不同文件夹下的css的引用

点击下载项目完整代码

vue-element-template打包生成的静态资源404问题

上面的项目是自己手动创建的静态页面和js,html页面里对于js、css的引用都是人为可控的。但是如果是使用的第三方框架,如vue-elemen-template,因为浏览器是不认识.vue文件的,那么开发完成后是将vue等打包成浏览器能解析的js、css、html等文件。打包生成的.html里对于js等的引用路径是可以修改的,但是太过于麻烦,有兴趣的道友可以自行百度,我这里就按它默认生成的资源,然后在go代码里去解决404问题。

工欲善其事,必先利其器。既然是404那么就是静态资源没有加载到,我们就需要了解go是怎么加载静态资源的。那就是函数http.StripPrefix与http.FileServer

我们来看看这行代码

http.Handle("/template/", http.StripPrefix("/template/", http.FileServer(http.Dir("template"))))

以上http.Handle("/template/",就是相当于一个请求,当前端发起http:www.xxx.com:9527/template时,会进入该方法。即
相当于java的

@RequestMapping("/index")
public void IndexHandler() {// 在此,怀念我那逝去的java
}

等价于go中的

http.HandleFunc("/index", IndexHandler)

然后我们看http.StripPrefix方法,它就是拦截请求中含有/template/前缀的资源请求,然后将该前缀替换成http.Dir(“template”)中的template。

http.Dir表示文件的起始路径,空即为当前路径。调用Open方法时,传入的参数需要在前面拼接上该起始路径得到实际文件路径。

http.FileServer的返回值类型是http.Handler,所以需要使用Handle方法注册处理器。http.FileServer将收到的请求路径传给http.Dir的Open方法打开对应的文件或目录进行处理。 在上面的程序中,如果请求路径为/static/hello.html,那么拼接http.Dir的起始路径.,最终会读取路径为./static/hello.html的文件。

有时候,我们想要处理器的注册路径和http.Dir的起始路径不相同。有些工具在打包时会将静态文件输出到public目录中。 这时需要使用http.StripPrefix方法,该方法会将请求路径中特定的前缀去掉,然后再进行处理:如下代码

package mainimport ("log""net/http"
)func main() {mux := http.NewServeMux()mux.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir("./public"))))server := &http.Server {Addr: ":8080",Handler: mux,}if err := server.ListenAndServe(); err != nil {log.Fatal(err)}
}

这时,请求localhost:8080/static/hello.html将会返回./public/hello.html文件。 路径/static/index.html经过处理器http.StripPrefix去掉了前缀/static得到/index.html,然后又加上了http.Dir的起始目录./public得到文件最终路径./public/hello.html。
如果你就想请求static下的文件,那么就将http.Dir中写static即可。
简单点理解就是将含有static的请求拦截,并将http.Dir中的路径替换掉http.StripPrefix中的路径,拼接成新的文件路径然后相应给前端。

好了,大致原理我们明白了。那么实际操作一下,看我的代码。
目录结构

dist文件夹结构

index.html页面的代码

,我们可以看到它打包生成后对静态文件的应用全部都是以static开头的,那么在浏览器加载静态资源的时候,请求的路径就是

GET http://127.0.0.1:8090/static/js/app.js


这样的请求路径显然是请求不到数据的,那么我们只需要将http://127.0.0.1:8090/static/js/app.js的请求路径修改为
http://127.0.0.1:8090/src/views/vue-element-template/dist/static/js/app.js即可。也就是我们上面分析的将static的请求拦截并且替换路径即可,
我们的项目文件路径是/src/views/vue-element-template/dist/static/
就一行代码,

// 启动静态文件服务
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./src/views/vue-element-template/dist/static/"))))

vscode里切换到main.go所在的路径,运行

go run main.go

再次打开浏览器,问题解决


此处贴出部分代码
main.go

package mainimport ("fmt""engine_stability_platform/src/app/httpServer"
)func main() {fmt.Println("main.....")httpServer.Start()
}

httpServer.go

package httpServerimport ("fmt". "fmt""html""html/template""net/http"
)func IndexHandler(w http.ResponseWriter, r *http.Request) {t, err := template.ParseFiles("src/views/vue-element-template/dist/index.html")if err != nil {fmt.Println(err)}err = t.Execute(w, nil)if err != nil {fmt.Println(err)}
}
var count int = 1
// 测试demo
func Task(w http.ResponseWriter, r *http.Request) {Printf(" ------ here is Task[%d] ------- \n", count)Fprintf(w, "Response.No.%d: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))count++answer := `{"status:":"OK"}`w.Write([]byte(answer))
}func Task1(w http.ResponseWriter, r *http.Request) {Printf(" ------ here is Task1[%d] ------- \n", count)Fprintf(w, "Response.No[%d]: Your request is %q\n\n", count, html.EscapeString(r.URL.Path))count++answer := `{"status:":"OK"}`w.Write([]byte(answer))
}
var server *http.Serverfunc Start() {Println("===== This is http server =====")mux := http.NewServeMux()mux.HandleFunc("/hello/world", Task)mux.HandleFunc("/hello/world1", Task1)// 启动静态文件服务mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./src/views/vue-element-template/dist/static/"))))mux.HandleFunc("/index", IndexHandler)if server != nil {// 避免重复start server 端口泄露server.Close()}// 设置服务器server := &http.Server{Addr: "127.0.0.1:8090",Handler: mux,}// 设置服务器监听端口server.ListenAndServe()
}

index.html

<!DOCTYPE html>
<html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"><link rel="icon" href="favicon.ico"><title>Vue Admin Template</title><link href="static/js/app.js" rel="preload" as="script"><link href="static/js/chunk-elementUI.js" rel="preload" as="script"><link href="static/js/chunk-libs.js" rel="preload" as="script"><link href="static/js/runtime.js" rel="preload" as="script"></head><body><noscript><strong>We're sorry but Vue Admin Template doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><!-- built files will be auto injected --><script type="text/javascript" src="static/js/runtime.js"></script><script type="text/javascript" src="static/js/chunk-elementUI.js"></script><script type="text/javascript" src="static/js/chunk-libs.js"></script><script type="text/javascript" src="static/js/app.js"></script></body>
</html>

补充:vue-element-template生成的资源文件夹也可以在vue.config.js里进行更改

点击下载项目完整代码

参考文章:https://blog.csdn.net/whatday/article/details/109747385?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242.1

go读取静态文件.html、css、js404问题相关推荐

  1. 将 laravel 项目内静态文件,css、js、images 部署到七牛云 CDN

    项目升级,打算把 public 目录下的 css.js.image等文件,上传到七牛云,一直想搞来着,今天又想起来,正好 laravel 也从 5.2 升级到了 5.7,接下来把这边一搞,项目就更加优 ...

  2. django1.4.5配置静态文件(img,css,js)访问

    在settings.py加入 import osWEB_ROOT = os.path.dirname(os.path.abspath(__file__)).replace('\\','/').deco ...

  3. .NET Core开发实战(第23课:静态文件中间件:前后端分离开发合并部署骚操作)--学习笔记(下)...

    23 | 静态文件中间件:前后端分离开发合并部署骚操作 这里还有一个比较特殊的用法 一般情况下,我们前后端分离的架构,前端会编译成一个 index.html 文件和若干个 CSS 文件和 JavaSc ...

  4. 百度智能云实战——静态文件CDN加速

    前言 互联网进入移动互联网时代后,产品形态有几次大的演进.最初,H5站点如雨后春笋般的出现,大量H5站点迅速占领PC市场,中期,为了追求极致用户体验,大量原生Android.IOS应用出现,为用户提供 ...

  5. 各种 django 静态文件的配置总结【待续】

    2019独角兽企业重金招聘Python工程师标准>>> 最近在学习django框架的使用,想引用静态css文件,怎么都引用不到,从网搜了好多,大多因为版本问题, 和我现在的使用的da ...

  6. Django静态文件配置

    本文目的 最近用django开发项目,发现django的静态文件(js,css和img等)配置比较麻烦,开发环境和生产环境的配置还不一样,这里记录一下,作为备忘.我当前使用的版本是django v1. ...

  7. django 1.8 官方文档翻译: 6-6-4 部署静态文件

    部署静态文件 另见 django.contrib.staticfiles 的用法简介,请参见管理静态文件(CSS.images). 在线上环境部署静态文件 放置静态文件到线上环境的基本步骤很简单:当静 ...

  8. 安卓文件操作全解:内部文件、公共文件、私有文件、app静态文件

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓文件操作全解:内部文件.公共文件.私有文件.app静态文件. 读内部文件(当前应用程序文件夹下文件) public static String o ...

  9. 2Flask模板2控制代码块3静态文件4模板的继承

    -回顾 Flask是基于python并且依赖jinja2模板引擎的框架. 注册路由:客户端与Flask程序交互 用户在浏览器输入请求地址->request Flask程序接收请求,分析请求地址 ...

最新文章

  1. [译] 在 Facebook 发一张登机牌,你就有可能被盗号了
  2. j90度度复数运算_看得懂的复数
  3. pythondjango项目集成_[Python]将Wagtail整合到Django2项目中
  4. 《C++语言基础》程序阅读——和对象找感觉
  5. jersey2.22.2异常java.lang.NoSuchMethodError: org.glassfish.jersey.CommonProperties.getValue
  6. win10下cuda、cudnn、c++的cuda环境(build tool of Visual Studio 2019)、anaconda的pytorch-gpu环境、gcc编译环境
  7. 【转载】程序员这口饭-职业规划解决方案
  8. 3、TPshop之邮箱注册配置教程以及常见错误集合
  9. Intel FPGA的JESD204B例程的搭建
  10. 推荐一款安卓手机一键Root工具
  11. vba筛选出满足条件的数据_VBA专题02:使用代码进行复制操作
  12. 三千书源——愿成为整理最全的书源合集
  13. 服务器显示idc,知道一个IP,怎么查询这个服务器是哪家IDC提供的?
  14. 【阿里云】二级域名创建
  15. 判断一个多边形是凸多边形还是凹多边形
  16. 华为鸿蒙系统建立生态链的环境,华为自研操作系统,怎么构建生态?感觉太难了?...
  17. 鸿蒙如何用JS开发智能手表App
  18. Unity3D之Navigation导航系统学习及案例讲解(适合初学者)
  19. Unity3D 设置帧频及显示FPS
  20. excel 用公式查找单元格

热门文章

  1. C++中的取余(rem)与取模(mod), 与实现fix函数
  2. python sched_Python用sched执行周期性任务
  3. Sql Server查看所有数据库名,表名,字段名(SQL语句)
  4. 全球及中国小丑鱼行业研究及十四五规划分析报告
  5. bluebird promise化之循环方法
  6. 关于金币充值的那件事儿
  7. 视频质量评价 Zoom-VQA Patches, Frames and Clips Integration for Video Quality Assessment
  8. 家电“电磁辐射”:不可不防的危害
  9. 德赛西威上海车展重磅发布Smart Solution 2.0,有哪些革新点?
  10. C# mschart 做了一个简单的股票K线