Flask是一个简洁的 Python_web 框架.

零. virtualenv 虚拟环境配置.

$ easy_install pip
$ pip install virtualenv
$ virtualenv venv        # 创建名称为 venv 的虚拟环境
$ source venv/bin/active     # 进入 venv 虚拟环境
(venv) $ pip install flask   # 在虚拟环境中安装 flask 包
(venv) $ deactivate          # 从虚拟环境退出

一. 基本配置

1. 创建并启动程序实例

示例 :

from flask import Flask
app = Flask(__name__)       # Flask 类的构造函数只有一个必须制定的参数, 即程序主模块或包的名字. 

# route here

if __name__ == "__main__":      # 程序启动后进入轮训, 等待并处理请求.
    app.run(debug=True)         # 启动服务器,并启用调试模式, 激活调试器和重载程序.

2. 配置

app.config 字典用来存储框架, 扩展和程序本身的配置变量. 使用标准的字典语法就可把配置值添加到 app.config 对象中.

示例代码 :

from flask import Flask
app = Flask(app)
app.config["SECRET_KEY"] = "hard to guess string"

该对象还提供了一些其他方法, 可以从文件或环境中导入配置值.

3. 路由 = 装饰器 + 视图函数.

处理URL 和 视图函数 之间映射关系的程序成为路由.

1.生成路由映射

1. app.route 装饰器
    最简单方式是使用 app.route 装饰器.

    示例代码 : 

        @app.route("/", methods=["GET", "POST"])    # methods 为请求方法.
        def index():             # 视图函数.
            return "<h1>Hello World</h1>"

        @app.route("/user/<name>")      # 尖括号中的就是动态内容, 任何能匹配静态部分的 URL 都会映射到这个路由上. 调用视图函数时, Flaks 会将动态部分作为参数传入函数.
        def user(name):
            return "<h1>Hello , %s</h1>" % name

    动态视图函数类型定义 : 

        int : 匹配动态片id 为整数的 URL. `/user/<ind:id>`
        float : 浮点数
        path : path 类型也是字符串, 但不把斜线视作分隔符, 而将其视为动态片段的一部分. `/user/<path:dir_path>`        

2. app.add_url_role()

3. app.errorhandler() 错误页面

    示例代码 : 

        @app.errorhandler(404)
        def page_not_found(e):
            return render_template('404.html'), 404

        @app.errorhandler(500)
        def internal_server_error(e):
            return render_template('500.html'), 500

2.查看路由映射

>> from hello import app
>> app.url_map
    Map([<Rule '/' (HEAD, POST, OPTIONS, GET) -> main.index>,
     <Rule '/static/bootstrap/<filename>' (HEAD, OPTIONS, GET) -> bootstrap.static>,
     <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])    

二. 请求-响应模型.

HTTP 协议的基本模型即 请求 <---> 响应.

1. 上下文

Flask 使用上下文, 让特定的变量在一个线程中全局可访问, 而不会干扰其他线程.

Flask 中的上下文包含 程序上下文请求上下文 .

Flask 在分发请求之前激活(或推送)程序和请求上下文, 请求处理完成后将其删除.

程序上下文本推送后, 就可以在线程中使用 current_app 和 g 变量. 请求上下文本推送后, 就可以使用 request 和 session 变量.

如果使用这些变量时, 没有激活程序上下文或请求上下文, 就会导致错误.

很多 Flask 扩展都假设已经存在激活的程序上下文和请求上下文, 所以 使用不同线程执行 Flask 扩展时, 需要手动激活上下文.

1. 程序上下文

变量名称 上下文 说明
current_app 程序上下文 当前激活程序的程序实例
g 程序上下文 处理请求时做临时存储的对象. 每次请求都会重设这个变量

2. 请求上下文

变量名称 上下文 说明
request 请求上下文 请求对象, 封装了客户端发出的 HTTP 请求中的内容
session 请求上下文 用户会话, 用于存储请求之间需要 "记住" 的值的字典

示例 : 在视图函数中使用上下文

from flask import request

