drf-jwt配置文件 jwt签发认证源码分析 自定义用户签发认证 simpleui后台管理美化 权限控制 (acl、rbac)
昨日回顾
# 1 接口文档的编写
-1 word,md 编写----》存放位置:存放共享文件平台,git上
-2 第三方的接口文档编写平台
-3 公司自己开发,使用开源搭建 yapi
-4 自动生成接口文档
-djagno+drf:swagger,coreapi
-FastAPI:自带自动生成接口文档
-接口文档应该有的东西
-接口描述
-请求地址
-请求方式
-请求编码格式
-请求参数(get请求参数,post,put请求参数)
-参数类型
-参数是否必填
-参数解释
-返回数据
-json格式示例
-重点参数解释
-错误码:写到全局
# 2 cookie,session,token发展历史
-会话保持
-cookie:存在于客户端浏览器的键值对
-session:存才于服务端的键值对(文件,内存,数据库。。。)
-token:三部分:头,荷载,签名
-签发:登录
-认证:登录后才能访问的接口
-认证类
-中间件
-装饰器
-别的位置
# 3 jwt:json web token :前后端认证的机制,token的web形式认证机制
# 4 base64
-jwt
-前后端交互:字符串---》base64编码
-图片:使用base64编码
# 5 django+drf如何使用jwt
-drf-jwt
# 6 快速签发
-配置一条路由----》帮咱们写了登录接口
# 7 定制返回格式
-写一个函数,返回什么,前端就看到什么
-配置文件中配置
# 8 jwt 的认证
-局部:视图类上
-认证类 ---》JSONWebTokenAuthentication
-权限类:drf IsAuthenticated
-全局
-携带token
-请求头中
Authorization:jwt sadsfasdfasdf.asdfas'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)df.asdfasdf
# jwt 配置问题
-记住的
-JWT_RESPONSE_PAYLOAD_HANDLER
-'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
-了解的
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_SECRET_KEY': settings.SECRET_KEY,
接口文档

自动生成接口文档
关于框架学习顺序:
Django ---> Flask ---> FastAPI框架(使用多)
- django+drf:coreapi --基于--> swagger
- FastAPI:异步框架,自带自动生成接口文档。
FastAPI自动生成的接口文档示例:

接口文档必备的内容

cookie-session-token发展史
最开始的web只用于浏览文档、浏览新闻
交互式的web兴起 ---> 需要保存用户登录状态 ---> 和用户交互
会话保持 ---> 服务端分的清楚来到服务端的请求是谁
由于服务具有以下特性:无状态 、 无连接
导致服务器,记不住来的请求是谁,所以出现了cookie+session技术。

session占用服务器空间,开销比较大,吃不消 ---> 出现token技术
token原理
token串的三部分,用.分开:
- 头
- 荷载 最重要 但是不要放用户密码 有时候放签发时间
- 签名 头和载荷 ---> 通过(加密算法+密钥)运算 ---> 签名
签发阶段
认证阶段:登录之后才能访问的接口 ·
--认证类
--中间件
--装饰器
--别的位置
base64

base64长度一定是4的倍数。不足4的倍数的时候,需要使用=补齐。
快速签发
通过jwt自动生成的路由
定制返回格式
进行配置:

drf-jwt默认配置:

可见密钥使用的是django settings密钥。
在django settings配置jwt密钥:

jwt的认证
需要配合drf权限类一起使用。
认证类 ---> jwt ---> JSONWebTokenAuthentication
权限类 ---> drf ---> IsAuthenticated
前端发送请求token需要放在请求头,还需要使用固定的格式:

三大认证:

drf-jwt配置文件
需要关注的地方:
前缀:默认是jwt
对应前端请求头 token字符串前面的前缀。

过期时间:默认5分钟token过期

drf-jwt源码执行流程
前期准备
配置login路由:

auth表创建超级用户:

auth表:

auth表密文生成原理
#1 django 的auth user表,密码是加密的,即便的同样的密码,密文都不一样
-每次加密,都随机生成一个盐,把盐拼在加密后的串中
# 比如
pbkdf2_sha256$260000$B9ZRmPFpWb3H4kdDDmgYA9$CM3Q/ZfYyXzxwvjZ+HOcdovaJS7681kDsW77hr5fo5o=
明文:lqz12345
盐:B9ZRmPFpWb3H4kdDDmgYA9
后期来了明文lqz12345
#2 自定义用户表,生成密码用密文
from django.contrib.auth.hashers import make_password
#3 用户表的密码忘了怎么办
-新增一个用户,把它的密码复制过去
# 4 双token认证
auth表的密码如何生成?
同样的密码在auth表存放的密文都不一样。(高级)
再使用同样密码创建一个用户:密文不一样

