go读取静态文件.html、css、js404问题
go读取静态文件.html、css、js404问题简单项目的静态资源404问题vue-element-template打包生成的静态资源404问题本篇博客分两种情况来解决golang项目访问静态资源404问题,第一种是自己将静态页面手动创建或者复制到golang项目中。第二种情况是采用第三方框架vue-elementui-template打包生成的文件静态资源404问题简单项目的静态资源404问题
go读取静态文件.html、css、js404问题
本篇博客分两种情况来解决golang项目访问静态资源404问题,第一种是自己将静态页面手动创建或者复制到golang项目中。第二种情况是采用第三方框架vue-elementui-template打包生成的文件静态资源404问题
简单项目的静态资源404问题
问题
运行golang项目后,打开index.html页面后各种js、css加载404问题。不多比比,直接上代码。
test1.go
package main
import (
"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 = 1
func 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 main
import (
"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 main
import (
"fmt"
"engine_stability_platform/src/app/httpServer"
)
func main() {
fmt.Println("main.....")
httpServer.Start()
}
httpServer.go
package httpServer
import (
"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.Server
func 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
更多推荐
所有评论(0)