彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-JWT和中间件(Middleware)的使用EP07

彩虹,女神,长空,go,语言,进阶,高性能,web,框架,iris,项目,实战,jwt,中间件,middleware,使用,ep07 · 浏览次数 : 567

小编点评

**中间件(Middleware)鉴权** 中间件是提供系统软件和应用软件之间连接、便于软件各部件之间的沟通的软件。在所有需要鉴权的接口前面加一层逻辑,便于批量管理和控制。 **中间件的配置** 1. 创建一个中间件变量 `verifyMiddleware`,返回一个载荷结构体对象。 2. 为所有的后台接口、包括后台模板添加中间件: - 创建一个`adminhandler`对象,使用 `verifyMiddleware` 中的函数进行身份验证。 - 对所有 `/admin/*` 路径的接口添加 `adminhandler`。 **中间件的逻辑** 1. 检查请求的 `Authorization` 头中是否存在 `token`。 2. 如果存在 `token`,验证其有效性。 3. 如果验证成功,返回正常数据。 4. 如果验证失败,返回错误信息。 **示例代码** ```javascript //中间件 const verifyMiddleware = jwt.NewVerifier(jwt.HS256, mytool.SigKey); // 后端接口 app.Party("/admin", function(handler) { handler.Use(verifyMiddleware); // 其他接口逻辑 ... }); ``` **优点** * 降低服务器内存压力。 * 提高代码重用性。 * 简化身份验证逻辑。 **注意** * 在设置中间件之前,请确保 `mytool.SigKey` 已正确设置。 * 中间件只能处理需要身份验证的请求。

正文

前文再续,上一回我们完成了用户的登录逻辑,将之前用户管理模块中添加的用户账号进行账号和密码的校验,过程中使用图形验证码强制进行人机交互,防止账号的密码被暴力破解。本回我们需要为登录成功的用户生成Token,并且通过Iris的中间件(Middleware)进行鉴权操作。

Iris模板复用

在生成Token之前,首先我们需要对项目的模板进行优化改造,目前存在的页面模板有三块,分别是:首页模板(index.html)、登录页模板(signin.html)、后台用户管理页模板(/admin/user.html),虽然页面并不多,但不难发现,有很多重复的代码,比方说,首页模板和登录页模板都有公共的头部导航菜单,没必要每个模板都写一遍相同的代码,再比如,三块模板都会有axios的封装逻辑,也没必要三块模板封装三次,除此之外,以后模板多了,不做复用,就会出现维护困难的问题。

首先提取页面模板的公共部分,比如头部导航,在views目录建立header.html:

