目录:

  • 涉及知识点
  • Flask框架原理
  • 简单示例
  • 路由系统原理源码分析
  • 请求流程简单源码分析
  • 响应流程简单源码分析
  • session简单源码分析

涉及知识点

1、装饰器

闭包思想

def wapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner """
1. 立即执行wapper函数,并将下面装饰的函数当做参数传递
2. 将wapper函数返回值获取,在index赋值
index = inner函数
"""
@wapper
def index():
print('函数内容') # 实际执行的 inner函数,inner函数内部调用原函数
index()

ps.@functools.wraps,以上我们知道了python实现闭包,实际是index = inner(index)的封装思想。但不可避免的是inner封装后,会对封装的函数隐藏一些信息。如:包装异常,隐藏异常,打印日志,统计函数使用时间等。@functools.wraps通过update_wrapper函数,用参数wrapped表示的函数对象(例如:square)的一些属性(如:__name__、 __doc__)覆盖参数wrapper表示的函数对象(例如:callf,这里callf只是简单地调用square函数,因此可以说callf是 square的一个wrapper function)的这些相应属性。

import functools
def wapper(func):
@functools.wraps(func)
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner @wapper
def index():
print('函数内容') @wapper
def order():
print('函数内容') print(index.__name__)
print(order.__name__)

2、面向对象封装

class Foo(object):
def __init__(self,age,name):
self.age = age
self.name = name class Bar(object):
def __init__(self,counter):
self.counter = counter
self.obj = Foo('','石鹏') b1 = Bar(1)
print(b1.obj.name)

3、python对象什么后面可以加括号

- 函数
- 类
- 方法
- 对象
def f1():
print('f1') class F2(object):
pass class F3(object):
def __init__(self):
pass def ff3(self):
print('ff3') class F4(object):
def __init__(self):
pass def __call__(self, *args, **kwargs):
print('f4') def func(arg):
"""
由于arg在函数中加括号,所以他只有4中表现形式:
- 函数
- 类
- 方法
- 对象
:param arg:
:return:
"""
arg() # 1. 函数,内部执行函数
func(f1)
# 2. 类,内部执行__init__方法
func(F2) # 3. 方法,obj.ff3
obj1 = F3()
func(obj1.ff3) # 4. 对象
obj2 = F4()
func(obj2)

4、call方法

class F4(object):
def __init__(self):
print('构造方法') def __call__(self, *args, **kwargs):
print('f4') def run(self,str1):
print("run:%s" % str1) obj = F4()
obj()
obj.run('sssss')

5、函数和方法的区别

在于调用时有没有实例化对象,即跟某个对象关联。

from types import MethodType,FunctionType

class F3(object):
def __init__(self):
pass def ff3(self):
print('ff3') #
v1 = isinstance(F3.ff3,MethodType) # 方法
v2 = isinstance(F3.ff3,FunctionType) # 函数
print(v1,v2) # False,True obj = F3()
v1 = isinstance(obj.ff3,MethodType) # 方法
v2 = isinstance(obj.ff3,FunctionType) # 函数
print(v1,v2) # True False

Flask框架原理

1、框架本质为通过socket模块实现工作流的请求和响应。

通过socket建立实例,accept等待请求地址,并通过编写路由系统来给予相应的响应。

import socket

def main():
# 创建老师
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8000))
sock.listen(5) while True:
# 老师等待 用户请求的到来
connection, address = sock.accept() # 获取发送的内容:吴亦凡有没有女朋友?
buf = connection.recv(1024) # 根据请求URL的不同:
# 回答:没有
connection.send(b"HTTP/1.1 200 OK\r\n\r\n")
connection.send(b"No No No") # 关闭连接
connection.close() if __name__ == '__main__':
main()

2、flask通过werkzeug模块来帮助我们完成socket性能。

