路飞:路飞后台配置之封装logger、路飞后台配置之封装全局异常、路飞台配置之二次封装response、luffy数据库创建、软件开发模式、User模块User表配置,、开放media访问、djagno的配置文件讲解、开启media访问
一、路飞后台配置之封装logger
以后,项目肯定要记录日志
-日志都可以打印到控制台 -日志可以写到日志文件中 -日志存到某个库中 logru第三方日志库 -所有项目日志统一管理 sentry:django写的服务,收集日志的,可以展示 开源的
使用了日志之后,在项目中不要出现print了,以后都用日志 logger.info()打印信息,以后项目上线,只需要调整日志级别,低级别的日志就不打印了,于是日志输出不用删掉
sentry:django写的实时日志平台
配置步骤
步骤一:复制代码(之前学过的日志字典)到配置文件中(dev.py)
代码如下:
# 真实项目上线后,日志文件打印级别不能过低,因为一次日志记录就是一次文件io操作 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { # 这里是配置日志的输出格式,上面的记录了记录时间 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(module)s %(lineno)d %(message)s' }, }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { # console配置的是输出到控制台中的日志内容 'console': { # 实际开发建议使用WARNING 'level': 'WARNING', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'simple' }, # file配置的是记录到日志文件中的日志内容 'file': { # 实际开发建议使用ERROR 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', # 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi 'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"), # 日志文件的最大值,这里我们设置300M 'maxBytes': 300 * 1024 * 1024, # 日志文件的数量,设置最大日志数量为10 'backupCount': 10, # 日志格式:详细格式 'formatter': 'verbose', # 文件内容编码 'encoding': 'utf-8' }, }, # 日志对象 'loggers': { 'django': { 'handlers': ['console', 'file'], 'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统 }, } }
步骤二:在utils新建 common_logger.py ,写入下方代码,得到日志对象
import logging # 通过配置问中的名字拿到logger对象,以后只需要导入,直接使用对象写日志即可 logger=logging.getLogger('django')
步骤三:在任意想用日志的地方,导入使用即可
views.py
from utils.common_logger import logger from django.http import JsonResponse def test_logger(request): logger.info('info级别的日志') logger.error('error级别的日志') return JsonResponse({'name':'wxl'})
urls.py
from django.contrib import admin from django.urls import path from user import views urlpatterns = [ path('admin/', admin.site.urls), path('test_logger/', views.test_logger), ]
二、路飞后台配置之封装全局异常
前端要接收的数据格式,要统一,无论后端是否出错
在drf的三大认证,视图类的方法中只要出了异常,就会执行一个函数,但是这个函数只能处理drf的异常
因此我们需要自己写个函数,既能处理drf异常,又能处理django异常,这样前端看到格式都统一了
# 写一个函数,封装全局异常 -1 统一返回格式 -2 记录日志:出了异常,程序有问题,后期排查问题
127.0.0.1和0.0.0.0路由在项目中的区别
当我们在访问项目的路由时,如果使用的是127.0.0.1的本地路由,只有我们自己的计算机可以访问项目的路由。
当我们使用0.0.0.0充当项目的路由时,同一个局域网内的所有计算机都能访问我们项目的路由
配置步骤
因为我们要用到drf,所以需要安装djangorestframework模块
步骤一:在utils中新建 common_exceptions.py
步骤二:在common_exceptions.py中编写全局异常处理函数
from rest_framework.views import exception_handler as drf_exception_handler from rest_framework.response import Response from utils.common_logger import logger # 只要走到这个函数中,一定是出异常了,所以要记录日志 def exception_handler(exc, context): # 1 记录日志 : 哪个ip地址,用户id是多少,访问哪个路径,执行哪个视图函数,出了什么错 request = context.get('request') view = context.get('view') ip = request.META.get('REMOTE_ADDR') user_id = request.user.pk path = request.get_full_path() response = drf_exception_handler(exc, context) if response: logger.warning('drf出了异常,异常是:%s' % str(exc)) # drf的异常已经处理了--->直接取detail 会有点小小的问题,碰到再解决 res = Response({'code': 999, 'msg': response.data.get('detail', '服务器异常,请联系系统管理员')}) else: # djagno的异常,咱们要处理 logger.error('用户【%s】,ip地址为【%s】,访问地址为【%s】,执行视图函数为【%s】,出错是【%s】' % (user_id, ip, path, str(view), str(exc))) res = Response({'code': 888, 'msg': '服务器异常,请联系系统管理员'}) return res
ps1:这里因为需要用warning级别的日志记录drf中的错误,所以需要修改配置文件中的日志记录等级
# 真实项目上线后,日志文件打印级别不能过低,因为一次日志记录就是一次文件io操作 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { # 这里是配置日志的输出格式,上面的记录了记录时间 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(module)s %(lineno)d %(message)s' }, }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { # console配置的是输出到控制台中的日志内容 'console': { # 实际开发建议使用WARNING 'level': 'WARNING', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'simple' }, # file配置的是记录到日志文件中的日志内容 'file': { # 实际开发建议使用ERROR 'level': 'WARNING', 'class': 'logging.handlers.RotatingFileHandler', # 日志位置,日志文件名,日志保存目录必须手动创建,注:这里的文件路径要注意BASE_DIR代表的是小luffyapi 'filename': os.path.join(os.path.dirname(BASE_DIR), "logs", "luffy.log"), # 日志文件的最大值,这里我们设置300M 'maxBytes': 300 * 1024 * 1024, # 日志文件的数量,设置最大日志数量为10 'backupCount': 10, # 日志格式:详细格式 'formatter': 'verbose', # 文件内容编码 'encoding': 'utf-8' }, }, # 日志对象 'loggers': { 'django': { 'handlers': ['console', 'file'], 'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统 }, } }
ps2:因为封装了全局异常处理,所以当用户为登陆的时候,日志中记录的用户名会是None
步骤三:在配置文件中注册drf的app,并修改drf使用的异常处理函数以后只要出了异常,都会走咱们的函数
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'home', 'user', ] # drf的配置 REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'utils.common_exceptions.exception_handler', }
步骤四:在视图层中测试
views.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.exceptions import APIException class TestExcepiton(APIView): def get(self, request): # drf 异常 raise APIException('drf抛出异常') # 未知错误 # l = [1, 23, 4] # print(l[9]) # 9/0 # django主动抛的错误 # raise Exception('出错了') return Response('ok')
urls.py
from django.contrib import admin from django.urls import path from user import views urlpatterns = [ path('admin/', admin.site.urls), path('test_logger/', views.test_logger), path('test_exception/', views.TestExcepiton.as_view()), ]
当我们配置好全局异常处理后,就可以勇敢大胆写代码,即便报错,程序不会蹦,并且会记录日志,并且处理成统一格式
如果我们在配置了全局异常处理的情况下出现程序报错停止的情况,就说明我们编写的全局异常处理函数(common_exceptions.py)中出了问题
三、路飞台配置之二次封装response
- drf提供的Response对象,不能很方便的加入code和msg字段,但是咱们公司规定,前端收到的格式都是固定的。
- 因此我们自己封装一个Response类,以后都用我们自己封装的,方便咱们写code和msg
-{code:100,msg:提示,data:{}/[]} -{code:100,msg:提示,token:asdfasd,user:lqz}
封装后的效果:code,msg可以不传,不传就用默认的值
配置步骤
第一步:在utils下新建common_response.py
第二步:在common_response.py中封装APIRespon
ps:这里使用了字典的update方法,基本作用就是跟新有的字段,并把没有的字段添加进去
from rest_framework.response import Response ''' 以后使用 -return APIResponse()----------前端收到-->{code:100,msg:成功} -return APIResponse(token=xsdse,username=lqz)----------前端收到-->{code:100,msg:成功,token:xsdse,username:lqz} -return APIResponse(data=[{},{},{}])----------前端收到-->{code:100,msg:成功,data:[{},{},{}]} -return APIResponse(code=101,msg=失败)----------前端收到-->{code:101,msg:失败} -return APIResponse(headers={'xx':'xx'})----------前端收到-->{code:100,msg:成功},但是响应头中有xx=xx -return APIResponse(status=201)----------前端收到-->{code:100,msg:成功},但是响应状态码是201 ''' class APIResponse(Response): def __init__(self, code=100, msg='成功', status=None, headers=None, **kwargs): data = {'code': code, 'msg': msg} if kwargs: # 有值,说明,传了 除了code msg status headers 以外的,咱们都要返回给前端,放到这个data中 data.update(kwargs) # Response(data=data,status=status,headers=headers) super().__init__(data=data, status=status, headers=headers) # 不要return,你可以这样做 self.data=data self.status=status
第三步:导入使用,视图函数的方法,返回时,都使用咱们自己的
views.py
## 只是为了测试APIResponse from utils.common_response import APIResponse class TestAPIResponse(APIView): def get(self, request): # return APIResponse(token='asdfasdf', usename='lqz') # return APIResponse(code=101, msg='错误') return APIResponse(data=[{'name': "红楼梦", 'price': '66'}, {'name': "红楼梦", 'price': '66'}])
urls.py
from django.contrib import admin from django.urls import path from user import views urlpatterns = [ path('admin/', admin.site.urls), path('test_logger/', views.test_logger), path('test_exception/', views.TestExcepiton.as_view()), path('test_response/', views.TestAPIResponse.as_view()), ]
四、luffy数据库创建
4.1 创建用户创建库
- 创建luffy数据库使用mysql
ps:mysql需要使用5.7版本
- 之前项目操作数据库,都是使用root用户,root用户权限太高了,在公司里,一般不会给你root用户权限
- 如果开发人员是root权限,数据安全性就很差
- 在mysql中创建一个luffy库,再创建luffy用户,给用户授予luffy库的所有权限,即luffy用户只对luffy库有操作权限
步骤一
- 管理员连接数据库(每个人的密码不同)
mysql -uroot -proot
步骤二
- 创建数据库
create database luffy default charset=utf8;
步骤三
- 查看用户目前已有的用户
select user,host,password from mysql.user;
如果没有创建过别的用户,这里只会显示root用户的信息
ps:5.7往后的版本使用的命令如下:
select user,host,authentication_string from mysql.user;
步骤四
- 创建路飞用户,并授予luffy库所有权限
如何设置权限账号密码?
# 授权账号命令:grant 权限(create, update) on 库.表 to '账号'@'host' identified by '密码'
- 配置任意ip都可以连入数据库的账户
grant all privileges on luffy.* to 'luffy'@'%' identified by 'Luffy123?';
步骤五
- 由于数据库版本的问题,可能本地还连接不上,就给本地用户单独配置
grant all privileges on luffy.* to 'luffy'@'localhost' identified by 'Luffy123?';
步骤六
- 配置完账号信息后还需要刷新一下权限,因为此时我们的配置信息是写在文件中的,刷新权限后就会让他加载到内存中运行
flush privileges;
最后我们得到了只能操作luffy数据库的账户
账号:luffy 密码:Luffy123?
使用不同的用户,能操作的表也是不同的:
root用户
luffy用户
4.2本地连接数据库和使用ip连接数据库的区别
通过上面的查看已有用户的命令,我们可以看到用户的信息,其中的host信息代表的就是用不同的方式连接数据库时的配置。
如果host为%号,表示所有的远程路由都可以访问
4.3 使用项目连接库
mysqlclient模块的选择
项目操作mysql,需要使用模块
-pymysql -mysqlDB -mysqlclient
- 如果我们直接运行项目会报错,django默认使用mysqlDB操作mysql,mysqlDB这个模块,在python2可以的,在python3中不支持,于是咱们使用pymysql替换,到了django2.0.7以后,如果使用pymysql替换,需要改django的源代码,后期使用mysqlclient,替换pymysql,mysqlclient是mysqlDB的python3.x版本
- 如果使用pymysql,需要改源码,需要执行(这段代码的作用我们成为猴子补丁)
import pymysql pymysql.install_as_MySQLdb()# 猴子补丁
-
猴子补丁:
猴子补丁,把里面所有mysqlDB的对象,都替换成pymysql
-猴子补丁是:在程序运行过程中得动态替换技术
-详见老刘博客:Python并发编程-协程之gevent模块-以后再django中不使用pymysql了,使用mysqlclient,不需要再执行任何补丁了
-win,linux,mac,这个模块不太好装,看人品,有时候很顺利,有时候装不上 -
统一使用mysqlclient来作为操作mysql的底层库,一切都解决了
-统一使用mysqlclient来作为操作mysql的底层库 -基于py2的mysqldb,在py3上重新了,但是名字改成了mysqlclient -使用mysqlclient,只需要安装这个模块,不需要再写任何代码,直接用即可 -但是:mysqlclient 这个模块,不好装 -win 一般人品好,人品好,pip install mysqlclient -人品不好,装不了,centos部署项目,后面会讲centos上如何装
- mysqlclientan安装
pip install mysqlclient 也可以使用pycharm安装
pycharm连接数据库
安装了mysqlclient后,需要在配置文件dev.py中写入下列代码:
'修改数据库配置' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'luffy', 'USER': 'luffy', 'PASSWORD': 'Luffy123?', 'HOST': 'localhost', 'PORT': 3306 } } '如果使用的是pymysql,需要额外添加这些代码' import pymysql pymysql.install_as_MySQLdb()
在配置数据库信息的时候,我们考虑到用户名跟密码写死了,并不安全
可能存在的风险
如果我的源代码泄露了->数据库用户名密码就泄露->黑客可以远程登录->脱库(就是数据库被人家偷了) -华住汉庭的酒店入住信息泄露,源代码泄露了,导致被脱库 -上海随身办的数据泄露
- 因此这里可以使用环境变量来动态的存储用户名和密码,修改后的代码如下:
# 用户名密码写死在代码中了,为保证安全,使用环境变量存取 # os.environ可以获取到环境变量中的数据 # 这里我们设置的是通过环境变量的名称获取用户密码,如果不存在就使用默认的值 name = os.environ.get('LUFFY_NAME', 'luffy') password = os.environ.get('LUFFY_PASSWORD', 'Luffy123?') # 拓展:有的公司,直接有个配置中心---》服务--》只用来存放配置文件 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'luffy', 'USER': name, 'PASSWORD': password, 'HOST': '127.0.0.1', 'PORT': 3306 } }
配置好之后在pycharm中连接数据库
五、软件开发模式
瀑布模式
bbs项目就是按照这种模式,现在已经用的不多了
-需求分析---》设计--》创建数据库 所有都创建---》开发(3个月)---》交给测试--》测试通过---》上线
敏捷开发
-需求分析---》设计---》只设计一个板块---》开发(2周)---》交给测试---》运维上线(测试环境) -设计---》只设计一个板块---》开发(2周)---》交给测试---》运维上线(测试环境) -一个sprint周期 -scrum敏捷项目管理
六、User模块User表配置,开放media访问
提示:当你决定使用auth表扩写,项目一定不要先迁移,先建好用户表再迁移
如果已经迁移完了,再想用auth的user表,操作很复杂: -删库,删迁移文件所有app -删admin和auth的迁移文件
因为我们在扩写auth表的时候添加了头像字段,存储了图片,因此我们需要导入pillow模块
pip install Pillow
接着我们去user app的models.py中扩写一个User表
from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): # 扩写手机号和头像字段 mobile = models.CharField(max_length=11, unique=True) # 需要pillow包的支持 icon = models.ImageField(upload_to='icon', default='icon/default.png') class Meta: db_table = 'luffy_user' verbose_name = '用户表' verbose_name_plural = verbose_name def __str__(self): return self.username
接着我们需要去配置文件中更换auth模块使用的用户表
dev.py
# 自定义用户表配置 AUTH_USER_MODEL = 'user.User'
之后我们在迁移数据库的时候会报错,报错提示是说找不到小luffy_api的环境变量,这是因为在配置文件中配置环境变量的时候,小luffy_api的配置代码如下:
sys.path.insert(0, BASE_DIR)
这时候我们使用os.environ可以发现跟别的环境变量相比,小luffy_api的环境变量是一个对象,因此我们需要改变写法为:
sys.path.insert(0, str(BASE_DIR))
数据库迁移命令:
执行迁移命令前,需要从cmd界面中进去manage.py文件所在的目录
python38 manage.py makemigrations python38 manage.py migrate
数据库迁移成功结果如下:
七、djagno的配置文件讲解
在配置文件的最上方我们看到他导入了pathlib模块
from pathlib import Path
作用:3.6 以后,处理文件路径的模块,原来是用os模块拼接路径
from pathlib import Path import os import sys # 项目根路径 # 我们就是要让小路飞路径作为项目根路径 BASE_DIR = Path(__file__).resolve().parent.parent # 项目根路径, 小路飞luffy_api路径 D:\pythonProject03\luffy_api\luffy_api # print(BASE_DIR) # 把 apps 路径加入到环境变量 sys.path.insert(0, os.path.join(BASE_DIR, 'apps')) # 把BASE_DIR也加入到环境变量,以后直接从小路飞开始导起即可 sys.path.insert(0, str(BASE_DIR)) # print(sys.path) # 以后从大路飞开始导起,或者小路飞开始导起,或者apps开始导起都可以 # 秘钥,涉及到加密的django中,都会用它 SECRET_KEY = 'django-insecure-!g(8l%fw_#t$pz$x4jdf#e3$b4+c%xzqyq@3zki08vj&i)z4k-' # 项目是以debug模式运行,还是非debug模式运行 # 项目上线,要改成false # debug=True 代码可以热更新 # 调试模式下,对开发者更友好:可以列出所有路径.报了错,前端能看到 DEBUG = False # ALLOWED_HOSTS = ['*']需要搭配debug=False,它的意思是,允许我的项目部署在哪个ip地址上,* 表示允许部署在所有地址上 ALLOWED_HOSTS = ['*'] # django 是多个app组成的,里面配置app,默认带的app,django内置的app # django 是一个大而全的框架,有很多内置app: # admin后台管理, # auth权限管理, # contenttypes表中存app也表的关系, # sessions session表,django的session相关 # messages:消息框架,flask讲闪现,是一样的东西 # staticfiles:静态资源的 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', # 'luffy_api.apps.home', # luffy_api在环境变量,直接从这一层开始导起, 太长了,以后就想 注册 home # 'luffy_api.apps.user' 'home', 'user' ] # 中间件 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', # 安全相关中间件 'django.contrib.sessions.middleware.SessionMiddleware', # session相关中间件 'django.middleware.common.CommonMiddleware', # 带不带 / 问题 'django.middleware.csrf.CsrfViewMiddleware', # csrf 认证,生成csrf串 'django.contrib.auth.middleware.AuthenticationMiddleware', # 用户认证 'django.contrib.messages.middleware.MessageMiddleware', #消息框架相关 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] # 根路由 ROOT_URLCONF = 'luffy_api.urls' # 模板文件 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], # 坑,模板路径用列表,可以有多个 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] # 项目运行的配置---》项目上线运行,使用uwsgi 运行 application() WSGI_APPLICATION = 'luffy_api.wsgi.application' # 用户名密码写死在代码中了,保证安全 name = os.environ.get('LUFFY_NAME', 'luffy') password = os.environ.get('LUFFY_PASSWORD', 'Luffy123?') # 拓展:有的公司,直接有个配置中心---》服务--》只用来存放配置文件 # 数据库配置,mysql 主从搭建完,读写分离 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'luffy', 'USER': name, 'PASSWORD': password, 'HOST': '127.0.0.1', 'PORT': 3306 }, } #忽略掉 AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # 国际化 LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False # 静态资源 STATIC_URL = '/static/' # 这是后面版本才有的配置,更改了id字段的字段类型(更大了) DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
八、开启media访问
因为我们需要存储用户的头像,因此需要实现自定义开放接口给前端访问
步骤一
在配置文件中添加media的配置信息
MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
步骤二
在总路由中注册,这里也不是非要使用re_path
from django.contrib import admin from django.urls import path from user import views from django.views.static import serve # 导入配置文件--->如果你配了,用你的,如果没配,用内置的 from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('test_logger/', views.test_logger), path('test_exception/', views.TestExcepiton.as_view()), path('test_response/', views.TestAPIResponse.as_view()), # 开启media访问 # re_path('^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}), path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}) ]
ps1:转换器的第一个path是匹配的方式(也可以说类型吧),第二个path是传入到视图函数中的参数名称
ps2:路由中的serve起到传递参数给视图函数的作用,并且能找到视图函数或类的位置拿到结果(这样的功能建议研究一下,可能有些情况需要我们自行编写)
ps2:在给media注册路由的时候我们会导入配置文件,我们可以根据配置文件的路由直接导入配置文件,也可以使用这里的
from django.conf import settings
导入,在使用这种方式导入的时候,如果我们没有配置配置文件,就会使用内置的自带的配置文件,如果我们写了配置文件,就会优先使用我们的配置文件,以后都使用这种方式
配置成功之后,就可以在浏览器中使用路由打开图像
更多内容请参考之前的博客:https://www.cnblogs.com/zhihuanzzh/p/17023231.html#前端获取头像文件
九、扩展
# 期终架构相关 -前端---》看人家开源的前端项目,看不懂 -第一种情况,vue+java====》分析有哪些接口,drf复写出来 -第二种情况: 你新建前端项目,你看到它哪个页面好看,copy你里面去只要template和style -js东西自己写 # https://zhuanlan.zhihu.com/p/370167569 # windows安装 mysql 5.7 https://zhuanlan.zhihu.com/p/571585588
前后端分离的rbac项目演示
# 后台:https://gitee.com/liuqingzheng/rbac_manager # 前端:https://gitee.com/liuqingzheng/vue_admin
项目演示
# 登录 # 系统管理 -用户管理 -角色管理 -菜单管理 -部门管理 -岗位管理 # 最核心 -创建了用户,授予了角色,因为角色有权限,这个用户就有权限 -如果这个用户有权限,进入到系统,就能看到相关的操作,如果没有权限,就不能操作
面试题,md5是对称加密还是非对称加密(题目没什么含金量)
# 面试题,md5是对称加密还是非对称加密 -对称加密:加密的秘钥和解密的秘钥是同一个 -非对称加密:加密使用公钥加密,解密使用私钥解密,使用公钥是不能解密的 -摘要算法:没有解密这一说
十、作业
1、面试题搜索:utf8和utf8mb4的区别
一、起源
MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。
可以简单的理解 utf8mb4 是目前最大的一个字符编码,支持任意文字。
二、为什么mysql有utf8和utf8mb4两种几乎差不多的字符集
utf8 是 Mysql 中的一种字符集,只支持最长三个字节的 UTF-8字符,也就是 Unicode 中的基本多文本平面。
Mysql 中的 utf8 为什么只支持持最长三个字节的 UTF-8字符呢?我想了一下,可能是因为 Mysql 刚开始开发那会,Unicode 还没有辅助平面这一说呢。那时候,Unicode 委员会还做着 “65535 个字符足够全世界用了”的美梦。Mysql 中的字符串长度算的是字符数而非字节数,对于 CHAR 数据类型来说,需要为字符串保留足够的长。当使用 utf8 字符集时,需要保留的长度就是 utf8 最长字符长度乘以字符串长度,所以这里理所当然的限制了 utf8 最大长度为 3,比如 CHAR(100) Mysql 会保留 300字节长度。至于后续的版本为什么不对 4 字节长度的 UTF-8 字符提供支持,我想一个是为了向后兼容性的考虑,还有就是基本多文种平面之外的字符确实很少用到。
要在 Mysql 中保存 4 字节长度的 UTF-8 字符,需要使用 utf8mb4 字符集,但只有 5.5.3 版本以后的才支持。我觉得,为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8. 对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR 替代 CHAR。
三、为什么要使用utf8mb4字符集
既然utf8应付日常使用完全没有问题,那为什么还要使用utf8mb4呢? 低版本的MySQL支持的utf8编码,最大字符长度为 3 字节,如果遇到 4 字节的字符就会出现错误了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xFFFF,也就是 Unicode 中的基本多文平面(BMP)。也就是说,任何不在基本多文平面的 Unicode字符,都无法使用MySQL原有的 utf8 字符集存储。这些不在BMP中的字符包括哪些呢?最常见的就是Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和一些不常用的汉字,以及任何新增的 Unicode 字符等等。
那么utf8mb4比utf8多了什么的呢?
多了emoji编码支持.
如果实际用途上来看,可以给要用到emoji的库或者说表,设置utf8mb4.
比如评论要支持emoji可以用到。
2、搜索:mysql本地连接和用ip连接的区别
本地连接与IP连接
MySQL有两种连接方式,一种是网络监听TCP/IP端口的模式,还有一种是socket模式。
- socket模式
- 在Linux下,socket是一种特殊的文件,也叫做套接字,是应用层与TCP/IP协议族通信的中间软件抽象层。虽然性能会比较好,但是这种socket模式仅限本机使用,其他机器无法通过网络链接连接到socket文件
- TCP/IP端口模式
- 这个就是为了让远程的应用连接到MySQL数据库的服务。
在MySQL配置中mysqld节中,可以设置绑定的对应的IP和端口,需要重启服务
- 这个就是为了让远程的应用连接到MySQL数据库的服务。
如果有使用-h指定主机的都是使用远程登录的方式,如果没有就是使用socket的方式
- mysql -h 127.0.0.1 的时候,使用TCP/IP连接, mysql server 认为该连接来自于127.0.0.1或者是 localhost.localdomain
- mysql -h localhost 的时候,是不使用TCP/IP连接的,而使用 Unix socket。此时,mysqlserver则认为该 client 是来自 localhost
- mysql权限管理中的"localhost"有特定含义:
注意:虽然两者连接方式有区别,但当localhost为默认的127.0.0.1时,两种连接方式使用的权限记录都是以下的1.row的记录(因为记录在前,先被匹配)
3、学习python位运算
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现