<nav class="navbar navbar-inverse navbar-fixed-top">  
    <div class="container">  
      <div class="navbar-header">  
  
          <div class="switch_a nav_swich">  
            
              <div class="react-toggle">  
            <div class="react-toggle-track"><div class="react-toggle-track-check"><img src="data:image/png;base64,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" width="16" height="16" role="presentation" style="pointer-events: none;"></div>  
          <div class="react-toggle-track-x"><img src="data:image/png;base64,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" width="16" height="16" role="presentation" style="pointer-events: none;"></div></div><div class="react-toggle-thumb"></div></div>  
  
            </div>  
  
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">  
        <span class="sr-only">菜单</span>  
        <span class="icon-bar"></span>  
        <span class="icon-bar"></span>  
        <span class="icon-bar"></span>  
        </button>  
      </div>  
      <div id="navbar" class="collapse navbar-collapse">  
        <ul class="nav navbar-nav">  
          <li  class="index_nav index_index"><a href="/" title='刘悦'>Home</a></li>  
          <li class="index_nav index_1"><a href="/l_id_1" title='python编程'>Python</a></li>  
          <li class="index_nav index_2"><a href="/l_id_2" title='前端技术'>Web Design</a></li>  
          <li class="index_nav index_3"><a href="/l_id_3" title='数据库相关技术(mysql,redis)'>Db & SQL</a></li>  
          <li class="index_nav index_4"><a href="/l_id_4" title='Mac & Linux(苹果系统和linux相关技术)'>Mac & Linux</a></li>  
          <li class="index_nav index_5"><a href="/l_id_5" title='Go 和 Ruby 相关实践'>Go & Ruby</a></li>  
          <li class="index_nav index_6"><a href="/l_id_6" title='生活和工作'>Life & Work</a></li>  
          <li class="index_nav index_7"><a href="/resume" title='刘悦简历'>Resume</a></li>  
        </ul>  
  
  
          <div class="react-toggle bigtoggle">  
            <div class="react-toggle-track"><div class="react-toggle-track-check"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAABwNJREFUWAmtV1tsFFUY/s6Z2d22zLYlZakUCRVaQcqlWIiCiS1gTEB9UAO+GR9En3iQGI0xJiSiRB98MjEq8cEQTSBeHhQM0V7whtEGDWC90BYitxahtNtu25058/v/ZzvLbilawJNM5+yZ89+//1LgJhYRNLW1uDfBAvpGiIk2O5auvfFxqIH3ZJ8/u06GN6Z9+wVl5SjcD1IbZa/UPkPyYl2uR4dreoD2bnbYxTlBBRytkHXtAREphP5KuH4lddx9h70yxX05t7yYXwGb6W8nx1jibpl2rFlGBxcG9M18okOrn7Bnk/BAO/4bI0UeEE1zjBp3UmvjOxJXJdaKN/ZiIu4tOZrAb4aTdZAZArKmWeiiJZ6jt5tiagdCS9+6cgO1Ne6Mvhe+ixTIfyDVhipnK9p+P0Edqx9RW/YZtQVGmOLChRxNNlyPsTEgPQKMB3dbEHa0h1awYmQ83enTd2vmUtvKd1Glv2RkzBb+kZGRrKtjzG60Wguhd/lJZBingbcfWWe72vjT75bJDrhYtvA0hrurETDr5HyF2Knb1MM4ab//xIoOqueA0edRnkkinTyJdYvqLFDZO4zUPFCvVoDjJq4T7TE61IWh4x5KqxX5KVKkX8WZ/t2ov2cb3MHt4dhIyOxIJxJOOF6xRx/99BksXLoecWcXytILMNBDqKpnGZWPquYfPxY8iXGR9fK+SgFrgcRPXPjVqhehL+3EmZ5RGJQi1QBU8TPThQnOQzm+5UXGIcetUeEAfP13VwzpI+w1jGJWdSliNfvVhiMPiOsllJag4M/UGHiqM6dlBb2OTLKHHV6KkvogrJ4XhBWniWK/Gp1MQyf93FOeUXKmKk/FzJxbQtKLjFXYT4USupy8fQVir2ynVEBiZMG0qtOHMS/AW4Gwrk7BG3C1F0B5nqNKE0CME4MfVRLPnXkBKe+ipvoFhNQywOhdghvLi0F8ReyVXV4BKTBRbbe5f64zR/DHsdZw1hJfeWlHl/GNRJzDxrd5m192z78TMaVnKELZoINZS4BzQ7vtnZljSnha/pPCbkuxzXcupYwI5tIeCpGc0Yp9tWHZQy/rmYhRfNgg4bHJBYLzGkxsRJF4XKlE2jBOHNSv3kY7Tj6vthzPFl61BrYwqFlmEQhtSVXmLiksxLmtRgYXI1ULU61JJ4eVKmG3/5sCVgpbMT6OMJ2E08/29Xf3w6v4FnHdCjfWgXu/O8Z5mLdCkeRs2khHe1DqOtQwbHWTAnM5S2HNmhALYo5KjkPFrMMKjZl6HxhWIAb0BqE+/73GrBRQUsKYiBu4JX8ycI6wtw+i5ef3NZpsrKVSHYCP37jwGDgeE1SA0S/xtl5SU2fs1ApEp0qTLVRjgyycDSsLHMSwmFltZMStR3uLLg6BdLhDa5dC6ryU2pHBe1BVO9tUcwfitJt2CLJZUHoG6T7Op75u0IyK31TCPcwFqgPk/KCaD3dFOuZBCO7xvCT/j048b3I3c7F2+WuOW7qdgkucFYlcQ4qop3yzTX7WaKfOCccye3Ts1Etq0+a/BHCF1yPgF3tAUkR6OrtGmo6gl94qqcXKh3rDyrOkPa58URoWcov2Mo6M+0QjrqKB+b7++oMa9Sz+ZkM0mie6aAtnGUvhmxaI+TogPOSQedgWioGSHFLn3v4kLh4HRspNmOGv41k+55siLFp2z6xYeJjhljFcbmxJlr4ga06TbevSByz/glQq4BJx46/c+237PbBqEYKxX3HpmKZEnQnr65X20hqJYaNcLoFOLiJk2LuBbyg7Q0OEn+hm0P3honxFD6rdxYorKpeIoi4YSSvyQHQIbM5t4+YNxLj/OxhVOOE4585qGpjnq+wSx6Q9CtNxTjd5klB+g6Mv36r0+b9cZFi44WYkHdG2ZWb3TtOUOXyVAlKlpGvJIAJ3eBMyfYS5C0qRZGtC85j+4sOasDe9xznPYezhhO/2Q6eP2fSOvYHOjtuQ1a9Q1VKynVDaMc8E0tptdxUsTFpFIYjcZKcbnoaQTNdiqCwNlL4G7oziSqGnT1ALf34vhk4R5zU3qYV9ONp9K88RtouShE68JwaU8dFw5W617shWa9ykeaBIn2hcsvPgL00k45QdTCZuSVcTRNs+8fnyLvooQfR5iujAnR9bxfY2xOVOxFS8SK3Le0l48VyYu1M8HRe5JD8wKPTjYnifaK3Wfn/GChYQ8ZAi6WRzWgqLV5YrsVLnZaVSoXU1g9gOIDwFySiGi+Zdrnzr7J3r+SMuszlcQCRn8lNGcTuSy2jOI7o9mxjZo+vR3ej3tN+ifRSOyUTS0+VMOid93cCubeiy/6TImS0QxRSCq2vxKr45zV+FQnjWH6D2xg+E9EatLcLAdHTgtGGD80D6jM0+aOl4wJgO/f96R2aJKCQ3yvgftRhdFMOpd6oAAAAASUVORK5CYII=" width="16" height="16" role="presentation" style="pointer-events: none;"></div>  
          <div class="react-toggle-track-x"><img src="data:image/png;base64,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" width="16" height="16" role="presentation" style="pointer-events: none;"></div></div><div class="react-toggle-thumb"></div></div>  
  
        <div class="search navbar-right" >  
          <form action="/Index_search" method ="GET" class="search_form" >  
            <input type="search" name="text" class="search_input" placeholder="Search" required="required" >  
          </form>  
        </div>  
  
  
      </div>  
      
    </div>  
  </nav>