"""
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple @Request.application
def hello(request):
return Response('Hello World!') if __name__ == '__main__':
# 当请求打来之后,自动执行:hello()
run_simple('localhost', 4000, hello)
""" from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple class Foo(object):
def __call__(self, *args, **kwargs):
return Response('Hello World!') if __name__ == '__main__':
# 当请求打来之后,自动执行:hello()
obj = Foo()
run_simple('localhost', 4000, obj)

3、flask快速入门

"""
pip install flask
pip3 install flask
""" from flask import Flask
# 1. 实例化Flask对象
app = Flask('xxxx') """
1. 执行 app.route('/index')并获取返回值 xx
2.
@xx
def index():
return 'Hello World'
3. 执行 index = xx(index)
本质:
{
'/index': index
}
"""
@app.route('/index')
def index():
return 'Hello World' if __name__ == '__main__':
app.run()

简单示例

1、实现简单登陆

import functools
from flask import Flask,render_template,request,redirect,session app = Flask('xxxx',template_folder="templates")
app.secret_key = 'as923lrjks9d8fwlkxlduf' def auth(func):
@functools.wraps(func)
def inner(*args,**kwargs):
user_info = session.get('user_info')
if not user_info:
return redirect('/login')
return func(*args,**kwargs)
return inner """
{
/order: inner函数, name: order
/index: inner函数, name: index
}
""" @app.route('/order',methods=['GET'])
@auth
def order():
user_info = session.get('user_info')
if not user_info:
return redirect('/login') return render_template('index.html') @app.route('/index',methods=['GET'])
@auth
def index():
return render_template('index.html') @app.route('/login',methods=['GET','POST'])
def login():
if request.method == "GET":
return render_template('login.html')
else:
user = request.form.get('user')
pwd = request.form.get('pwd')
if user == 'alex' and pwd == '':
session['user_info'] = user
return redirect('/index')
# return render_template('login.html',msg = "用户名或密码错误",x = 123)
return render_template('login.html',**{'msg':'用户名或密码错误'}) @app.route('/logout',methods=['GET'])
def logout():
del session['user_info']
return redirect('/login') if __name__ == '__main__':
app.run()

app.py

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录页面</h1>
<form method="post">
<input type="text" name="user">
<input type="password" name="pwd">
<input type="submit" value="提交">{{msg}}
</form>
</body>
</html>

templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>欢迎进入系统</h1>
<img src="/static/111.png" alt="">
</body>
</html>

templates/index.html

2、flask配置文件

import functools
from flask import Flask # 配置:模板/静态文件
app = Flask('xxxx',template_folder="templates")
# 配置:secret_key
app.secret_key = 'as923lrjks9d8fwlkxlduf' # 导入配置文件
app.config.from_object('settings.TestingConfig') @app.route('/index')
def index():
return "index" if __name__ == '__main__':
app.run()
class BaseConfig(object):
DEBUG = False
SESSION_REFRESH_EACH_REQUEST = True class ProConfig(BaseConfig):
pass class DevConfig(BaseConfig):
DEBUG = True class TestingConfig(BaseConfig):
DEBUG = True

settings.py

ps.import importlib模块,模块支持传递字符串来导入模块。我们先来创建一些简单模块一遍演示。我们在模块里提供了相同接口,通过打印它们自身名字来区分。可通过importlib.import_module(module_path)来动态导入。其等价于import module_path。

路由系统原理源码分析

1、总体流程:

1.初始化Flask类,Rule类,Map类

2.调用app.route方法

3.route方法调用add_url_rule方法

4. add_url_rule方法rule = self.url_rule_class调用Rule方法,封装url和试图函数

5.add_url_rule方法调用url_map.add(Rule)对路由的rules进行添加[Rule('/index', 函数),]

6.map类存到self.url_map中,Rule存在url_rule_class中

