python day 18

2019/10/29

1. thinking in UML读书小感

这3天在看谭云杰的thinking in UML这本书,500多页的PDF扫描版,现在只看到279页,算是看完了一半,很多概念都是半懂不懂的,如在云山雾罩中一样。虽然看得不太明白,但是也有一些小感悟。

  1. 代码并不是全部,前期的需求分析,建模设计才是重点,这个就像行军打仗做好作战方略,备好粮草一样,后面的代码就是排兵步阵了。
  2. UML能看懂,不代表会画,会画的人必定是懂得RUP的人,这也解释了我这个初学者连一个小小的多用户登录FTP的程序的用例图都没画好的原因。
  3. 目标问题,我的目标是学会python,先掌握一门语言,而不是先上来就更高级的系统分析,有点好高骛远了。
  4. 不过,这本书看到,然后现在停下来,还是对我有不小的收获,对于整个软件开发的全貌有了不同的认识。同时也理解为什么很多公司不愿意招培训班或者自学的人了,因为如果只会写代码,像一些沟通用图如UML没有掌握,团队之间就不好沟通。

2. FTP作业重写

2.1 软件目录结构

按照老师的讲解,在命令行模式下输入python FTPServer.py start.

另一个命令行输入python FTPClient.py -s 127.0.0.1 -p 9999

2.2 FTPClient端脚本

2.2.1 bin目录下的FTPClient.py模块

import os
import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lib import client if __name__ == '__main__': client.Client(sys.argv)

2.2.2 config目录下的settings.py模块

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
USER_HOME = os.path.join(BASE_DIR, "db", "users")

2.2.3 lib目录下的client.py模块

import os
import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import hashlib
import json
import socket
from config import settings
import getpass
import time class Client(object):
def __init__(self, sys_argv):
self.USER_HOME = settings.USER_HOME
self.cwd = ""
self.args = sys_argv
self.HOST_IP = None
self.HOST_PORT = None
self.sock = None
self.logout_flag = False
self.response_code_dict = {
"100": "user successfully registerd",
"101": "username already existed,enter another username",
"200": "pass users authentication",
"201": "wrong username or password",
"202": "user does not exist",
"300": "ready to get file from server",
"301": "ready to send to server",
"302": "file doesn't exist on ftp server",
"303": "storage is full",
"601": "changed directory",
"602": "failed to find directory",
"2003": "already existed",
"2004": 'continue put',
"2005": "directory created"
}
self.argv_parse() def argv_parse(self):
if len(self.args) < 5:
self.help_msg()
sys.exit()
else:
mandatory_fields = ['-s', '-p']
for i in mandatory_fields:
if i not in self.args:
self.help_msg()
sys.exit()
try:
self.HOST_IP = self.args[self.args.index('-s') + 1]
self.HOST_PORT = int(self.args[self.args.index('-p') + 1])
self.handle()
except (IndexError, ValueError):
# 如果有索引错误,就打印帮助信息并退出程序
self.help_msg()
sys.exit("hhhh") def help_msg(self):
msg = """
input like below:\n
python FTPClient.py -s 127.0.0.1 -p 9999
"""
print(msg) def handle(self):
self.connect(self.HOST_IP, self.HOST_PORT)
while True:
username = input("username:>>>").strip()
password = getpass.getpass("password:>>>").strip()
md5 = hashlib.md5("lan".encode("utf-8"))
md5.update(password.encode("utf-8"))
password = md5.hexdigest()
user_pwd_dict = {"username": username, "password": password}
user_pwd = json.dumps(user_pwd_dict)
inp = input("请输入数字:1是登录,2是注册(q退出):>>>").strip()
if len(inp) < 1:
continue
if inp == '1':
if self.auth(user_pwd):
self.interactive()
elif inp == '2':
self.register(user_pwd)
elif inp.lower() == 'q':
break
else:
print("Invalid input")
self.sock.close() def connect(self, ip, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((ip, port,)) def auth(self, user_pwd):
'''
验证用户名与密码
:param user_pwd:
:return:
'''
self.sock.sendall(("user_auth|%s" % user_pwd).encode("utf-8"))
data = json.loads(self.sock.recv(1024).decode("utf-8"))
if data["result"] == "200":
self.username = data["username"]
self.cwd = data["user_home"]
self.storage_limit = data["storage_limit"]
self.storage_used = data["storage_used"]
return True
elif data["result"] == "202":
print(self.response_code_dict["202"])
return False
else:
print(self.response_code_dict["201"])
return False def register(self, user_pwd):
'''
注册用户
:param user_pwd:
:return:
'''
self.sock.sendall(("user_register|%s" % user_pwd).encode("utf-8"))
msg = self.sock.recv(1024)
if msg == b"100":
print(self.response_code_dict["100"])
elif msg == b"101":
print(self.response_code_dict["101"]) def interactive(self):
while not self.logout_flag:
cmd = input("[%s %s]:" % (self.username, self.cwd)).strip()
if len(cmd) < 1: continue
cmd_str = "cmd_" + cmd.split()[0] if hasattr(self, cmd_str):
func = getattr(self, cmd_str)
func(cmd)
else:
print("Invalid command") def cmd_cd(self, cmd):
'''
切换路径
:param cmd:
:return:
'''
if len(cmd.split()) < 2: pass
input_path = cmd.split()[1].strip()
print("try_path:>>>", input_path)
dir_list = self.cwd.split(os.sep)
print("dir_list:>>>", dir_list) # ["lanxing",""]
if dir_list[-1] == "":
del dir_list[-1]
new_path = ""
if input_path == "..":
del dir_list[-1] # []
if len(dir_list) > 0:
new_path = os.sep.join(dir_list) + os.sep
else:
if input_path.startswith(self.cwd):
new_path = input_path
else:
new_path = os.path.join(self.cwd, input_path) + os.sep
print("new_path:>>>", new_path)
if not new_path.startswith(self.username):
pass
else:
data = {"cwd": new_path}
data_json = json.dumps(data)
self.sock.sendall(("cd|%s" % data_json).encode("utf-8"))
server_reply = self.sock.recv(1024)
auth_result = json.loads(server_reply.decode("utf-8"))
if auth_result["result"] == "601":
self.cwd = new_path
else:
print(self.response_code_dict["602"]) def cmd_ls(self, cmd):
msg = ""
if len(cmd.split()) == 1:
msg = json.dumps({"cwd": self.cwd}) elif len(cmd.split()) == 2:
path = cmd.split()[1]
dir_list = self.cwd.split()
new_path = ""
if dir_list[-1] == "":
del dir_list[-1]
if path == "..":
del dir_list[-1]
if len(dir_list) > 0:
new_path = os.sep.join(dir_list) + os.sep
else:
if path.startswith(self.user_def_cwd):
new_path = path
else:
new_path = self.user_def_cwd + path if not new_path.startswith(self.user_def_cwd):
pass
msg = json.dumps({"cwd": new_path})
self.sock.sendall(("ls|{0}".format(msg)).encode("utf-8"))
msg_size = int(self.sock.recv(1024).decode("utf-8"))
self.sock.sendall(b"300")
has_received = 0
auth_result = ""
while has_received < msg_size:
data = self.sock.recv(1024)
auth_result += data.decode("utf-8")
has_received += len(data)
auth_result = json.loads(auth_result)
if auth_result["result"]:
print(auth_result["result"])
else:
print(self.response_code_dict["302"]) def cmd_put(self, cmd):
data = {"file_size": None, "file_name": None, "dst_path": None} if len(cmd.split()) == 2:
src_file = cmd.split()[1]
dst_path = self.cwd
else:
src_file, dst_path = cmd.split()[1], cmd.split()[2]
if len(src_file.split(os.sep)) == 1:
src_file = os.path.join(settings.BASE_DIR, "bin", src_file)
if os.path.isfile(src_file):
file_size = os.stat(src_file).st_size
data["file_size"] = file_size
data["file_name"] = os.path.basename(src_file)
if dst_path.startswith("lanxing"):
data["dst_path"] = dst_path
else:
print("Wrong directory!")
data_json = json.dumps(data)
self.sock.sendall(("put|%s" % data_json).encode("utf-8"))
auth_result = json.loads(self.sock.recv(1024).decode("utf-8"))
print(auth_result)
has_sent = 0
with open(src_file, "rb") as f:
if auth_result["result"] == "2003":
print(self.response_code_dict["2003"], )
print("服务端同名文件大小:%s,本地文件大小:%s" % (auth_result["file_size"], file_size))
choice = input("Y:续传;N:覆盖 >>>").strip()
if choice.upper() == "Y":
f.seek(auth_result["file_size"])
self.sock.sendall(b"2004")
has_sent += auth_result["file_size"]
elif choice.upper() == "N":
self.sock.sendall(b"301")
elif auth_result["result"] == "302":
self.sock.sendall(b"301")
print(self.sock.recv(1024))
for line in f:
self.sock.sendall(line)
has_sent += len(line)
percent = has_sent / file_size * 100
sys.stdout.write("\r")
sys.stdout.write("%.2f%% |%s" % (percent, int(percent) * "*"))
sys.stdout.flush()
time.sleep(0.01) else:
print("file does not exist!") def cmd_get(self, cmd):
client_path = ""
data = {
"file_name": None,
"client_path": None,
"file_size": None,
"result":"300"
}
if len(cmd.split()) > 1:
file_path = cmd.split()[1]
file_name = os.path.basename(file_path)
if file_path.startswith(self.username):
client_path = file_path
else:
client_path = os.path.join(self.cwd, file_path)
if len(cmd.split()) == 2:
dst_path = os.path.join(settings.USER_HOME, self.cwd, file_name)
elif len(cmd.split()) == 3:
dst_path = cmd.split()[2]
if not dst_path.startswith(self.username):
dst_path = os.path.join(settings.USER_HOME, self.cwd, dst_path, file_name)
else:
dst_path = os.path.join(settings.USER_HOME, dst_path, file_name)
if os.path.exists(dst_path):
file_size = os.stat(dst_path).st_size
data["file_size"] = file_size
data["client_path"] = client_path
data_json = json.dumps(data)
self.sock.sendall(("get|%s" % data_json).encode("utf-8"))
server_reply = json.loads(self.sock.recv(1024).decode("utf-8"))
has_received = 0
if server_reply["result"]=="2003":
choice=input("目标文件已存在,续载Y或全部重新下载N:").strip()
if choice.upper() =="Y":
data["result"]="2004"
data_json = json.dumps(data).encode("utf-8")
self.sock.sendall(data_json)
has_received += file_size
try:
os.makedirs(os.path.dirname(dst_path))
except OSError:
pass
with open(dst_path,"ab") as f:
while has_received < server_reply["file_size"]:
ret = self.sock.recv(1024)
f.write(ret)
has_received += len(ret)
percent = has_received/server_reply["file_size"]*100
sys.stdout.write("\r")
sys.stdout.write("%.2f%%"%percent)
sys.stdout.flush()
elif choice.upper()=="N":
data["result"] = "300"
data_json = json.dumps(data).encode("utf-8")
self.sock.sendall(data_json)
try:
os.makedirs(os.path.dirname(dst_path))
except OSError:
pass
with open(dst_path, "wb") as f:
while has_received < server_reply["file_size"]:
ret = self.sock.recv(1024)
f.write(ret)
has_received += len(ret)
percent = has_received / server_reply["file_size"] * 100
sys.stdout.write("\r")
sys.stdout.write("%.2f%%" % percent)
sys.stdout.flush()
elif server_reply["result"]=="300":
data["result"] = "300"
data_json = json.dumps(data).encode("utf-8")
self.sock.sendall(data_json)
try:
os.makedirs(os.path.dirname(dst_path))
except OSError:
pass
with open(dst_path, "wb") as f:
while has_received < server_reply["file_size"]:
ret = self.sock.recv(1024)
f.write(ret)
has_received += len(ret)
percent = has_received / server_reply["file_size"] * 100
sys.stdout.write("\r")
sys.stdout.write("%.2f%%" % percent)
sys.stdout.flush() else:
print("Wrong instructions") def cmd_mkdir(self, cmd):
new_path = ""
if len(cmd.split()) <= 1:
pass
elif len(cmd.split()) == 2:
input_path = cmd.split()[1] if input_path.startswith(self.cwd):
new_path = input_path
else:
new_path = os.path.join(self.cwd, input_path)
print("new_path>>>", new_path)
msg = json.dumps({"cwd": new_path})
self.sock.sendall(("makedirs|{0}".format(msg)).encode("utf-8"))
auth_result = json.loads(self.sock.recv(1024).decode("utf-8"))
if auth_result["result"] == "2003":
print(self.response_code_dict["2003"])
else:
print(self.response_code_dict["2005"]) def cmd_exit(self, cmd):
self.logout_flag = True

2.3 FTPServer端脚本

2.3.1 bin目录下的FTPServer.py模块

import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lib import main if __name__ == '__main__':
main.ArgvHandler(sys.argv)

2.3.2 config目录下的settings.py模块

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
USER_HOME = os.path.join(BASE_DIR, "db", "users")
HOST_IP = "127.0.0.1"
HOST_PORT = 9999
USER_ACCOUNT_DIR = os.path.join(BASE_DIR, "db", "user_account")

2.3.3 lib目录下的main.py模块与ftp_server.py模块

main.py模块

import os, sys

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import socketserver
import ftp_server
from config import settings class ArgvHandler(object):
def __init__(self, sys_argv):
self.args = sys_argv
self.argv_handle() def argv_handle(self):
'''
处理命令行参数,看是否符合输入规范
:return:
'''
if len(self.args) < 2:
self.help_msg()
else:
first_argv = self.args[1] # first_argv = "start"
if hasattr(self, first_argv):
# 通过反射判断现有类的对象是否有start方法
func = getattr(self, first_argv)
# 有则通过反射拿到此方法,并运行此方法
func()
else:
self.help_msg() def help_msg(self):
msg = """
input like below:\n
python FTPServer start
""" def start(self):
"""
创建多线程socket对象,并让该对象一直运行
:return:
"""
try:
print("starting")
tcp_server = socketserver.ThreadingTCPServer((settings.HOST_IP, settings.HOST_PORT,),ftp_server.MyServer)
print("server started")
tcp_server.serve_forever()
except KeyboardInterrupt:
pass

ftp_server.py模块

import os
import sys sys.path.append(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import subprocess
import json
import socketserver
from config import settings class MyServer(socketserver.BaseRequestHandler):
response_code_dict = {
'100': 'user successfully registered',
'101': 'username already existed',
'200': 'Pass authentication!',
'201': 'Wrong username or password!',
'202': 'user does not exist',
'300': 'Ready to send file to client',
'301': 'Client ready to receive file',
'302': "File doesn't exist",
'2002': 'ACK(可以开始上传)',
'2003': 'already existed',
'2004': 'continue put',
"2005": "directory created"
} def handle(self):
while True:
# 死循环,一直接收客户端发过来的消息
data = self.request.recv(1024).decode()
if not data:
# 如果用户发过来的消息是空,则判定用户断开连接
break
data = data.split("|")
func_str = data[0] # 通过反射查看对象有无此属性
if hasattr(self, func_str):
func = getattr(self, func_str)
func(json.loads(data[1]))
else:
print("Invalid instructions") def user_auth(self, name_pwd):
username = name_pwd["username"]
password = name_pwd["password"]
auth_result = {
"username": username,
"password": password,
"storage_size": 0,
"storage_used": 0,
"result": "201",
"user_home": ""
}
with open(settings.USER_ACCOUNT_DIR, "r", encoding="utf-8") as f:
user_info = json.load(f)
if username in user_info.keys():
if password == user_info[username]["password"]:
self.login_user = username
path = os.path.join(settings.USER_HOME, username)
try:
os.makedirs(path)
except OSError:
pass
self.login_user_home = os.path.join(self.login_user) + os.sep
auth_result["user_home"] = self.login_user_home
auth_result["result"] = "200"
auth_result["storage_limit"] = user_info[username]["storage_limit"]
auth_result["storage_used"] = self.getdirsize(path)
else:
auth_result["result"] = "202"
data = json.dumps(auth_result).encode("utf-8")
self.request.sendall(data) def user_register(self, name_pwd):
with open(settings.USER_ACCOUNT_DIR, "r", encoding="utf-8") as f:
user_info = json.load(f)
if name_pwd["username"] in user_info:
self.request.sendall(b"101")
else:
name_pwd["storage_limit"] = 104857600
user_info[name_pwd["username"]] = name_pwd
self.request.sendall(b"100")
with open(settings.USER_ACCOUNT_DIR, "w", encoding="utf-8") as f:
json.dump(user_info, f) def cd(self, dir_str):
new_path = dir_str["cwd"]
# print(new_path)
server_path = settings.USER_HOME + os.sep + new_path
# print(server_path)
auth_result = {"result": "602"}
if os.path.exists(server_path):
auth_result["result"] = "601"
auth_result_json = json.dumps(auth_result)
self.request.sendall(auth_result_json.encode("utf-8")) def ls(self, ins):
dir_str = ins["cwd"]
server_path = os.sep.join([settings.USER_HOME, dir_str])
auth_result = {"result": None}
if os.path.exists(server_path):
path = os.path.join(settings.USER_HOME, server_path)
if sys.platform == "win32":
command = "dir" + " " + path
else:
command = "ls" + " " + path
auth_result["result"] = subprocess.getoutput(command)
msg_size=len(json.dumps(auth_result).encode("utf-8"))
self.request.sendall(str(msg_size).encode("utf-8"))
self.request.recv(1024)
self.request.sendall(json.dumps(auth_result).encode("utf-8")) def put(self, data):
file_size = data["file_size"]
file_name = data["file_name"]
dst_path = data["dst_path"]
file_path = os.path.join(settings.USER_HOME, dst_path, file_name)
# print(file_path)
if os.path.exists(file_path):
file_size2 = os.stat(file_path).st_size
if file_size2 <=file_size:
data["file_size"] = file_size2
data["result"] = "2003" else:
data["result"] = "302"
print(data)
data_json = json.dumps(data)
self.request.sendall(data_json.encode("utf-8"))
client_msg = self.request.recv(1024).decode("utf-8")
has_received = 0
if client_msg == "2004":
has_received += file_size2
with open(file_path, "ab") as f:
self.request.sendall(b"2002")
while has_received < file_size:
data1 = self.request.recv(1024)
f.write(data1)
has_received += len(data1) elif client_msg =="301":
try:
os.makedirs(os.path.dirname(file_path))
except OSError:
pass
with open(file_path, "wb") as f:
self.request.sendall(b"2002")
while has_received < file_size:
data1 = self.request.recv(1024)
f.write(data1)
has_received += len(data1) def get(self, data):
client_path = data["client_path"]
print("client_path>>>",client_path)
file_size = data["file_size"]
data["result"]="2003"
server_path = os.path.join(settings.USER_HOME,client_path)
if os.path.isfile(server_path):
file_size2 = os.stat(server_path).st_size
if not file_size:
data["result"]="300"
data["file_size"] = file_size2
data_json = json.dumps(data).encode("utf-8")
self.request.sendall(data_json)
client_reply = json.loads(self.request.recv(1024).decode("utf-8"))
with open(server_path,"rb") as f :
if client_reply["result"] == "2004":
f.seek(file_size)
for line in f:
self.request.sendall(line) def getdirsize(self, path):
file_size = 0
for root, dirs, files in os.walk(path):
file_size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
return file_size def makedirs(self, data):
path = data["cwd"]
server_path = os.path.join(settings.USER_HOME, path)
print(server_path)
auth_result = {"result": None}
if os.path.exists(server_path):
auth_result["result"] = "2003"
else:
os.makedirs(server_path)
auth_result["result"] = "2005"
msg = json.dumps(auth_result).encode("utf-8")
self.request.sendall(msg)

python day 18: thinking in UML与FTP作业重写的更多相关文章

  1. 十八. Python基础(18)常用模块

    十八. Python基础(18)常用模块 1 ● 常用模块及其用途 collections模块: 一些扩展的数据类型→Counter, deque, defaultdict, namedtuple, ...

  2. python之ftp作业【还未完成】

    作业要求 0.实现用户登陆 1.实现上传和下载 3.每个用户都有自己的家目录,且只可以访问自己的家目录 4.对用户进行磁盘配额,每个用户的空间不同,超过配额不允许下载和上传 5.允许用户在指定的家目录 ...

  3. Python学习笔记——基础篇【第七周】———FTP作业(面向对象编程进阶 & Socket编程基础)

    FTP作业 本节内容: 面向对象高级语法部分 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 参考:http://www.cnblogs.com/wupeiqi/ ...

  4. python day33 ,socketserver多线程传输,ftp作业

    一.一个服务端连多个客户端的方法 1.服务端 import socketserver class MyServer(socketserver.BaseRequestHandler): def hand ...

  5. python全栈开发day29-网络编程之socket常见方法,socketserver模块,ftp作业

    一.昨日内容回顾 1.arp协议含义 2.子网,子网掩码 3.两台电脑在网络中怎么通信的? 4.tcp和udp socket编码 5.tcp和udp协议的区别 6.tcp三次握手和四次挥手,syn洪攻 ...

  6. Python window console 控制台 实现最后一行输出 print 重写

    Python window console 控制台 实现最后一行输出 print 重写 # -*- coding: utf-8-*- from __future__ import print_func ...

  7. python 开发一个支持多用户在线的FTP

    ### 作者介绍:* author:lzl### 博客地址:* http://www.cnblogs.com/lianzhilei/p/5813986.html### 功能实现 作业:开发一个支持多用 ...

  8. python基础——18(面向对象2+异常处理)

    一.组合 自定义类的对象作为另一个类的属性. class Teacher: def __init__(self,name,age): self.name = name self.age = age t ...

  9. Python实现支持并发、断点续传的FTP

    参考网上一个FTP程序,重写了一遍,并稍加扩展 一.要求 1. 支持多用户同时登录 2. 可以注册用户,密码使用md5加密 3. 可以登录已注册用户 4.  支持cd切换目录,ls查看目录子文件 5. ...

随机推荐

  1. 解决vue视图不渲染

    动态添加对象属性 //声明var travelMainVueObj;travelMainVueObj = new Vue({ "el" : "#portletConten ...

  2. qt5 qmake开发

    mkdir hello helloworld.cpp #include <QPushButton> #include <QApplication> int main(int a ...

  3. Unity制作地形的常用插件之GAIA

    用Unity制作大型游戏少了地形制作怎么行,用原生的Unity工具制作地形效率较低而且也不甚美观,后期运行的效率也得不到保证.下面推荐的专业地形制作工具可以帮助开发者解决地形制作的相关问题. 打开Un ...

  4. MySQL索引原理(三)

    多个单列索引和联合索引的区别详解 背景:为了提高数据库效率,建索引是家常便饭:那么当查询条件为2个及以上时,我们是创建多个单列索引还是创建一个联合索引好呢?他们之间的区别是什么?哪个效率高呢?我在这里 ...

  5. Oracle的“ORA-00937: 不是单组分组函数” 如何解决?

    之前在编写oracle的sql语句时遇到这个问题,这里做个记录 问题描述:ORA-00937: 不是单组分组函数 问题原因:select语句中又在查询某一列的值,其中还有聚合函数 原先本人编写SQL是 ...

  6. 面试突击(八)——JVM的结构及内存模型,是怎么划分的?

    声明:本文图片均来自网络,我只是进行了选择,利用一图胜千言的力量来帮助自己快速的回忆相关的知识点 0:再上一张Java代码的转换流程图 .java——Java程序员编写,给人看的 .class——Ja ...

  7. PHP商品秒杀问题解决方案实例详解【mysql与redis】

    本文实例讲述了PHP商品秒杀问题解决方案.分享给大家供大家参考,具体如下: 引言 假设num是存储在数据库中的字段,保存了被秒杀产品的剩余数量. if($num > 0){ //用户抢购成功,记 ...

  8. 两个字符串对比提升比较性能用 StringComparison.OrdinalIgnoreCase

    如果用string.ToLower() 或者 string.ToUpper()字符串在进行大小写转换时会消耗额外的性能 用这个比较性能更好 StringPwd1.Equals(Md5(PassWord ...

  9. Flutter中极光推送的使用----jpush_flutter

    原文地址:https://www.cnblogs.com/niceyoo/p/11095994.html 1.申请极光账号和建立应用 极光推送的官方网址为:https://www.jiguang.cn ...

  10. Srping的IOC

    XML方式: IOC:控制反转的底层原理就是:工厂模式+反射+配置文件DI:依赖注入就是通过配置文件设置属性值 BeanFactory 是老版本的工厂类:调用getBean的时候,才会生成类的实例Ap ...