随后,在需要头部导航的模板进行引入操作,比如修改signin.html:

${ render "header.html" }

注意,使用${}是为了避免和前端的Vue.js标签冲突。

同样地,将封装axios.js逻辑单独抽取出来myaxios.html:

<script>  
  
const myaxios = function (url, type, data = {}) {  
  
return new  
  
    Promise((resolve) => {  
  
        if (type === "get" || type === "delete") {  
  
  
            axios({  
  
                method: type,  
                url: url,  
                params: data  
            }).then((result) => {  
  
                resolve(result.data);  
  
            });  
  
  
        } else {  
  
            const params = new URLSearchParams();  
            for (var key in data) {  
            params.append(key,data[key]);  
            }  
            axios({  
  
                method: type,  
                url: url,  
                data:params  
            }).then((result) => {  
  
                resolve(result.data);  
  
            });  
  
        }  
  
    });  
  
}  
  
</script>

然后在需要的地方进行引入操作:

${ render "myaxios.html" }

如此,我们只需要维护模板的公共部分即可。

修改后,项目的结构如下:

.  
├── README.md  
├── assets  
│ ├── css  
│ │ └── style.css  
│ └── js  
│     ├── axios.js  
│     └── vue.js  
├── database  
│ └── database.go  
├── favicon.ico  
├── go.mod  
├── go.sum  
├── handler  
│ ├── admin.go  
│ └── user.go  
├── main.go  
├── model  
│ └── model.go  
├── mytool  
│ └── mytool.go  
├── tmp  
│ └── runner-build  
└── views  
    ├── admin  
    │ └── user.html  
    ├── admin_header.html  
    ├── header.html  
    ├── index.html  
    ├── myaxios.html  
    ├── signin.html  
    └── test.html