import functools
from flask import Flask,views # 配置:模板/静态文件
app = Flask('xxxx',template_folder="templates")
"""
{
'/index': index函数
} 1. decorator = app.route('/index')
2.
@decorator
def index():
return "index"
3. decorator(index)
""" """
Map() = [
Rule(rule=/index/ endpoint=None view_func=函数),
]
"""
@app.route('/index')
def index():
return "index" """
Map() = [
Rule(rule=/index endpoint=None view_func=函数),
Rule(rule=/order endpoint=None view_func=order),
]
"""
def order():
return 'Order'
app.add_url_rule('/order', None, order) class TestView(views.View):
methods = ['GET']
def dispatch_request(self):
return 'test!' app.add_url_rule('/test', view_func=TestView.as_view(name='test')) # name=endpoint
# app.add_url_rule('/test', view_func=view函数) # name=endpoint def auth(func):
def inner(*args, **kwargs):
print('before')
result = func(*args, **kwargs)
print('after')
return result
return inner class X1View(views.MethodView):
methods = ['GET','POST']
decorators = [auth, ] def get(self):
return 'x1.GET' def post(self):
return 'x1.POST' app.add_url_rule('/x1', view_func=X1View.as_view(name='x1')) # name=endpoint if __name__ == '__main__':
app.run()

2、初始化Flask类,Rule类,Map类

#--------------------------------------
# Flask类
class Flask(_PackageBoundObject):
url_rule_class = Rule
def __init__(self, import_name, static_path=None, static_url_path=None,
static_folder='static', template_folder='templates',
instance_path=None, instance_relative_config=False,
root_path=None)
self.url_map = Map() #--------------------------------------
# Role类
@implements_to_string
class Rule(RuleFactory):
def __init__(self, string, defaults=None, subdomain=None, methods=None,
build_only=False, endpoint=None, strict_slashes=None,
redirect_to=None, alias=False, host=None):
if not string.startswith('/'):
raise ValueError('urls must start with a leading slash')
self.rule = string
self.is_leaf = not string.endswith('/') self.map = None
self.strict_slashes = strict_slashes
self.subdomain = subdomain
self.host = host
self.defaults = defaults
self.build_only = build_only
self.alias = alias
if methods is None:
self.methods = None
else:
if isinstance(methods, str):
raise TypeError('param `methods` should be `Iterable[str]`, not `str`')
self.methods = set([x.upper() for x in methods])
if 'HEAD' not in self.methods and 'GET' in self.methods:
self.methods.add('HEAD')
self.endpoint = endpoint
self.redirect_to = redirect_to if defaults:
self.arguments = set(map(str, defaults))
else:
self.arguments = set()
self._trace = self._converters = self._regex = self._weights = None #-------------------
#map类
class Map(object):
default_converters = ImmutableDict(DEFAULT_CONVERTERS) def __init__(self, rules=None, default_subdomain='', charset='utf-8',
strict_slashes=True, redirect_defaults=True,
converters=None, sort_parameters=False, sort_key=None,
encoding_errors='replace', host_matching=False):
self._rules = []
self._rules_by_endpoint = {}
self._remap = True
self._remap_lock = Lock() self.default_subdomain = default_subdomain
self.charset = charset
self.encoding_errors = encoding_errors
self.strict_slashes = strict_slashes
self.redirect_defaults = redirect_defaults
self.host_matching = host_matching self.converters = self.default_converters.copy()
if converters:
self.converters.update(converters) self.sort_parameters = sort_parameters
self.sort_key = sort_key for rulefactory in rules or ():
self.add(rulefactory)

3、调用app.route方法

def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator

4、route方法调用add_url_rule方法

@setupmethod
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options['endpoint'] = endpoint
methods = options.pop('methods', None) # if the methods are not given and the view_func object knows its
# methods we can use that instead. If neither exists, we go with
# a tuple of only ``GET`` as default.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
if isinstance(methods, string_types):
raise TypeError('Allowed methods have to be iterables of strings, '
'for example: @app.route(..., methods=["POST"])')
methods = set(item.upper() for item in methods) # Methods that should always be added
required_methods = set(getattr(view_func, 'required_methods', ())) # starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling.
provide_automatic_options = getattr(view_func,
'provide_automatic_options', None) if provide_automatic_options is None:
if 'OPTIONS' not in methods:
provide_automatic_options = True
required_methods.add('OPTIONS')
else:
provide_automatic_options = False # Add the required methods now.
methods |= required_methods rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options self.url_map.add(rule)