如何实现? ---> 动态加盐

每次加密都生成一个随机盐。(比如uuid,生成随机字符串)

后端密码校验的时候怎么校验:
根据用户名 取出随机盐 运算出真正的密码?
再和数据库中密文进行比对。
随机盐 + 用户密码明文 --md5加密--> 用户密文
auth表存放的密文 = 固定前缀 + 随机盐 + 用户密文
make_password函数生成密文
make_password源码:
def make_password(password, salt=None, hasher='default'):
"""
Turn a plain-text password into a hash for database storage
Same as encode() but generate a new random salt. If password is None then
return a concatenation of UNUSABLE_PASSWORD_PREFIX and a random string,
which disallows logins. Additional random string reduces chances of gaining
access to staff or superuser accounts. See ticket #20079 for more info.
"""
if password is None:
return UNUSABLE_PASSWORD_PREFIX + get_random_string(UNUSABLE_PASSWORD_SUFFIX_LENGTH)
if not isinstance(password, (bytes, str)):
raise TypeError(
'Password must be a string or bytes, got %s.'
% type(password).__qualname__
)
hasher = get_hasher(hasher)
salt = salt or hasher.salt()
return hasher.encode(password, salt)

这里传入给make_password()方法的是明文的密码。通过该方法生成密文的password,保存到user对象中,然后再调用user.save,存到数据库。
通过django的make_password函数生成密文:
django 校验密文的函数在哪?
from django.contrib.auth.hashers import check_password

忘记密码?
创建一个用户 生成一个密码 把密码复制到数据库中 进去用完了之后 再把数据库原来的密码复制回来。
jwt签发源码分析
# 登录接口,路由匹配成功,执行obtain_jwt_token---》post请求---》ObtainJSONWebToken的post方法
path('login/', obtain_jwt_token),
# ObtainJSONWebToken的post方法 继承APIView
def post(self, request, *args, **kwargs):
# 实例化得到序列化类
serializer = self.get_serializer(data=request.data)
# 做校验:字段自己,局部钩子,全局钩子
if serializer.is_valid():
# user:当前登录用户
user = serializer.object.get('user') or request.user
# 签发的token
token = serializer.object.get('token')
# 构造返回格式,咱们可以自定制---》讲过了
response_data = jwt_response_payload_handler(token, user, request)
response = Response(response_data)
if api_settings.JWT_AUTH_COOKIE:
expiration = (datetime.utcnow() +
api_settings.JWT_EXPIRATION_DELTA)
response.set_cookie(api_settings.JWT_AUTH_COOKIE,
token,
expires=expiration,
httponly=True)
#最终返回了咱们定制的返回格式
return response
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# 如何得到user,如何签发的token----》在序列化类的全局钩子中得到的user和签发的token
-JSONWebTokenSerializer---全局钩子---validate
#前端传入,校验过后的数据---》{"username":"lqz","password":"lqz1e2345"}
def validate(self, attrs):
credentials = {
# self.username_field: attrs.get(self.username_field),
'username':attrs.get('username')
'password': attrs.get('password')
}
if all(credentials.values()):
# auth 模块,authenticate 可以传入用户名,密码如果用户存在,就返回用户对象,如果不存就是None
# 正确的用户
user = authenticate(**credentials)
if user:
# 校验用户是否是活跃用户,如果禁用了,不能登录成功
if not user.is_active:
msg = _('User account is disabled.')
raise serializers.ValidationError(msg)
# 荷载----》通过user得到荷载 {id,name,email,exp}
payload = jwt_payload_handler(user)
return {
# jwt_encode_handler通过荷载得到token串
'token': jwt_encode_handler(payload),
'user': user
}
else:
msg = _('Unable to log in with provided credentials.')
raise serializers.ValidationError(msg)
else:
msg = _('Must include "{username_field}" and "password".')
msg = msg.format(username_field=self.username_field)
raise serializers.ValidationError(msg)
### 重点:
1 通过user得到荷载:payload = jwt_payload_handler(user)
2 通过荷载签发token:jwt_encode_handler(payload)
## 了解:
# 翻译函数,只要做了国际化,放的英文,会翻译成该国语言(配置文件配置的)
from django.utils.translation import ugettext as _
msg = _('Unable to log in with provided credentials.')