@app.route('/')
def index():
    user_agent = request.headers.get("User-Agent")
    return "<p>Your browser is  %s</p>" % user_agent

示例 : 在 shell 中使用上下文(手动推送上下文).

>> from hello import app  # hello 为程序主文件
>> from flask import current_app
>> current_app.name                 # 未激活程序上下文就调用 current_app 导致错误.
    Traceback (most recent call last):
    ...
    RuntimeError : working outside of application context.
>> app_ctx = app.app_context()      # 获取程序上下文
>> app_ctx.push()                   # 推送上下文
>> current_app.name
    "hello"

2. 请求钩子(注册通用函数)

Flask 提供了注册通用函数的功能, 注册的函数可在请求被分发到视图函数之前或之后调用.

请求钩子函数 说明
before_first_request 注册一个函数, 在处理第一个请求之前运行.
before_request 注册一个函数, 在每次请求之前运行.
after_request 注册一个函数, 如果没有未处理的异常抛出, 在每次请求之后运行.
teardown_request 注册一个函数, 即使有未处理的异常抛出, 在每次请求之后运行.

在请求钩子函数和视图函数之间共享数据, 一般使用上下文全局变量 g .

before_request 钩子在应用到蓝本时, 只能对应到针对蓝本的请求上; 如想在蓝本中使用针对程序全局请求的钩子, 必须使用 before_app_request .

示例代码 :

@auth.before_app_request
def before_request():
    if current_user.is_authenticated() and not current_user.confirmed and \
                    request.endpoint[:5] != 'auth.' and \
                    request.endpoint != 'static':
        return redirect(url_for("auth.unconfirmed"))

3. 响应 : 响应内容, 响应码, 响应首部.

Flask 返回响应有 4 种方式:

  1. return : 在视图函数中返回响应.

    return "响应内容或模板", 响应码, {响应首部字典}

  2. Response 对象 : flaks.make_response()

    make_response() 函数接受 1个, 2个, 或 3个参数, 并返回一个 Response 对象.

    示例代码 :

    from flask import make_response
    
    @app.route("/")
    def index():
        response = make_response("<p>This Document carries a cookie !</p>")
        response.set_cookie("answer", "42")
        return response
  3. 重定向 .

    重定向是一种特殊的响应类型, 这种响应没有页面文档, 只会告诉浏览器一个新地址, 浏览器在得到新地址之后, 自动重新请求加载新地址.

    重定向可以使用 3个 值形式的返回值生成, 可在 Response 对象中设定. 但是 Flask 提供了 redirect() 辅助函数, 用于生成这种响应.

    示例代码 :

    from flask import redirect
    
    @app.route("/")
    def index():
        return redirect("http://www.example.com")
  4. abort() :

    abort() 处理错误.

    示例代码 :

    from flask import abort
    
    @app.route("/user/<id>")
    def get_user(id):
        user = load_user(id)
        if not user:
            abort(404)
        return "<h1>Hello , %s !</h1>" % user.name

    注意 : abort 不会把控制权交给调用它的函数, 而是抛出异常把控制权交给 web 服务器.

三. 大型程序组织结构

Flaks 并不强制要求大型项目使用特定的组织方式, 程序的结构组织方式完全有开发者自己决定.

1. 项目结构示例

├── app
│   ├── __init__.py
│   ├── email.py
│   ├── models.py
│   ├── main /
│   │   ├── __init__.py
│   │   ├── errors.py
│   │   ├── forms.py
│   │   ├── views.py
│   ├── static /
│   └── templates /
├── config.py
├── manage.py
├── venv /
├── migrations /
├── requirements.txt
└── tests /
    ├── __init__.py
    ├── test_*.py

文件夹类 :
    app : Flask 程序
    migrations : 数据库迁移脚本
    tests : 单元测试脚本
    venv : 虚拟环境

文件类 :
    requirements.txt : 程序依赖包
    config.py  : 存储配置
    manage.py : 启动脚本及程序任务.

2. 配置选项 : 层次的配置类.

import os
basedir = os.path.abspath(os.path.dirname(__file__))

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard to guess string'
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True

    FLASKY_MAIL_SUBJECT_PREFIX = '[Flasky]'
    FLASKY_MAIL_SENDER = 'Flasky Admin <flasky@example.com>'
    FLASKY_ADMIN = os.environ.get('FLASKY_ADMIN')

    @staticmethod
    def init_app(app):
        pass

class DevelopmentConfig(Config):
    DEBUG = True

    MAIL_SERVER = 'smtp.googlemail.com'
    MAIL_PORT = 587
    MAIL_USE_TLS = True
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
    MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')

    SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')

class TestingConfig(Config):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'data-test.sqlite')

class ProductionConfig(Config):
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'data.sqlite')

config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,

    'default': DevelopmentConfig
}

基类 Config 中包含通用配置, 子类分别定义专用的配置. 如果需要还可以添加其他的配置类.

配置类可以定义 init_app() 类方法, 其参数是程序实例. 在这个方法中, 可以执行对当前环境的配置初始化. 现在 , 基类 Confifg 中的 init_app() 方法为空.

config 字典中注册了不同的配置环境, 而且还注册了一个默认配置(开发环境).

3. 程序包

程序包用来保存程序的所有代码,模板和静态文件.

1) 程序工厂函数

在单个文件中开发程序很方便, 但却有个很大的缺点, 因为程序在全局作用域中创建, 所以无法动态修改配置. 运行脚本时, 程序实例已经创建完毕, 再修改配置为时已晚. 这一点对单元测试尤其重要, 因为有事为了提高测试覆盖度, 必须在不同的配置环境中运行程序.

解决办法就是 : 延迟创建程序实例, 把创建过程移到可现实调用的工厂函数中. 这种方法不仅可以给脚本流出配置程序的时间, 还能够创建多个程序实例, 这些实例有时在测试中非常有用.

构造文件示例 :

# app/__init__.py

from flask import Flask
from flask_bootstrap import Bootstrap
from flask_moment import Moment
from flask_mail import Mail
from flask_sqlalchemy import SQLAlchemy

from config import config

bootstrap = Bootstrap()
mail = Mail()
moment = Moment()
db = SQLAlchemy()

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)

    bootstrap.init_app(app)
    mail.init_app(app)
    moment.init_app(app)
    db.init_app(app)

    # 附加路由和自定义的错误页面

    return app

构造文件导入了大多数正在使用的 Flask 扩展. 由于尚未初始化所需的程序实例, 所以没有初始化扩展, 创建扩展类时, 没有向构造函数传入参数.

create_app() 函数就是程序的工厂函数, 接受一个 参数, 就是程序使用的配置名称. 配置类在 config.py 文件中定义, 其中保存的配置可以使用 Flaks app.config 配置对象提供的 from_object() 方法直接导入程序. 至于配置对象, 则可以通过名字从 config 字典中选择. 程序创建并配置好后, 就能初始化扩展了. 在之前创建的扩展对象上调用 init_app() 可以完成初始化过程.

工厂函数返回创建的程序示例, 不过,现在工厂函数创建的程序还不完整, 因为没有路由和自定义的错误页面处理程序.

2) 蓝本

转换成程序工厂函数的操作让定义路由变复杂了. 在当脚本程序中, 程序实例存在于全局作用域中, 路由可以直接使用 app.route 装饰器定义. 但现在程序在运行时创建, 只有调用 create_app() 之后才能使用 app.route 装饰器, 这是定义路由就太晚了. 错误页面处理程序使用 app.errorhandler 装饰器, 也面临同样的困难.

解决方法 : 蓝本

  1. 创建蓝本

    蓝本中可以定义路由, 不同的是, 在蓝本中定义的路由处于休眠状态, 直到蓝本注册到程序上后, 路由才真正成为程序的一部分. 使用位于全局作用域中的蓝本时, 定义路由的方法几乎和单脚本程序一样.

    蓝本可以在单个文件中定义, 也可使用更结构化的方式在包中的多个模块中创建.

    为了获取更大的灵活性, 程序包中创建了一个子包, 用于保存蓝本.

    示例 :

    # app/main/__init__.py
    
    from flask import Blueprint     
    
    main = Blueprint('main', __name__)    # 通过实例化一个 Blueprint 类对象创建蓝本, 该构造函数必须制定两个参数 : 蓝本名称 , 蓝本所在的包或模块(__name__即可).
    
    from . import views, errors     # views 模块保存程序路由, errors 模块保存页面错误处理程序. 导入这两个模块,可以路由和错误处理程序与蓝本关联起来.
    
    ** views 和 errors 在 __init__.py 脚本的末尾导入, 是为了避免循环导入依赖 ,因为在 两个模块中, 还有导入 蓝本 main.
  2. 注册蓝本

    蓝本在 工厂函数 create_app() 中注册到程序上.

    示例 :

    # app/__init__.py
    
    #...
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)
    
    from .auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint, url_prefix="/auth")         # url_prefix 使得蓝本中定义的路由都会加上指定前缀.
    
    return app
  3. 蓝本中的错误处理程序

    在蓝本中编写错误处理程序, 如果使用 errorhandler 装饰器, 那么只有蓝本中的错误才能触发处理程序; 要想注册程序全局的错误处理程序, 必须使用 app_errorhandler .

    示例 :

    # app/main/errors.py
    
    from flask import render_template
    from . import main
    
    @main.app_errorhandler(404)
    def page_not_fount(e):
        return render_template('404.html'), 404
    
    @main.app_errorhandler(500)
    def page_not_fount(e):
        return render_template('500.html'), 500
  4. 蓝本中的路由程序

    蓝本中的视图函数,与单脚本中的视图函数有两点不同:

    • 路由装饰器由蓝本提供.
    • url_for() 的用法不同. 需要加上蓝本的名字. 如下 :
      url_for('main.index') # 全局通用
      url_for('.index') # 简写形式, 只在当前蓝本中使用.

    flask 为蓝本中的全部断点加上了一个命名空间, 这样在不同蓝本中使用相同的端点名称定义视图函数, 就不会产生冲突了. 命令空间的名称就是蓝本的名称. 这也是 url_for() 写法不同的原因.

    示例 :

    # app/main/views.pys
    
    from datetime import datetime
    
    from flask import render_template, session, redirect, url_for
    
    from . import main
    from .forms import NameForm
    from .. import db
    from ..models import User
    
    @main.route("/", methods=["GET", "POST"])
    def index():
        form = NameForm()
    
        if form.validate_on_submit():
            # ...
            return redirect(url_for(".index"))
        return render_template("index.html",
                               current_time=datetime.utcnow(),
                               form=form,
                               name=session.get("name"),
                               known=session.get("known"))

4. 启动脚本

顶级文件夹中的 manage.py 用于启动程序.

示例 :

# manage.py

import os
from app import create_app, db
from app.models import User, Role
from flask_script import Manager, Shell
from flask_migrate import Migrate, MigrateCommand

app = create_app(os.getenv("FLASK_CONFIG" or "default"))    # 创建程序.
manager = Manager(app)      # 初始化 Flask-Script
migrate = Migrate(app, db)  # 初始化 Flask-Migrate

def make_shell_context():
    return dict(app=app, db=db, Role=Role, User=User)

manager.add_command("shell", Shell(make_context=make_shell_context))
manager.add_command("db", MigrateCommand)

if __name__ == "__main__":
    manager.run()

5. 需求文件

生成需求文件 :

$ pip freeze > requirements.txt

依据需求文件创建新的虚拟环境 :

$ pip install -r requirements.txt

配置文件的导入包含一般在开发环境中, 可以将 requirements.txt 文件替换为 requirements 文件夹, 其中包含不同环境的配置文件 :

common.txt   # 基础包
prod.txt     # 生产专用包
demo.txt     # 测试专用包

其中 prod.txt 和 demo.txt 可以从 common.txt 中导入, 而无需重复包名, 格式如下:

$ cat demo.txt
  -r common.txt
  ForgerPy==0.1

6. 创建数据库

要在新数据库中创建数据表。如果使用 Flask-Migrate 跟踪迁移,可使用如下命令创建数据表或者升级到最新修订版本:

$ python manage.py shell
    > db.create_all()
$ python manage.py db upgrade

四. Flask 模板

1. Jinja2

2. Mako

五. Flask 其他

1. url_for()

url_for() 辅助函数 : 使用程序 URL 映射中保存的信息, 生成 URL. 可用于 视图函数中, 或者 Jinja2 模板中.

  1. 相对地址

    url_for(view_func)

    示例 :

    url_for('index')    
  2. 绝对地址

    url_for(view_func, exterual=True)
  3. 动态地址

    url_for(view_func, key=value)
  4. 动态参数

    url_for(view_func, page=2)
  5. 静态文件

    url_for('static', filename="filename")
  6. 在 蓝本 中

    url_for(Blueprint_Name.view_func)

2. Flash 消息

消息是 Flask 的核心特性.

1) 在视图函数中使用消息

示例代码 :

from flask import flash

@app.route("/", methods=["GET", "POST"])
def index():
    form = NameForm()
    if form.validate_on_submit():
        old_name = session.get("name")
        if old_name is not None and old_name != form.name.data :
            flash("Looks lick you have changed your name !")
        session["name"] = form.name.data
        return redirect(url_for('index'))
    return render_template('index.html', form=form, name=session.get("name"))
2) 在模板中渲染消息.

Flask 把 get_flashed_messages() 函数开放给模板, 用来获取并渲染消息.

仅在 视图函数中调用 flash() 函数并不能把消息显示出来, 程序使用的模板需要渲染这些消息. 最好在基模板中渲染 Flash 消息, 因为这样所有的页面都能使用这些消息.

示例代码 :

{% block content %}
    <div class="container">
    {% for message in get_flashed_messages() %}
    <div class="alert alert-warning">
        <button type="button" class="close" data-dismiss="alert" >&times;</button>
        {{ message }}
    </div>
    {% endfor %}
        {% block page_content %}{% endblock %}
    </div>
{% endblock %}

在模板中使用循环是因为在之前的请求循环中每次调用 flash() 函数都会生成一个消息, 所以可能有很多消息在排队等待显示.

get_flash_messages() 函数获取的消息在下次调用时不会再次返回, 因此 Flash 消息只显示一次, 然后就消失了.

六. Flask 扩展

Flask 被设计为可扩展模式, 故而没有提供一些重要的功能, 如数据库和用户认证, 所以开发者可以自由选择最合适程序的包, 或者自行开发.

专为 Flask 开发的扩展都暴露在 flask.ext 命名空间下.

Flask 扩展的通用初始化方法 : 把程序实例作为参数传给构造函数, 初始化主类的实例. 创建的对象可以在各个扩展中使用.

  1. werkzeug : WSGI 工具集
  2. flask-script
  3. flask-moment
  4. flask-wtf : 表单处理
  5. flask-mail : 邮件发送
  6. flask-sqlalchemy : SQL ORM
  7. flask-migrate : 数据库迁移
  8. flask-login : 登录用户管理
  9. flask-pagedown : Markdown 支持
  10. flask-HTTPAuth : HTTP 认证
  11. Flask-Babel : 提供国际化和本地化支持。
  12. FLask-RESTful : 开发 REST API 的工具。
  13. Celery : 处理后台作业的任务队列。
  14. Frozen-Flask : 把 Flask 程序转换成静态网站。
  15. Flask-Debug Toolbar : 在浏览器中使用的调试工具。
  16. Flask-Assets : 用于合并、压缩、编译 CSS 和 Java Script 静态资源文件。
  17. Flask-OAuth : 使用 OAuth 服务进行认证。
  18. Flask-Open ID : 使用 Open ID 服务进行认证。
  19. Flask-Whoosh Alchemy : 使用 Whoosh 实现 Flask-SQLAlchemy 模型的全文搜索。
  20. Flask-KVsession : 使用服务器端存储实现的另一种用户会话。

七. Flask 信号

pip search blinker

八. 参考链接

Flask web 开发 : 基于Python的Web应用开发实战