5、 add_url_rule方法rule = self.url_rule_class调用Rule方法,封装url和试图函数

add_url_rule,代码同4 ;通过url_rule_class = Rule实例化,代码同2

6、add_url_rule方法调用url_map.add(Rule)对路由的rules进行添加[Rule('/index', 函数),]

add_url_rule代码同4,调用url_map.add方法

    def add(self, rulefactory):
"""Add a new rule or factory to the map and bind it. Requires that the
rule is not bound to another map. :param rulefactory: a :class:`Rule` or :class:`RuleFactory`
"""
for rule in rulefactory.get_rules(self):
rule.bind(self)
self._rules.append(rule)
self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule)
self._remap = True

7.map类存到self.url_map中,Rule存在url_rule_class中。

同代码2.

请求流程简单源码分析

1、综述:

1.已生成路由后,由app.run执行run方法

2.run方法通过werkzeug模块执行run_simple方法

3.werkzeug模块会触发__call__方法

4.__call__方法会触发wsgi_app

5.ctx=request_context对象,触发request_context对象

6.request_context对象__init__进行实例化

--request = app.request_class(environ)

7.flask初始化通过request实例化调用Request对象,通过request实例化调用Request对象

8.Request对象通过werkzeug模块__init__进行实例化

9.存储到ctx中

10.ctx.push()调用RequestContest.push方法

2、__call__方法会触发wsgi_app

    def __call__(self, environ, start_response):
"""Shortcut for :attr:`wsgi_app`."""
return self.wsgi_app(environ, start_response)

3、ctx=request_context对象,触发request_context对象

def wsgi_app(self, environ, start_response):
ctx = self.request_context(environ)
ctx.push()

4、request_context对象__init__进行实例化

def request_context(self, environ):
return RequestContext(self, environ)

--request = app.request_class(environ)

    def __init__(self, app, environ, request=None):
self.app = app
if request is None:
request = app.request_class(environ)
self.request = request
self.url_adapter = app.create_url_adapter(self.request)
self.flashes = None
self.session = None # Request contexts can be pushed multiple times and interleaved with
# other request contexts. Now only if the last level is popped we
# get rid of them. Additionally if an application context is missing
# one is created implicitly so for each level we add this information
self._implicit_app_ctx_stack = [] # indicator if the context was preserved. Next time another context
# is pushed the preserved context is popped.
self.preserved = False # remembers the exception for pop if there is one in case the context
# preservation kicks in.
self._preserved_exc = None # Functions that should be executed after the request on the response
# object. These will be called before the regular "after_request"
# functions.
self._after_request_functions = [] self.match_request()

5、flask初始化通过request实例化调用Request对象,通过request实例化调用Request对象

class Flask(_PackageBoundObject):
  request_class = Request

6、Request对象通过werkzeug模块__init__进行实例化

class Request(RequestBase):
#: The internal URL rule that matched the request. This can be
#: useful to inspect which methods are allowed for the URL from
#: a before/after handler (``request.url_rule.methods``) etc.
#:
#: .. versionadded:: 0.6
url_rule = None #: A dict of view arguments that matched the request. If an exception
#: happened when matching, this will be ``None``.
view_args = None #: If matching the URL failed, this is the exception that will be
#: raised / was raised as part of the request handling. This is
#: usually a :exc:`~werkzeug.exceptions.NotFound` exception or
#: something similar.
routing_exception = None # Switched by the request context until 1.0 to opt in deprecated
# module functionality.
_is_old_module = False

7、.存储到ctx中

同3代码