JWT生成逻辑

JSON Web Token (JWT)是一个互联网应用的开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息,这种信息可以被验证和信任,因为它是数字签名的。

说白了,登录成功以后,生成一个 JSON 对象,返回给前端,就像下面这样:

{  
"uid":1  
}

这之后,用户与服务端通信的时候,所有请求都要带着这个JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止JSON对象被篡改,服务器在生成这个对象的时候,会加上签名,变成这种模样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVaWQiOjEsImlhdCI6MTY2MTg0MjYxMCwiZXhwIjoxNjYxODQ1NjEwfQ.BXK9awvVCk7L3JAnDGt9z6U9TOjPCpI0AcHRu1eq_mo

这玩意就是普遍意义上的Token,俗称“令牌”。

在我们的项目中,需要为登录校验通过的账号生成Token,首先安装jwt包:

go get -u github.com/kataras/iris/v12/middleware/jwt

随后修改本地的工具包mytool.jwt:

package mytool  
  
import (  
	"crypto/md5"  
	"fmt"  
	"io"  
	"time"  
  
	"github.com/dchest/captcha"  
	"github.com/kataras/iris/v12"  
	"github.com/kataras/iris/v12/middleware/jwt"  
)  
  
  
var SigKey = []byte("signature_hmac_secret_shared_key")  
  
type PlayLoad struct {  
	Uid uint  
}  
  

func GenerateToken(uid uint) string {  
  
	signer := jwt.NewSigner(jwt.HS256, SigKey, 50*time.Minute)  
	claims := PlayLoad{Uid: uid}  
  
	token, err := signer.Sign(claims)  
	if err != nil {  
		fmt.Println(err)  
  
	}  
  
	s := string(token)  
  
	return s  
  
}


众所周知,Token由三部分组成:头部、载荷以及秘钥。这里SigKey字符为签名秘钥,PlayLoad结构体为载荷信息,这里通过签名生成一个字符格式的token,注意返回前端时,需要强转为字符串。

需要注意的是,生成签名时使用的是HS256算法,同时为了确保安全性,token设置生命周期,这里为50分钟。

随后修改用户登录逻辑,将生成好的token返回给前端:

//登录动作  
func Signin(ctx iris.Context) {  
  
	ret := make(map[string]interface{}, 0)  
  
	cid := ctx.PostValue("cid")  
	code := ctx.PostValue("code")  
  
	if captcha.VerifyString(cid, code) == false {  
  
		ret["errcode"] = 2  
		ret["msg"] = "登录失败,验证码错误"  
		ctx.JSON(ret)  
		return  
  
	}  
  
	db := database.Db()  
	defer func() {  
		_ = db.Close()  
	}()  
  
	Username := ctx.PostValue("username")  
	Password := ctx.PostValue("password")  
  
	user := &model.User{}  
  
	db.Where(&model.User{Username: Username, Password: mytool.Make_password((Password))}).First(&user)  
  
	if user.ID == 0 {  
  
		ret["errcode"] = 1  
		ret["msg"] = "登录失败,账号或者密码错误"  
		ctx.JSON(ret)  
		return  
  
	}  
  
	token := mytool.GenerateToken(user.ID)  
  
	fmt.Println(token)  
  
	ret["errcode"] = 0  
	ret["msg"] = "登录成功"  
	ret["username"] = user.Username  
	ret["token"] = token  
	ctx.JSON(ret)  
  
}