jwt 配置文件默认JWT_AUTH_COOKIE这个为None:

用于前后端混合使用 ---> 设置为True ---> 将token写入cookies
如何得到user?如何签发token?
在序列化类的全局钩子得到user,签发token。

逻辑写在序列化类中的validata。
前端上传的字典:

查看序列化类中的validata法:
attrs ---> 前端上传的字典:{"username":"小红", "password":"123"}

相当于取出这些数据,将数据存储在credentials字典中:

credentials.values()校验前端是否上传值。然后将前端上传的字典,放入auth模块的authenticate方法
authenticate方法:传入用户名和密码,如果用户存在则返回用户对象

校验用户是否被禁用了:

产生荷载部分:

通过荷载得到token串(签发token):

is_valid执行完之后,token就已经产生:

就可以直接获取。
修改django中文环境,注意注册app:

做了国际化,错误提示会变成中文。

国际化的原理:将源码中的英文翻译成中文

其实是使用了__这个函数进行翻译,没错这个函数起了个别名就是叫__

jwt认证源码分析
# JSONWebTokenAuthentication---->父类BaseJSONWebTokenAuthentication----》authenticate方法
def authenticate(self, request):
# 前端带在请求头中的token 值
jwt_value = self.get_jwt_value(request)
# 如果没有携带token,就不校验了
if jwt_value is None:
return None
try:
# jwt_value就是token
# 通过token,得到荷载,中途会出错
# 出错的原因:
-篡改token
-过期了
-未知错误
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed()
# 如果能顺利解开,没有被异常捕获,说明token是可以信任的
# payload就可以使用,通过payload得到当前登录用户
user = self.authenticate_credentials(payload)
# 返回当前登录用户,token
return (user, jwt_value)
# jwt_value = self.get_jwt_value(request)
def get_jwt_value(self, request):
# 拿到了前端请求头中传入的 jwt dasdfasdfasdfa
# auth=[jwt,asdfasdfasdf]
auth = get_authorization_header(request).split()
# 'jwt'
auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()
if not auth:
# 请求头中如果没带,去cookie中取
if api_settings.JWT_AUTH_COOKIE:
return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
return None
if smart_text(auth[0].lower()) != auth_header_prefix:
return None
if len(auth) == 1:
msg = _('Invalid Authorization header. No credentials provided.')
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = _('Invalid Authorization header. Credentials string '
'should not contain spaces.')
raise exceptions.AuthenticationFailed(msg)
return auth[1]
# 认证类配置了,如果不传jwt,不会校验,一定配合权限类使用



认证类都需要重写authenticate还记得吗?
是因为三大认证中源码会调用这个authenticate


核心:如何校验token 如何得到token

拿到authuser表:通过用户名拿到当前用户
token怎么取出来的:



django 会把所有请求头加个大写的http

基于drf-jwt自定义用户签发与认证
自定义用户签发
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import UserInfo
from .authentication import JsonWebTokenAuthentication
class UserView(ViewSet):
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
user = UserInfo.objects.filter(username=username, password=password).first()
if user:
# 登录成功,签发token
# 通过user得到payload
payload = jwt_payload_handler(user)
# 通过payload得到token
token = jwt_encode_handler(payload)
return Response({'code': 1000, 'msg': '登录成功', 'token': token})
else:
return Response({'code': 1001, 'msg': '用户名或密码错误'})
建表:

views: Viewset = 魔法类 + APIView

写逻辑:

使用drf-jwt的函数生成token:

通过user对象得到payload载荷,通过payload得到token字符串。

导入配置:

自定义payload:

自定义token串:

配置路由。

向路由发送请求:

基于auth_user表自己写签发。
自定义认证类
前端放在请求头中,并且名字就叫token。django自动加http.


抛异常:

复制源码写token认证:

修改:

导入:

得到当前用户:

base64decode:
解析payload

完整代码:

只要访问异常登录接口,就会去UserInfo表中查异常用户:
希望惰性查询,用到user对象,再去查。



测试认证类:




修改token过期时间:

元组的产生:

token签发出来了,在过期时间内可以一直使用。
双token认证:

simpleui后台管理美化
# 之前公司里,做项目,要使用权限,要快速搭建后台管理,使用djagno的admin直接搭建,django的admin界面不好
#第三方的美化:
-xadmin:作者弃坑了,bootstrap+jq
-simpleui: vue,界面更好看
# 现在阶段,一般前后端分离比较多:django+vue
-带权限的前端端分离的快速开发框架
-django-vue-admin
-自己写
对django admin后台管理进行了美化。
带权限的前后端分离的快速开发框架
-django-vue-admin
-自己写
使用步骤
# 1 安装
pip install django-simpleui
# 2 在app中注册
# 3 调整左侧导航栏----》
-menu_display对应menus name
-如果是项目的app,就menus写app
-菜单可以多级,一般咱们内部app,都是一级
-可以增加除咱们app外的其它链接---》如果是外部链接,直接写地址,如果是内部链接,跟之前前后端混合项目一样的写法:咱们的案例---》show 的路由
SIMPLEUI_CONFIG = {
'system_keep': False,
'menu_display': ['图书管理', '权限认证', '张红测试'], # 开启排序和过滤功能, 不填此字段为默认排序和全部显示, 空列表[] 为全部不显示.
'dynamic': True, # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
'menus': [
{
'name': '图书管理',
'app': 'app01',
'icon': 'fas fa-code',
'models': [
{
'name': '图书',
'icon': 'fa fa-user',
'url': 'app01/book/'
},
{
'name': '出版社',
'icon': 'fa fa-user',
'url': 'app01/publisssh/'
},
{
'name': '作者',
'icon': 'fa fa-user',
'url': 'app01/author/'
},
{
'name': '作者详情',
'icon': 'fa fa-user',
'url': 'app01/authordetail/'
},
]
},
{
'app': 'auth',
'name': '权限认证',
'icon': 'fas fa-user-shield',
'models': [
{
'name': '用户',
'icon': 'fa fa-user',
'url': 'auth/user/'
},
{
'name': '组',
'icon': 'fa fa-user',
'url': 'auth/group/'
},
]
},
{
'name': '张红测试',
'icon': 'fa fa-file',
'models': [
{
'name': 'Baidu',
'icon': 'far fa-surprise',
# 第三级菜单 ,
'models': [
{
'name': '爱奇艺',
'url': 'https://www.iqiyi.com/dianshiju/'
# 第四级就不支持了,element只支持了3级
}, {
'name': '百度问答',
'icon': 'far fa-surprise',
'url': 'https://zhidao.baidu.com/'
}
]
},
{
'name': '大屏展示',
'url': '/show/',
'icon': 'fab fa-github'
}]
}
]
}
# 4 内部app,图书管理系统某个链接要展示的字段---》在admin.py 中----》自定义按钮
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('nid', 'name', 'price', 'publish_date', 'publish')
# 增加自定义按钮
actions = ['custom_button']
def custom_button(self, request, queryset):
print(queryset)
custom_button.confirm = '你是否执意要点击这个按钮?'
# 显示的文本,与django admin一致
custom_button.short_description = '测试按钮'
# icon,参考element-ui icon与https://fontawesome.com
# custom_button.icon = 'fas fa-audio-description'
# # 指定element-ui的按钮类型,参考https://element.eleme.cn/#/zh-CN/component/button
custom_button.type = 'danger'
# # 给按钮追加自定义的颜色
# custom_button.style = 'color:black;'
# 5 app名字显示中文,字段名字显示中文
-新增,查看修改展示中文,在表模型的字段上加:verbose_name='图书名字',help_text='这里填图书名'
-app名字中文:apps.py---》verbose_name = '图书管理系统'
# 6 其它配置项
SIMPLEUI_LOGIN_PARTICLES = False #登录页面动态效果
SIMPLEUI_LOGO = 'https://avatars2.githubusercontent.com/u/13655483?s=60&v=4'#图标替换
SIMPLEUI_HOME_INFO = False #首页右侧github提示
SIMPLEUI_HOME_QUICK = False #快捷操作
SIMPLEUI_HOME_ACTION = False # 动作

注册:

查看页面:

快速写一个图书管理系统:建表
admin.py:

修改app的名字:







添加按钮:


点按钮就会执行函数:

完整:


添加弹窗也可以做。
添加功能:

修改配置文件:

修改的示例:

menus:

二级菜单和三级菜单:



点击可以访问url.
复制models添加二级菜单:


输入错误的url:

我们写的地址,必须是自动生成的路由之一。
这样不行:

跟表没有必然联系的页面:
写一个我们项目中存在的路径

添加弹出框:



还可以layer文件上传。
配置项:
关闭粒子特效。
修改logo。