8、ctx.push()调用RequestContest.push方法

同3代码

flask的sesstion流程

1、综述

1.RequestContext.push,调用app.open_sesstion

2.self.session调用app.open_session

3.通过session_interface变量调用到secureCookieSeeionInerface类的open_session

4.如果没有,则session_class = SecureCookieSession,open_session经过loads加密返回self.session_class(),

5.将加密session返回到self.session

6.执行视图函数

response = self.full_dispatch_request()
----调用try_trigger_before_first_request_functions
(before_first_request)
----调用preprocess_request(before_request)
----调用dispatch_request(执行试图函数)
----调用finalize_request(@fater_request)

7.finalize_request

----response = self.process_response(response)

8.process_response

----执行@fater_request函数
----self.save_session(ctx.session, response)

9.通过self.save_session调用save_session并返回SecureCookieSessionInterface.save_session(self, session, response)

10.save_session保存session,报错return null

2、RequestContext.push,调用app.open_sesstion

def wsgi_app(self, environ, start_response):
ctx = self.request_context(environ)
ctx.push()
error = None
try:
try:
# 4 执行视图函数
response = self.full_dispatch_request()
except Exception as e:
# 异常处理试图报错,包含信号2345报错执行,got_request_exception信号
error = e
response = self.handle_exception(e)
except:
error = sys.exc_info()[1]
raise
# 将处理的内容,返回给用户浏览器
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None # 9、结束
ctx.auto_pop(error)

通过self.session = self.app.open_session(self.request)调用flask.open_session方法

def open_session(self, request):
return self.session_interface.open_session(self, request)

3、self.session调用app.open_session

class RequestContext(object):
  def push(self):
  self.session = self.app.open_session(self.request)
  if self.session is None:
  self.session = self.app.make_null_session()

4、通过session_interface变量调用到secureCookieSeeionInerface类的open_session

class Flask(_PackageBoundObject):
session_interface = SecureCookieSessionInterface()

5、如果没有,则session_class = SecureCookieSession,open_session经过loads加密返回self.session_class(),

class SecureCookieSessionInterface(SessionInterface):
"""The default session interface that stores sessions in signed cookies
through the :mod:`itsdangerous` module.
"""
#: the salt that should be applied on top of the secret key for the
#: signing of cookie based sessions.
salt = 'cookie-session'
#: the hash function to use for the signature. The default is sha1
digest_method = staticmethod(hashlib.sha1)
#: the name of the itsdangerous supported key derivation. The default
#: is hmac.
key_derivation = 'hmac'
#: A python serializer for the payload. The default is a compact
#: JSON derived serializer with support for some extra Python types
#: such as datetime objects or tuples.
serializer = session_json_serializer
session_class = SecureCookieSession
  
  
  def open_session(self, app, request):
  # sission,key值
  s = self.get_signing_serializer(app)
  if s is None:
  return None
  # 如果能从cookie拿到session的话
  val = request.cookies.get(app.session_cookie_name)
  if not val:
  return self.session_class() #如果没有session,则返回一个空字典
  max_age = total_seconds(app.permanent_session_lifetime)
  try:
  data = s.loads(val, max_age=max_age) # 加密保存
  return self.session_class(data)
  except BadSignature:
  return self.session_class() # 返回session类

6、将加密session返回到self.session


class RequestContext(object):
  def push(self):
  self.session = self.app.open_session(self.request)
  if self.session is None:
  self.session = self.app.make_null_session()

7、执行视图函数

response = self.full_dispatch_request()

同代码2
----调用try_trigger_before_first_request_functions
(before_first_request)

    def full_dispatch_request(self):
"""Dispatches the request and on top of that performs request
pre and postprocessing as well as HTTP exception catching and
error handling. .. versionadded:: 0.7
"""
# 触发只执行一次的装饰器函数,@before_first_request
self.try_trigger_before_first_request_functions()

----调用preprocess_request(before_request)