python web -- flask的更多相关文章

  1. Python Web Flask源码解读(一)——启动流程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  2. Python Web Flask源码解读(二)——路由原理

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  3. Python Web Flask源码解读(三)——模板渲染过程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  4. Python Web Flask源码解读(四)——全局变量

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  5. virtualenv 环境下 Nginx + Flask + Gunicorn+ Supervisor 搭建 Python Web

    在这篇文章里,我们将搭建一个简单的 Web 应用,在虚拟环境中基于 Flask 框架,用 Gunicorn 做 wsgi 容器,用 Supervisor 管理进程,然后使用 Python 探针来监测应 ...

  6. 通过uwsgi+nginx启动flask的python web程序

    通过uwsgi+nginx启动flask的python web程序 一般我们启动python web程序的时候都是通过python直接启动主文件,测试的时候是可以的,当访问量大的时候就会出问题pyth ...

  7. python三大web框架Django,Flask,Flask,Python几种主流框架,13个Python web框架比较,2018年Python web五大主流框架

    Python几种主流框架 从GitHub中整理出的15个最受欢迎的Python开源框架.这些框架包括事件I/O,OLAP,Web开发,高性能网络通信,测试,爬虫等. Django: Python We ...

  8. 选择一个 Python Web 框架:Django vs Flask vs Pyramid

    Pyramid, Django, 和 Flask都是优秀的框架,为项目选择其中的哪一个都是伤脑筋的事.我们将会用三种框架实现相同功能的应用来更容易的对比三者.也可以直接跳到框架实战(Framework ...

  9. 浅谈Python Web 框架:Django, Twisted, Tornado, Flask, Cyclone 和 Pyramid

    Django Django 是一个高级的 Python Web 框架,支持快速开发,简洁.实用的设计.如果你正在建一个和电子商务网站相似的应用,那你应该选择用 Django 框架.它能使你快速完成工作 ...

随机推荐

  1. UVA 10905 Children's Game (贪心)

    Children's Game Problem Description There are lots of number games for children. These games are pre ...

  2. Gym - 101102C线段树

    Judge Bahosain was bored at ACM AmrahCPC 2016 as the winner of the contest had the first rank from t ...

  3. sql注入基础(原理)

    一.注入的分类 按数据库分类:1.整形 2.字符型(需要考虑单引号闭合的问题,还有注释不必要的语句  #  ) eag:  id='admin'  id='admin and1=1'这样会报错  所以 ...

  4. SpringMVC构建Restful。

    因为spring是依赖jackson来生成json,需要添加jar包. pom.xml文件添加依赖. <dependency> <groupId>org.codehaus.ja ...

  5. MySQL使用pt-online-change-schema工具在线修改1.6亿级数据表结构

    摘  要:本文阐述了MySQL DDL 的问题现状.pt-online-schema-change的工作原理,并实际利用pt-online-schema-change工具在线修改生产环境下1.6亿级数 ...

  6. gitignore.io-程序猿值得拥有的智能生成gitignore文件的秘密武器

    gitignore.io Create useful .gitignore files for your project by selecting from 360 Operating System, ...

  7. SpringMVC中使用@Value给非String类型注入值

    String类型的@Value注入方式 String类型的直接可以使用 @Value("陈婉清") private String name; 非String类型的@Value注入方 ...

  8. Hibernate中调用带有underscore的Column Name

    Hibernate中默认的NamingStrategy不支持调用带有下划线的column name.在hibernate的bean中必须使用camel case.使用ImprovedNamingStr ...

  9. MySql学习笔记(一) —— 数据的分组

    前面介绍的聚集函数只是用来计算行数,平均数,最大值,最小值而不用检索所有数据.通过count()函数,我们可以计算生产商1003提供的产品数目,但如果我要查询所有生产商提供的商品数,这就需要进行分组查 ...

  10. Jmeter结构体系及运行原理

    Jmeter结构体系 把Jmeter的结构体系拆分为三维空间,如图: X1~X5:是负载模拟的一个过程,使用这些组件来完成负载的模拟: X1:选择协议,模拟用户请求,检查服务器响应是否正确,然后收集结 ...