隐藏快捷动作:
这个一定要置为False:


app名字显示中文,字段名字显示中文:
在表里写ver_bosename



大屏展示
# 监控大屏展示
-https://search.gitee.com/?skin=rec&type=repository&q=%E5%B1%95%E7%A4%BA%E5%A4%A7%E5%B1%8F
-就是前后端混合项目,js,css,图片对应好,就可以了



将Index复制到templates,然后写个路由:

ctrl+R全局替换。




每个用户显示的菜单不一样:

所以每次修改代码需要重新登录。
权限控制 (acl、rbac)
# 公司内部项目
-rbac:是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便
-用户表:用户和角色多对多关系,
-角色表
-一个角色可能有多个权限----》
-开发角色:拉取代码,上传代码
-财务角色:开工资,招人,开除人
-
-权限表:角色和权限是多多多
-拉取代码
-上传代码
-部署项目
-开工资
-招人
-开除人
-
-通过5张表完成rbac控制:用户表,角色表,权限表, 用户角色中间表, 角色权限中间表
-如果某个人,属于财务角色,单只想要拉取代码权限,不要上传代码权限
-通过6张表:django的admin----》后台管理就是使用这套权限认证
用户表,
角色表,
权限表,
用户角色中间表,
角色权限中间表
用户和权限中间表
# 互联网项目
-acl:Access Control List 访问控制列表,权限放在列表中
-权限:权限表----》 发视频,评论,开直播
-用户表:用户和权限是一对多
张三:[发视频,]
李四:[发视频,评论,开直播]
# 演示了 django-admin 的权限控制
-授予lqz 某个组
-单独授予权限
# django -auth--6张表
auth_user 用户表
auth_group 角色表,组表
auth_permission 权限表
-----------
auth_user_groups 用户和角色中间表
auth_group_permissions 角色和权限中间表
-------------
auth_user_user_permissions 用户和权限中间表
# java:若依
# go :gin-vue-admin
# python :django-vue-admin
用户表 和 权限表 一对多关系。
互联网对外的用户:
acl访问控制列表 权限放在列表中
Access Control List
rbac基于角色的访问
开发 总监 总裁办 都是我
用户跟角色是多对多。
角色和权限也是多对多
财务可以发工资 总裁也可以发公司
一个权限多个角色。
不是同时把所有权限都授予某个人。是把权限授予角色,角色再授予用户。
自定义rbac

把开发权限授予财务角色。但是直接授予角色的全部权限,那么这个权限太大了,所有需要自定义权限控制。

给一个组,这个组里面的用户只有查看图书的权限。
新建组:

给组授予权限。

给用户分配组:需要使用root账号

重新登录:

只能看,增删按钮没了。
基于前后端分离的基于rbac的访问控制。
期中架构如果能写个django-admin
公司的权限控制框架。


单独对组中某个用户授予权限,如何设置:
django admin是基于auth表写的:

权限表:


饿了么-vue-admin 开源框架
D2Admin

fastapi vue admin
python casbin0......

练习
1 整理 jwt 签发,认证流程 3
2 自定义用户表,签发,认证 4
3 自定义用户表,使用make_password保存密码 5 密码存在后端不是明文 使用类似django的加密技术
4 simpleui 写个图书管理系统 6
5 演示一下admin 的rbac 7
----------------------
6 研究 python casbin 支持acl rbac,abac。。。。权限控制 1 ---> 还可以耗时间研究
7 双token认证 2
drf-jwt配置文件 jwt签发认证源码分析 自定义用户签发认证 simpleui后台管理美化 权限控制 (acl、rbac)的更多相关文章
- Django drf:序列化增删改查、局部与全局钩子源码流程、认证源码分析、执行流程
一.序列化类的增.删.改.查 用drf的序列化组件 -定义一个类继承class BookSerializer(serializers.Serializer): -写字段,如果不指定source ...
- Django rest framework源码分析(1)----认证
目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...
- Django(64)频率认证源码分析与自定义频率认证
前言 有时候我们发送手机验证码,会发现1分钟只能发送1次,这是做了频率限制,限制的时间次数,都由开发者自己决定 频率认证源码分析 def check_throttles(self, request): ...
- drf-三大认证源码分析、基于APIView编写分页、异常处理
1.权限源码分析 1.APIView源码497行:self.initial(request, *args, **kwargs)中进行了三大认证. 2.在initial的源码中,以下三行代码是进行三大认 ...
- Solr4.8.0源码分析(3)之index的线程池管理
Solr4.8.0源码分析(3)之index的线程池管理 Solr建索引时候是有最大的线程数限制的,它由solrconfig.xml的<maxIndexingThreads>8</m ...
- Django rest framework 源码分析 (1)----认证
一.基础 django 2.0官方文档 https://docs.djangoproject.com/en/2.0/ 安装 pip3 install djangorestframework 假如我们想 ...
- drf框架,restful接口规范,源码分析
复习 """ 1.vue如果控制html 在html中设置挂载点.导入vue.js环境.创建Vue对象与挂载点绑定 2.vue是渐进式js框架 3.vue指令 {{ }} ...
- drf的基本使用、APIView源码分析和CBV源码拓展
cbv源码拓展 扩展,如果我在Book视图类中重写dispatch方法 -可以实现,在get,post方法执行之前或者之后执行代码,完成类似装饰器的效果 def dispatch(self, requ ...
- Django-restframework 之认证源码分析
Django-restframework 源码分析之认证 前言 最近学习了 django 的一个 restframework 框架,对于里面的执行流程产生了兴趣,经过昨天一晚上初步搞清楚了执行流程(部 ...
- SOFA 源码分析 — 自定义线程池原理
前言 在 SOFA-RPC 的官方介绍里,介绍了自定义线程池,可以为指定服务设置一个独立的业务线程池,和 SOFARPC 自身的业务线程池是隔离的.多个服务可以共用一个独立的线程池. API使用方式如 ...
随机推荐
- Java 面试题之 Logback 打印日志是如何获取当前方法名称的?
在 Java 中,有四种方法可以获取当前正在执行方法体的方法名称,分别是: 使用 Thread.currentThread().getStackTrace() 方法 使用异常对象的 getStackT ...
- dbeaver软件的使用
dbeaver软件的使用 一.dbeaver简介: dbeaver是免费和开源(GPL)为开发人员和数据库管理员通用数据库工具. DBeaver [1] 是一个通用的数据库管理工具和 SQL 客户端, ...
- .net下功能强大的HTML解析库HtmlAgilityPack,数据抓取必备
HtmlAgilityPack是一个.NET平台下的HTML解析库,它可以将HTML文本转换为DOM文档对象,方便我们对HTML文本进行操作和分析.HtmlAgilityPack支持XPath语法,可 ...
- 【scipy 基础】--空间计算
scipy.spatial子模块提供了一系列用于处理和计算空间数据和几何形状的算法和工具,在许多领域都有广泛的应用,例如计算机视觉.地理信息系统.机器人学.医学影像分析等. 下面,来具体看看scipy ...
- 功能不够,SQL来凑,修改数据库的正确姿势?
修改数据库是一项关键任务,需要小心谨慎地执行,以确保数据的完整性和准确性.下面是一个详细的步骤指南,介绍了正确修改数据库的姿势. 第一步:备份数据库 在进行任何数据库修改之前,务必备份数据库.这样,如 ...
- Java的四种内部类(成员内部变量,静态内部变量,局部内部类,匿名内部类)
内部类 内部类就是在一个内的内部再定义一个内 内部类的分类:成员内部类,静态内部类,局部内部类,匿名内部类 (1)成员内部类 指类中的一个普通成员,可以定义成员属性,成员方法 内部类是可以访问外部类的 ...
- 【scikit-learn基础】--『数据加载』之玩具数据集
机器学习的第一步是准备数据,好的数据能帮助我们加深对机器学习算法的理解. 不管是在学习还是实际工作中,准备数据永远是一个枯燥乏味的步骤.scikit-learn库显然看到了这个痛点,才在它的数据加载子 ...
- WPF 入门基础
关于 WPF 和 XAML 什么是 WPF WPF(Windows Presentation Foundation)是由微软开发的桌面应用程序框架,用于创建现代化.高度交互和具有视觉吸引力的用户界面. ...
- Odoo16—权限控制
odoo的权限控制是通过用户组来实现的,在用户组中配置控制权限,然后再添加用户到用户组中,从而实现对用户的访问和操作权限控制.一个用户可以属于多个用户组,用户最终的权限范围取决于所属用户组权限的并集. ...
- NetSuite 开发日记:如何管理多环境自定义列表值
在 NetSuite 中可以创建自定义列表,列表可用于为其他(自定义)记录上的下拉选项列表值. var rec = record.create({ type: 'customrecord_xx' }) ...