前端接收的返回值为:

{  
    "errcode": 0,  
    "msg": "登录成功",  
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVaWQiOjEsImlhdCI6MTY2MTg0MzI5MSwiZXhwIjoxNjYxODQ2MjkxfQ.547z3nv4qj2-UeHTzfeG_qSsnFZD2DFyCP9gNZ-QiHA",  
    "username": "123"  
}

随后前端收到token后,将其存储localstorage,然后跳转到后台页面:

//登录请求  
                signin:function(){  
  
  
                    this.myaxios("http://localhost:5000/signin/","post",{"username":this.username,"password":this.password,"cid":this.cid,"code":this.code}).then(data => {  
                        console.log(data)  
                        alert(data.msg);  
  
                        localStorage.setItem("token",data.token);  
  
                        window.location.href = "/admin/user/"  
  
                    });  
  
                }

localStorage存储是永久的,如果对安全性要求较高,可以采用sessionStorage,token生命周期就会跟随浏览器进程,但之前设置的token生命周期就没意义了,各有利弊,各自权衡。

中间件(Middleware)鉴权

所谓中间件,是一类提供系统软件和应用软件之间连接、便于软件各部件之间的沟通的软件,应用软件可以借助中间件在不同的技术架构之间共享信息与资源。

说白了,就是在所有需要鉴权的接口前面加一层逻辑,便于批量管理和控制:

verifier := jwt.NewVerifier(jwt.HS256, mytool.SigKey)  
	  
  
	verifyMiddleware := verifier.Verify(func() interface{} {  
  
		return new(mytool.PlayLoad)  
	})

这里声明中间件变量verifyMiddleware,该变量会返回一个载荷结构体对象。

随后,为所有的后台接口、包括后台模板添加中间件:

adminhandler := app.Party("/admin")  
	  
  
	adminhandler.Use(verifyMiddleware)  
  
	adminhandler.Get("/userlist/", handler.Admin_userlist)  
	adminhandler.Delete("/user_action/", handler.Admin_userdel)  
	adminhandler.Put("/user_action/", handler.Admin_userupdate)  
	adminhandler.Post("/user_action/", handler.Admin_useradd)  
	adminhandler.Get("/user/", handler.Admin_user_page)

如此,所有后台操作都需要中间件的鉴权操作。

换句话说,如果请求地址中没有token或者token不合法,就不会返回正常数据。

访问:http://localhost:5000/admin/user 如图所示:

如果带着token:

当然了,之后所有的后台请求都需要携带token,所以改造上面封装的myaxios.html:

<script>  
  
var mytoken = localStorage.getItem("token");  
  
  
const myaxios = function (url, type, data = {}) {  
  
return new  
  
    Promise((resolve) => {  
  
        if (type === "get" || type === "delete") {  
  
  
            axios({  
  
                method: type,  
                url: url+"?token="+mytoken,  
                params: data  
            }).then((result) => {  
  
                resolve(result.data);  
  
            });  
  
  
        } else {  
  
            const params = new URLSearchParams();  
            for (var key in data) {  
            params.append(key,data[key]);  
            }  
            axios({  
  
                method: type,  
                url: url+"?token="+mytoken,  
                data:params  
            }).then((result) => {  
  
                resolve(result.data);  
  
            });  
  
        }  
  
    });  
  
}  
  
</script>

藉此,每个后端请求都会携带token。

结语

JWT形式的认证体系将用户状态分散到了客户端中,相比于服务端的session存储,可以明显减轻服务端的内存压力,此外,使用Iris中间件鉴权的方式有助于提高代码的重用性,也更便于维护,更加优雅。该项目已开源在Github:https://github.com/zcxey2911/IrisBlog ,与君共觞,和君共勉。

与彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-JWT和中间件(Middleware)的使用EP07相似的内容:

彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-登录与图形验证码(captcha)EP06

书接上回,上一回我们按照“低耦合高内聚”的组织架构方针对项目的整体结构进行了优化,本回将会继续编写业务,那就是用户的登录逻辑,将之前用户管理模块中添加的用户账号进行账号和密码的校验,校验通过后留存当前登录用户的信息,过程中使用图形验证码强制进行人机交互,防止账号的密码被暴力破解。 登录逻辑 首先在逻

彩虹女神跃长空,Go语言进阶之Go语言高性能Web框架Iris项目实战-JWT和中间件(Middleware)的使用EP07

前文再续,上一回我们完成了用户的登录逻辑,将之前用户管理模块中添加的用户账号进行账号和密码的校验,过程中使用图形验证码强制进行人机交互,防止账号的密码被暴力破解。本回我们需要为登录成功的用户生成Token,并且通过Iris的中间件(Middleware)进行鉴权操作。 Iris模板复用 在生成Tok

r0tracer 源码分析

使用方法 修改r0tracer.js文件最底部处的代码,开启某一个Hook模式。 function main() { Java.perform(function () { console.Purple("r0tracer begin ... !") //0. 增加精简模式,就是以彩虹色只显示进出函数

[转帖]采用cat与EOF组合添加多行内容时防止变量解析的解决办法

https://blog.51cto.com/xoyabc/1718355 【问题描述】 当采用cat与EOF组合添加多行内容时,若含有变量,则追加后的文件中是变量对应的的值,并不是变量本身。 如$a对应的值为111,执行以下命令后 cat >> /etc/profile << EOF $a $a

推荐一款采用 .NET 编写的 反编译到源码工具 Reko

今天给大家介绍的是一款名叫Reko的开源反编译工具,该工具采用C#开发,广大研究人员可利用Reko来对机器码进行反编译处理。我们知道.NET 7 有了NativeAOT 的支持,采用NativeAOT 编译的.NET程序 无法通过ILSpy 之类的传统工具得到源码,这款Reko 可能是唯一一款可以把

Python ArcPy批量掩膜、重采样大量遥感影像

本文介绍基于Python中ArcPy模块,对大量栅格遥感影像文件进行批量掩膜与批量重采样的操作~

[转帖]Data studio普通用户采用非SSL的方式连接openGauss

https://cdn.modb.pro/db/43087 关闭SSL认证由于openGauss默认开启SSL认证,且配置认证较为麻烦,个人开发测试并不需要它。因此关闭openGauss的远程用户登录SSL认证模式。1.找到postgresql.conf cd /gaussdb/data/openG

[转帖]你怎么看Data studio普通用户采用非SSL的方式连接openGauss?

https://zhuanlan.zhihu.com/p/365144226 关闭SSL认证 由于openGauss默认开启SSL认证,个人开发测试并不需要它。因此关闭openGauss的远程用户登录SSL认证模式。 1.找到postgresql.conf。 cd /gaussdb/data/ope

[转帖]浅谈redis采用不同内存分配器tcmalloc和jemalloc

http://www.kaotop.com/it/173669.html 我们知道Redis并没有自己实现内存池,没有在标准的系统内存分配器上再加上自己的东西。所以系统内存分配器的性能及碎片率会对Redis造成一些性能上的影响。 在Redis的 zmalloc.c 源码中,我们可以看到如下代码: ?

【转帖】50.设置HotSpot采用解释器还是JIT编译器(-Xint、-Xcomp、Xmixed以及-Server、-Client)

目录 1.设置HotSpot 1.设置HotSpot 1.设置采用解释器还是JIT编译器 -Xint: 完全采用解释器模式执行程序。 -Xcomp: 完全采用即时编译器模式执行程序。如果即时编译出现问题,解释器会介入执行。 -Xmixed: 采用解释器和JIT编译器并存的方式共同执行程序。默认模式。