Spark 網頁式 開發 (四)

接著上篇講的,上篇說的 通過 Janino 實現了代碼動態加載的過程,那麼接下來我講解下 後臺的操作吧。畢竟網頁式開發 肯定就需要一個網站,而網站也需要和後端交互,就需要後臺了。

因為本人不是專門寫後臺的,所以就想找個最簡單的後臺開發,想到自己有python基礎,就決定使用 bottle 作為後臺 進行開發。

剛接觸bottle的時候就被他吸引了,寫一個網站就需要5、6行代碼就可以跑起來,實在是太方便了。

好了,扯遠了,將我這邊在bottle中的開發的代碼展示下。

<code># encoding=utf8
import os
import socket
import traceback

import yaml
from beaker.middleware import SessionMiddleware
from bottle import Bottle, run, request, static_file, template, redirect, BaseRequest, response

from application.action import *
from application.util import *

os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'
import logging
import logging.config
import json

'''
stop-python
pid=`ps -ef|grep /home/appadmin/python3|grep -v grep|awk '{print $2}'`
echo $pid
kill -9 $pid


pip3 install DBUtils
pip3 install bottle
pip3 install breaker
pip3 install cx-Oracle
pip3 install pyyaml
pip3 install tornado
pip3 install requests
pip3 install lxml

'''


# scp -r [email protected]:/Users/zhonglieming/PycharmProjects/pythonWeb ~/python_project/
# scp -r [email protected]:/Users/zhonglieming/PycharmProjects/pythonWeb ~/python_project/
class BottleDemo:
\t@staticmethod
\tdef get_request_ip():
\t\t'''獲取請求方的ip'''
\t\ttry:
\t\t\tip = request.remote_addr
\t\t\treturn ip
\t\texcept Exception as e:
\t\t\tlogging.error(e)
\t
\t@staticmethod
\tdef check_login_user():
\t\ts = request.environ.get('beaker.session') # 獲取session
\t\tusername = s.get('user', None) # 從session中獲取Key為user的值,是上面登陸的時候保存進來的
\t\tif username:
\t\t\treturn username
\t\telse:
\t\t\treturn None
\t
\t@staticmethod
\tdef get_pre_job_search_content(oracle_dbs, login_name):
\t\t
\t\tconn = oracle_dbs['DABAO_T']
\t\tif socket.gethostname() == 'sg-tdnifi-1.800best.com':
\t\t\tconn = oracle_dbs['DABAO_T9']
\t\telif socket.gethostname() == 'localhost':
\t\t\tconn = oracle_dbs['uat']
\t\t
\t\tpre_query_data = conn.db_query('''
\t\tselect * from(
\t\t\tselect
\t\t\t\tproject_name,
\t\t\t\tquery_content,
\t\t\t\trow_number() over (partition by login_name order by created_time desc) as rk
\t\t\t\tfrom ge_bi_contract_log
\t\t\t\twhere user_action='search_job'
\t\t\t\t\tand login_name='%s' and user_action='search_job' order by created_time desc
\t\t\t)res where rk=1 ''' % (str(login_name).lower()), True)
\t\tif pre_query_data:
\t\t\tquery_data = {'project_name' : str(pre_query_data[0]['project_name']),
\t\t\t\t\t\t 'query_content': str(pre_query_data[0]['query_content'])}
\t\telse:
\t\t\tquery_data = {'project_name': 'Spark_Thai9Analysis', 'query_content': ''}