----调用dispatch_request(执行试图函数)
----调用finalize_request(@fater_request)

def full_dispatch_request(self):
try:
# 执行特殊装饰器:before_request装饰的所有函数
# 如果没有返回值,rv=None;有返回值 “嘻嘻嘻”
rv = self.preprocess_request()
if rv is None:
# 触发执行视图函数,使用session
rv = self.dispatch_request()
except Exception as e:
rv = self.handle_user_exception(e)
# 6 对返回值进行封装,执行@fater_request装饰器;session保存
return self.finalize_request(rv)

8、finalize_request

----response = self.process_response(response)

 def finalize_request(self, rv, from_error_handler=False):
''' 创建返视图返回'''
response = self.make_response(rv)
try:
'''返回值'''
response = self.process_response(response)
# 执行信号request_finished
request_finished.send(self, response=response)
except Exception:
if not from_error_handler:
raise
self.logger.exception('Request finalizing failed with an '
'error while handling an error')
return response

9、process_response

----执行@fater_request函数
----self.save_session(ctx.session, response)

def process_response(self, response):
ctx = _request_ctx_stack.top
bp = ctx.request.blueprint
funcs = ctx._after_request_functions
if bp is not None and bp in self.after_request_funcs:
funcs = chain(funcs, reversed(self.after_request_funcs[bp]))
if None in self.after_request_funcs:
funcs = chain(funcs, reversed(self.after_request_funcs[None]))
# 执行 after_request装饰器
for handler in funcs:
response = handler(response)
# 将内存中的session持久化到:数据库、....
if not self.session_interface.is_null_session(ctx.session):
self.save_session(ctx.session, response)
return response

10、通过self.save_session调用save_session并返回SecureCookieSessionInterface.save_session(self, session, response)

# Flask类
def save_session(self, session, response):
return self.session_interface.save_session(self, session, response)

11、save_session保存session,报错return null

SecureCookieSessionInterface类:
def save_session(self, app, session, response):
domain = self.get_cookie_domain(app) # 域名
path = self.get_cookie_path(app) # 路径 # Delete case. If there is no session we bail early.
# If the session was modified to be empty we remove the
# whole cookie.
if not session:
if session.modified:
response.delete_cookie(app.session_cookie_name,
domain=domain, path=path)
return # Modification case. There are upsides and downsides to
# emitting a set-cookie header each request. The behavior
# is controlled by the :meth:`should_set_cookie` method
# which performs a quick check to figure out if the cookie
# should be set or not. This is controlled by the
# SESSION_REFRESH_EACH_REQUEST config flag as well as
# the permanent flag on the session itself.
if not self.should_set_cookie(app, session):
return httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
expires = self.get_expiration_time(app, session)
val = self.get_signing_serializer(app).dumps(dict(session)) # 加密
response.set_cookie(app.session_cookie_name, val, # 最后保存在cookie中
expires=expires, httponly=httponly,
domain=domain, path=path, secure=secure)

附录

Flask系列之源码分析(一)的更多相关文章

  1. Flask系列之源码分析(二)

    应用技术点 python之__setattr__ python之threading.local python之偏函数 flask源码上下文管理 1.综述过程 将请求对象压入栈 1.请求进入 __cal ...

  2. Spring基础系列-AOP源码分析

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9560803.html 一.概述 Spring的两大特性:IOC和AOP. AOP是面向切 ...

  3. flask/app.py-add_url_rule源码分析

    之前分析route方法的时候,可以看到中间会调用add_url_rule方法,add_url_rule方法和route方法一样属于Flask这个类的. add_url_rule方法主要用来连接url规 ...

  4. Tomcat详解系列(3) - 源码分析准备和分析入口

    Tomcat - 源码分析准备和分析入口 上文我们介绍了Tomcat的架构设计,接下来我们便可以下载源码以及寻找源码入口了.@pdai 源代码下载和编译 首先是去官网下载Tomcat的源代码和二进制安 ...

  5. Flask之wtforms源码分析

    一.wtforms源码流程 1.实例化流程分析 # 源码流程 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._ ...

  6. Kafka源码系列之源码分析zookeeper在kafka的作用

    浪尖的kafka源码系列以kafka0.8.2.2源码为例给大家进行讲解的.纯属个人爱好,希望大家对不足之处批评指正. 一,zookeeper在分布式集群的作用 1,数据发布与订阅(配置中心) 发布与 ...

  7. Android进阶系列之源码分析Activity的启动流程

    美女镇楼,辟邪! 源码,是一个程序猿前进路上一个大的而又不得不去翻越障碍,我讨厌源码,看着一大堆.5000多行,要看完得啥时候去了啊.不过做安卓的总有这一天,自从踏上这条不归路,我就认命了.好吧,我慢 ...

  8. flask请求上下文源码分析

    一.什么是上下文 每一段程序都有很多外部变量,只有像add这种简单的函数才是没有外部变量的,一旦你的一段程序有了外部变量,这段程序就不完整了,不能独立运行,你为了使他们能运行,就要给所有的外部变量一个 ...

  9. Spring IOC 容器源码分析系列文章导读

    1. 简介 Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本.经过十几年的迭代,现在的 Spring 框架已经非常成熟了.Spring ...

随机推荐

  1. linux mint 19解决 输入法问题

    安装搜狗后出现 You're currently running Fcitx with GUI, but fcitx-configtool couldn't be found, the package ...

  2. kendo-ui的使用和开发自己的组件

    摘要: 前面介绍了一款非常不错的前端框架kendo-ui,如果你想阅读,请点这里.通过使用它一段时间,感觉是非常好用.下面就介绍一下如何使用它和开发自己的组件 引入: 只需要引进下面三个文件即可 ke ...

  3. day26<网络编程>

    网络编程(网络编程概述) 网络编程(网络编程三要素之IP概述) 网络编程(网络编程三要素之端口号概述) 网络编程(网络编程三要素协议) 网络编程(Socket通信原理图解) 网络编程(UDP传输) 网 ...

  4. ubuntu下code::blocks设置运行窗口为gnome命令行

    code::blocks编译运行C++程序(F9)默认出现的运行串口在有鼠标的情况下进行粘贴还是很方便的,只要按下鼠标滑轮,位与剪切板中的数据就能粘贴到运行串口中.但是对于用笔记本而且没有鼠标地童鞋这 ...

  5. Android 7.1 SystemUI--Multi-Window多窗口模式

    PhoneStatusBar.java private View.OnLongClickListener mRecentsLongClickListener = new View.OnLongClic ...

  6. 转移wordpress到另一台主机

    做项目的代码是两个人,我想把另一个小伙伴做的转移到自己的linux系统上(主要是linux下一片空白,从头做太浪费时间了) 这个过程其实也可以用来类比从本地到服务器的过程(可能略有不同,真上线的时候会 ...

  7. html表格中的tr td th用法

      表格是html中经常使用到的,简单的使用可能很多人都没问题,但是更深入的了解的人恐怕不多,下面我们先来看一下如何使用. <table>是<tr>的上层标签 <tr&g ...

  8. all index range ref eq_ref const system 索引type说明

    背景知识 在使用sql的过程中经常需要建立索引,而每种索引是怎么处罚的又是怎么起到作用的,首先必须知道索引和索引的类型. 索引类型type 我们可以清楚的看到type那一栏有index ALL eq_ ...

  9. java获取年份的第一天和最后一天

    Calendar cal = Calendar.getInstance();cal.set(Calendar.MONTH, 0);cal.set(Calendar.DATE, 1);String da ...

  10. 问答项目---金币经验奖励规则及网站配置写入config文件

    具体步骤: 引入配置文件——>获取当前数组——>进行合并 public function edit(){ //引入 config.php配置文件 $file = APP_PATH.'Com ...