\t\tquery_data['login_user'] = login_name
\t\tquery_data['active_index'] = 0
\t\treturn query_data
\t
\tdef __init__(self):
\t\t
\t\tself.log = logging.getLogger("BottleDemo")
\t\t# 避免出現 413 Request Entity Too Large
\t\tBaseRequest.MEMFILE_MAX = 1024 * 1024 * 5 # (or whatever you want)
\t\tself.app = Bottle()
\t\tself.app.install(OraclePlugin('oracle_dbs'))
\t\tself.user_permission = {'bl06250': 100, 'test': 10}
\t\tself.page_permission = {'page_table': 0, 'user_action': 90, 'data_table_config': 10, 'partition_table': 10,
\t\t\t\t\t\t\t\t'data_sync' : 20, 'jira_info': 20}
\t\tself.action_dict = {
\t\t\t\t\t\t\t 'page_table': (0, JobAction()), 'jobs': (0, JobAction())
\t\t

\t\t
\t\[email protected]('/static/:path#.+#')
\t\tdef server_static(path):
\t\t\treturn static_file(path, root='./static/', download=False)
\t\t
\t\[email protected](404)
\t\tdef error404(data):
\t\t\tself.log.error('404===' + str(data))
\t\t\tredirect('/login')
\t\t
\t\[email protected](500)
\t\tdef error500(error):
\t\t\tself.log.error('500===', error)
\t\t\tredirect('/login')
\t\t
\t\[email protected]('/')
\t\tdef except_url():
\t\t\tredirect('/login')
\t\t
\t\[email protected]('/:sub_url')
\t\tdef login_form(sub_url):
\t\t\tif sub_url != 'login':
\t\t\t\tself.log.info(sub_url + '-->login')
\t\t\t\tredirect('/login')
\t\t\treturn template('login', login_info="", pre_url="none")
\t\t
\t\[email protected]('/logout')
\t\tdef logout():
\t\t\tname = self.check_login_user()
\t\t\tself.log.info(name + ' logout')
\t\t\trequest.environ.get('beaker.session').delete()
\t\t\tredirect('/login')

\t\t
\t\t# 用戶登錄操作
\t\[email protected]('/login')
\t\tdef login(oracle_dbs):
\t\t\tname = request.forms.username
\t\t\tpassword = request.forms.password
\t\t\tpre_url = request.forms.pre_url
\t\t\t
\t\t\tif (str(name).lower() == 'bl06250' and password == 'zhonglieming') or str(name).lower() == 'test':
\t\t\t\tlogging.info(self.get_request_ip() + " go to login,username is " + name + ',ok.')
\t\t\t\t# 把username這個變量用安全字符串usafe加密,httponly指不允許通過javascript獲取cookie,降低用戶信息洩露風險,
\t\t\t\t# max_age = 600指這個cookie的有效期為600秒,600秒後就會過期,用戶需要重新登錄。
\t\t\t\t# response.set_cookie('username', name, secret='usafe', httponly=True, max_age=600)
\t\t\t\t# response.set_cookie('password', password, secret='psafe', httponly=True, max_age=600)
\t\t\t\t
\t\t\t\ts = request.environ.get('beaker.session')
\t\t\t\ts['user'] = name.lower()
\t\t\t\ts.save()
\t\t\t\tif pre_url == 'none':
\t\t\t\t\treturn template('page_table', self.get_pre_job_search_content(oracle_dbs, name))
\t\t\t\telse:
\t\t\t\t\tredirect(pre_url)
\t\t\telse:
\t\t\t\tlogging.info(self.get_request_ip() + " go to login,username is " + name + ', failed')
\t\t\t\treturn template('login', login_info='username or password error', pre_url=pre_url)
\t\t
\t\[email protected]('/tabs/tables/:sub_url', method='GET')
\t\tdef tables_web(sub_url):
\t\t\ttry:
\t\t\t\t
\t\t\t\tparams = request.GET.decode('utf8')
\t\t\t\tname = self.check_login_user()
\t\t\t\tif name:
\t\t\t\t\treturn template('data_table', table_name=sub_url, db_type=params['db_type'],
\t\t\t\t\t\t\t\t\tcollect_date=params['collect_date'], login_user=name)
\t\t\t\telse:
\t\t\t\t\tothers = []
\t\t\t\t\tfor key, v in params.items():
\t\t\t\t\t\tothers.append(key + '=' + v)
\t\t\t\t\tif others != []:
\t\t\t\t\t\tsub_url = sub_url + '?' + '&'.join(others)
\t\t\t\t\treturn template('login', login_info='please first login', pre_url="/tabs/tables/" + sub_url)
\t\t\texcept Exception as ie:
\t\t\t\ttraceback.print_exc()

\t\t\t\tself.log.error(str(ie))
\t\t
\t\[email protected]('/nav_bar/:sub_url', method='GET')
\t\tdef nav_bar_link(oracle_dbs, sub_url):
\t\t\tlogin_name = self.check_login_user()
\t\t\t
\t\t\tif login_name:
\t\t\t\tself.log.info('[%s ip(%s)]: nav_bar/%s' % (login_name, self.get_request_ip(), sub_url))
\t\t\t\tactive_index = self.action_dict.get(sub_url, (-1, None))[0]
\t\t\t\t
\t\t\t\tif self.user_permission[login_name] >= self.page_permission[sub_url]:
\t\t\t\t\t
\t\t\t\t\tif active_index == 0:
\t\t\t\t\t\treturn template(sub_url, self.get_pre_job_search_content(oracle_dbs, login_name))
\t\t\t\t\telif active_index > 0:
\t\t\t\t\t\treturn template(sub_url, login_user=login_name, active_index=active_index)
\t\t\t\t\telse:
\t\t\t\t\t\tredirect('/login')
\t\t\t\telse:
\t\t\t\t\tredirect('/login')
\t\t\telse:
\t\t\t\tself.log.info('[匿名登錄 ip(%s)]: /jobs/%s' % (self.get_request_ip(), sub_url))
\t\t\t\treturn template('login', login_info='please first login', pre_url="nav_bar/" + sub_url)
\t\t
\t\[email protected]("/tabs/:parent_url/:sub_url", method='POST')
\t\tdef partition_table(oracle_dbs, parent_url, sub_url):
\t\t\tif parent_url in self.action_dict:
\t\t\t\tlogin_name = self.check_login_user()
\t\t\t\taction = self.action_dict[parent_url][1]
\t\t\t\tif login_name is None:
\t\t\t\t\tself.log.info('[匿名登錄 ip(%s)]: /jobs/%s' % (self.get_request_ip(), sub_url))
\t\t\t\t\tredirect('/login')
\t\t\t\telse:
\t\t\t\t\tself.log.info('[%s ip(%s)]: tabs/%s/%s' % (login_name, self.get_request_ip(), parent_url, sub_url))
\t\t\t\t\t
\t\t\t\t\tif sub_url in ['table_config_update', 'add_one_reord', 'update_job_other',
\t\t\t\t\t\t\t\t 'update_job'] and login_name != 'bl06250':
\t\t\t\t\t\treturn json.dumps({'success' : False, 'rows': [], 'total': 0,
\t\t\t\t\t\t\t\t\t\t 'errorMsg': 'Sorry,user[%s] have not Permission' % login_name},
\t\t\t\t\t\t\t\t\t\t ensure_ascii=False)
\t\t\t\t\telse:
\t\t\t\t\t\treturn action.execute_action(oracle_dbs, login_name, sub_url, request.POST.decode('utf8'))
\t\t\telse:
\t\t\t\tredirect('/login')
\t\t
\t\[email protected]('after_request')
\t\tdef enable_cors():
\t\t\t"""
\t\t\t鉤子函數,處理請求路由之後需要做什麼的事情

\t\t\t:return:
\t\t\t"""
\t\t\tresponse.headers['Access-Control-Allow-Origin'] = '*'
\t
\tdef run(self):
\t\t
\t\t# 設置session參數
\t\tsession_opts = {'session.type' : 'file', # 以文件的方式保存session
\t\t\t\t\t\t'session.cookei_expires': 1800, # session過期時間為3600秒
\t\t\t\t\t\t# ,最後發現在session的配置參數中有一個參數timeout,如果我們使用session的方式,從描述上來看,我們使用timeout參數更加合理。
\t\t\t\t\t\t# 嘗試將配置'session.cookie_expires': 30,修改為'session.timeout': 30,session在30秒後失效,說明這裡應該使用timeout參數。
\t\t\t\t\t\t'session.timeout' : 1800, # session過期時間為3600秒
\t\t\t\t\t\t'session.data_dir' : '/tmp/sessions', # session存放路徑
\t\t\t\t\t\t'session.auto' : True}
\t\tlogging.config.dictConfig(yaml.load(open('logging.yaml', 'r')))
\t\t
\t\tweb_port = 8080
\t\trun(SessionMiddleware(self.app, session_opts), host=socket.gethostname(), port=web_port, reloader=True,
\t\t\tdebug=False, server="tornado")
/<code>

上述就是程序運行的入口,代碼寫法和 Spring的寫法類似,不過python作為python,就是寫起來簡單,。

簡單的實現了用戶登錄 和 頁面跳轉。

在前臺頁面用戶登錄的時候,會觸發

@self.app.post('/login') ,如果登錄的用戶名是bl06250,那麼就登錄成功,跳轉到


Spark 網頁式 開發 (四)

登錄成功


反之 就繼續留在登錄頁面

Spark 網頁式 開發 (四)

登錄失敗,username or password error


,而當用戶登錄成功,就會在頁面中修改代碼,那麼代碼修改完提交的時候就需要通過

@self.app.route("/tabs/:parent_url/:sub_url", method='POST')

這個地方 進行 post請求,數據以json的形式到後臺,被後臺解析,去執行

return action.execute_action(oracle_dbs, login_name, sub_url, request.POST.decode('utf8'))

這裡的內部實現就是處理 用戶代碼查詢、修改 操作。

下一篇章,給大家 展示


Spark 網頁式 開發 (四)

JobAction 內部的代碼。


分享到:


相關文章: