EBS OAF开发中的错误/异常处理(ErrorHandling) (转)

时间:2022-09-22 21:28:00

原文地址 EBS OAF开发中的错误/异常处理(ErrorHandling)

EBS OAF开发中的错误/异常处理(ErrorHandling)

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处;否则请与本人联系,违者必究)

总览

这篇文档描述了如何在你的Model和控制器代码中抛出OAF 框架异常.

内容

l  异常类型

l  异常类

l  批量异常

l  异常示例

l  对话框页和消息对话框

异常类型

OAF框架处理三种基本类型的异常:常规(general),验证(validation)和严重(severe).这三种类型将会做简单描述;相应的使用说明也会在下面介绍。

常规异常

在BC4J框架中,错误都是通过抛出一个隐式的(运行时)oracle.jbo.JBOException类型的异常。OAF 框架对这种异常有自己的专门的实现
oracle.apps.fnd.framework.OAException。

这种专门的实现提供了一种把多个异常捆绑在一起的机制,并且也可以通过Oracle E-Business Suite 消息字典来翻译异常消息,这样就可以显示有用的信息。在你的任何代码中,你可以为常规的,页面级的异常抛出一个OAException。

验证异常

可以从实体对象或者视图对象为行级别或者属性级别的失败抛出验证异常.

l  oracle.apps.fnd.framework.OAAttrValException - 用于实现属性级别验证失败的OAException.

l  oracle.apps.fnd.framework.OARowValException - 用于实现行级别验证失败的OAException的

OAF 框架像下面显示错误给用户:

l  属性级别异常显示在出错的Item(s)和页的上方.

l  行级别的异常显示在出错的行和也的上方.

l  页级别的异常显示在页的上方.

严重异常

严重(或者致命)异常包括意外的系统级别的错误(比如NullPointerException)和特别的JBOException,比如NoDefException.你也可以在你的代码中故意抛出一个严重异常.

如果一个严重异常发生,用户会被导向到OAErrorPage(如果严重异常发生在页面生成过程之中, 部分页面生成并包含一个用户友好的错误消息,其中包含了一个链接到详细堆栈跟踪的链接).OAErrorPage也显示了一个用户友好的错误消息,其中包含了一个链接到详细堆栈信息链接.

注意:这是一个未翻译的消息,但用户可以在site上进行修改。

Oracle Workflow通知

OAF框架也提供了一个内置的业务事件(oracle.apps.fnd.framework.OAFatalError), 不论什么时候OAF页面报告了一个严重的异常,它都可以发送通知给SYSADMIN用户。通知包含了严重异常的详细错误堆栈和关于哪个用户遇到这个异常的信息.如果你希望修改通知的默认接收人从SYSADMIN为其它人,你需要定制Item Type OAERROR的定义。

默认对这个业务事件的订阅是禁止的。要启用订阅,请参阅Oracle Workflow文档如何启用业务事件的订阅.

l  如果你使用的是OracleWorkflow Rlease 11i/2.6,Oracle Applications原先的界面,请看"To Update orDelete an Event Subscription", Oracle Workflow Developer's Guide.

l  如果你使用的是基于OAF框架的业务事件系统的界面,请参考"ToView and Maintain Event Subscriptions", Oracle Workflow Developer'sGuide.

异常类

OAF框架异常的继承层次就像下面的图1所示.基类OAException继承自JBOException.OAAttrValException和OARowValException继承自OAViewObjectException,一个继承自OAException并不再赞成使用的类。

EBS OAF开发中的错误/异常处理(ErrorHandling)  (转)

OAException

OAException 是用来抛出常规异常时用的异常(比如,如果你在一个控制器代码中碰到了一个意外的问题,如下面的代码)

OACellFormatBean shipTermsCell =

  (OACellFormatBean)webBean.findIndexedChildRecursive("ShipTermsCell");

 if (shipTermsCell == null)

 {

  MessageToken[] tokens = { new MessageToken("OBJECT_NAME","ShipTermsCell")};

  throw new OAException("AK","FWK_TBX_OBJECT_NOT_FOUND", tokens);

 }

注意我们在AK应用中在Oracle E-Bussiness Suite消息字典创建了消息(FWK_TBX_OBJECT_NOT_FOUND).消息定义中包含了标识(OBJECT_NAME),我们将会用我们期望找到的UI组件的名字来替换.OAF框架将使用这个消息在页面上面自动显示一个翻译过的错误消息(如果你实例化一个OAException,并且不指明消息类型,那么它一般显示为错误).

注意:虽然它不是一个明确的编程标准,但是包装一个异常而不是创建一个新的异常是一个好的编程习惯而且有好处的.

包装一个异常来创建一个新的包含原来异常作为详细异常的OAException。通过包装一个异常,核心异常会被报告,OAF框架监测到原先的异常来决定它的严重度.如果创建了一个新的异常,你就得不到这些信息,异常堆栈就停止在你的代码,导致BUG中的信息很少.

因为OAException是一个灵活的对象,也可以用来显示其他类型的消息(信息,确认和异常),,你也可以用下面展示确认示例中的消息类型来实例化它(参看对话框也和消息对话框部分,描述如何使用这些功能来显示信息,确认和警告消息).

MessageToken[] tokens = { new MessageToken("SUPPLIER_NAME", name),
new MessageToken("SUPPLIER_NUMBER", supplierId) }; OAException confirmMessage = new OAException("AK", "FWK_TBX_T_SUPPLIER_CREATE_CONF", tokens, OAException.CONFIRMATION, null);

消息类型

OAException, OAAttrValException, 和OARowValException类都包含了接受消息类型作为参数的构造器.消息类型参数告诉OAF框架要显示给用户的消息类型.有效的选项包括:

l  OAException.ERROR

l  OAException.WARNING

l  OAException.INFORMATION

l  OAException.CONFIRMATION

l  OAException.SEVERE

OAAttrValException

如果在视图对象行或者实体对象中,任意属性级别的验证失败,你都可以像如下抛出一个OAAttrValException.

要实例化这个异常,你必须传递下面的信息:

l  源对象类型(OAException.TYP_ENTITY_OBJECT或者OAException.TYP_VIEW_OBJECT)

l  完整的实体定义的名称或者视图实例的名字

l  实体或者行的主键

l  正验证的属性名

l  验证失败的属性值

l  错误消息所属的应用缩写名

l  错误消息名称

实体对象示例

public void setSalary(Number value)

{

   if (value != null)

   {

      // Verify value is > 0
if (value.compareTo(0) <= 0) { throw new OAAttrValException(OAException.TYP_ENTITY_OBJECT, // indicates EO source getEntityDef().getFullName(), // entity name getPrimaryKey(), // entity primary key "Salary", // attribute Name value, // bad attribute value "AK", // nessage application short name "FWK_TBX_T_EMP_SALARY_REQUIRED"); // message name } setAttributeInternal(SALARY, value); } } // end setSalary()

视图行示例

关于从视图行抛出这类异常的额外信息请参考下面的映射部分

setDescription(String value)
{
if("XXX".equals(value)) {
throw new OAAttrValException ( OAException.TYP_VIEW_OBJECT, // indicates VO row source getViewObject().getFullName(), //View Object full usage name getKey(), // row primary key "Description", //attribute name value, // bad attribute value "FND", //message application short name "ATTR_EXCEPTION"); // message name }
setAttributeInternal("Description", value);
} // end setDescription()

OARowValException

如果在视图对象行或者实体对象上的任意的行级别的验证失败,你可以像下面展示的抛出一个OARowValException

要示例化这个异常,你必须传入以下的信息:

l  完整的实体定义名称或者视图对象名称

l  实体或者行的主键

l  错误消息所属的应用缩写名

l  错误消息名

实体对象示例

protected void validateEntity()
{
super.validateEntity(); if(attr1!=attr2) throw new OARowValException ( getEntityDef().getFullName(), // entity full definition name getPrimaryKey(), // entity object primary key "FND", // message application short name "ATTR_EXCEPTION"); // message name }

视图行示例

关于从视图行抛出这类异常的额外信息请参考下面的映射部分

protected void validate()
{
super.validate();
if(attr1!=attr2)
throw new OARowValException (
getViewObject().getFullName(),//View Object full usage name getKey(), // row primary key
"FND", // message application short name "ATTR_EXCEPTION"); // message name
}

覆盖行级别的错误前缀

当OAF框架在表中生成行或者属性错误或者警告消息时,消息由两部分组成:行前缀+错误消息.比如:

l  Row 2 Error: <Some error messagerelating to the entire row 2>

l  Row 2 <AttributePrompt>: <Some error message relating to the given attribute inRow 2>

你可以选择覆盖这个前缀如果默认的行引用对你的界面不合适,比如:

l  Line 2-3 Error: <Some error messagerelating to this row in the table>

l  Line 2-3 <Attribute Prompt>:<Some error message relating to the given attribute in this designatedrow>

要实现这个:

第一步:创建一个临时的视图对象属性,其中包含要作为行前缀的以翻译的字符串

第二步:为视图对象创建一个自定义的属性

l  设置名称(Name)为ROW_DISPLAY_PREFIX_ATTR_NAME

l  设置值(Value)为第一步中创建的属性名.

当处理和这个视图对象相关的异常时,OAF框架将检查这个自定义的属性是否设置了,如果是,将使用指定的属性值作为行前缀.

注意:为保持一致,OAF框架应用这个前缀到你产生的任意错误或者警告消息,加上它内部生成的任意行级别的消息。

映射实体对象属性到视图对象属性

当创建自定义的视图行方法,并抛出源自于实体对象的异常时,你必须在异常上调用doEntityToVOMapping来创建在实体对象属性和视图对象属性之间的映射,示例如下:

/** 

 * Approves the purchase order associated with this row. 

 */ 

public void approve() 

{ 

  // Whenever you write custom methods on the VO Row that call custom methods 

  // on the Entity Object you need to do a manual mapping as shown below    

  // to correctly handle the entity exceptions. 

  try 

  { 

    getPurchaseOrderHeaderEO().approve();    

  } 

  catch(OARowValException e) 

  { 

    OAViewObject[] vos = {(OAViewObject)getViewObject()}; 

    e.doEntityToVOMapping(getApplicationModule(), vos); 

    throw e; 

  } 

} // end approve()

除了这种情况,OAF框架在以下的方法中为抛出异常调用这个方法:

l  viewRow.setAttribute()

l  viewRow.validate() (捕捉所有抛自eo.validate()的异常)

l  create(AttributeList)

l  viewRow.remove()

注意:如果你覆盖这些方法,这个映射是当你调用super的时候执行的.如果你的覆盖代码隐式的抛出实体对象异常,那么你需要调用doEntityToVOMapping

集束异常(BundledExceptions)

Bundled exceptions 允许你在进行验证的时候叠加同等的异常,当你完成验证的时候一块显示给用户。这些同等的异常被分组到一个叫做bundled exception 的容器异常中.

Bundled exceptions可以包含任意类型的服务器端的异常(包括系统级的异常,数据格式错误,属性验证错误,行验证错误以及实体创建错误).

同等异常列表

要创建一个bundled exception,首先必须创建一个列表,这样当你遇见异常的时候就把它加入到这个列表中去.

ArryList peerExceptions = new ArrayList();
peerExceptions.add(new OAException(....));
peerExceptions.add(new OAException(....));
...

Bundled Exception

当你准备抛出你的bundled exception,调用OAException.getBundledOAExceptioncon根据传入的同等异常列表来创建一个bundled OAException,或者调用OAException.raiseBundledOAException来创建并立即抛出一个bundledOAException。

l  注意对OAAttrValException 和OARowValException也有相似的API。

l  参考OA*Exception类中的各种用于与bundledOAException交互的访问方法(记住bundled Exception本身只是一个简单的包含同等异常数组的容器).

在实体和行验证过程中,如果你不想自己打包,你也可以注册异常.这些异常将会在验证完成的时候或者当一个异常被明确抛出的时候抛出来,请参考下面的例子(Javadoc: oracle.apps.fnd.framework.server.OAEntityImpl 和oracle.apps.fnd.framework.server.OAViewRowImpl).

BC4J集束异常模式

当这种模式被禁用时,所有由实体属性访问方法抛出的异常都会立刻抛给调用的视图对象行,然后再把异常抛给调用者。当你启用集束异常模式,BC4J会把实体属性访问方法抛出的异常放进堆栈,并在valdiateEntity结束抛出这些异常,或者当valdiateEntity抛出一个异常的时候抛出这些异常.所有这些异常都会打包成一个单独的异常返回给调用者.

你可以使用下面的代码来启用集束异常模式:

OADBTransaction.setBundledExceptionMode(true);

默认,这种模式是被禁止的。我们建议不要使用这个功能,因为在没有启用它的时候OAF框架会代表你收集所有的异常。

异常示例

示例1

下面的代码示例展示了如何捕获异常并把它们作为一个单独的集束异常抛出来。

public void foo()

{

//   ArrayList exceptions = new ArrayList();
com.sun.java.util.collections.ArrayList exceptions = new com.sun.java.util.collections.ArrayList(); for(int ...; ...; ...) { if(.....) { exceptions.add(new OAException(.....)); } } OAException.raiseBundledOAException(exceptions); }

示例2

下面的代码示例展示了如何缓存validateEntity()方法中抛出的异常,然后把缓存的异常作为一个集束异常抛出来。

protected void validateEntity()
{
super.validateEntity(); ArrayList exceptions = new ArrayList(); //check for duplicate Filter Name if (getEntityState() == STATUS_NEW) { String value = getFilterName(); OADBTransaction tx = getOADBTransaction(); OAApplicationModule vam = getMyValidationAM(); FiltersVOImpl vo = vam.findViewObject("filtersViewUsage"); if (vo == null) { vo = vam.createViewObject("filtersViewUsage","oracle.apps.qrm.filter.server.FiltersVO"); vo.setMaxFetchSize(-1); vo.initQuery(value,"C"); Row r = vo.first(); if (r != null) { exceptions.add( new OAAttrValException ( OAException.TYP_ENTITY_OBJECT, // Entity attribute exception. getEntityDef().getFullName(), //Entity full def name getPrimaryKey(), //Row primary key "FilterName", //Attribute Name value, //Bad Value "QRM", //Message Application Short Code "QRM_UNIQUE_FILTERS_ERR")); //Message Code } } //check for empty filters(no conditions) EntityDefImpl def = EntityDefImpl.findDefObject("oracle.apps.qrm.filter.server.QrmFilterConditionsEO"); Iterator iterator = def.getAllEntityInstancesIterator(getDBTransaction()); String flag = "no"; while (iterator.hasNext()) { QrmFilterConditionsEOImpl fcEO = (QrmFilterConditionsEOImpl)iterator.next(); // only check rows in valid state if ( fcEO.getEntityState() != STATUS_DELETED && fcEO.getEntityState() != STATUS_DEAD ) { flag = "OK"; } } if (flag.equals("no")) { exceptions.add( new OARowValException ( getEntityDef().getFullName(), getPrimaryKey(), //Row primary key "QRM", //Message Application Short Code "QRM_NO_CONDITIONS_ERR")); //Message Code } OAException.raiseBundledOAException(exceptions); }

示例3

下面的代码示例展示了如何缓存一个视图对象方法中抛出的异常,然后把缓存的异常作为一个集束异常抛出来。

public void checkUsed()
{
String ifSelected = null;
String name;
ArrayList exceptions = new ArrayList();
FiltersVORowImpl row = (FiltersVORowImpl)first();
while (row != null)
{
ifSelected = (String)row.getAttribute("SelectFlag"); if ("Y".equals(ifSelected))
{
name = (String)row.getAttribute("FilterName");
OAViewObjectImpl vo = (OAViewObjectImpl)getApplicationModule().findViewObject("IsFilterUsedVO");
vo.setWhereClause(null);
vo.setWhereClauseParams(null);
vo.setWhereClauseParam(0,name);
vo.executeQuery();
Row r = vo.first(); //if there are analyses, then use them
if (r != null)
{
String msg= (String)r.getAttribute("AnalysisName");
String flag ="f"; while (r != null)
{
//change flag if it was the first row,if not append analysis name
if (flag.equals("f"))
flag = "N";
else
msg = msg +", "+ (String)r.getAttribute("AnalysisName");
r = vo.next();
}
MessageToken[] tokens = {new MessageToken("FILTER_NAME",name),
new MessageToken("ANALYSIS",msg)};
exceptions.add(
new OARowValException(
getViewObject().getFullName(),
row.getKey(),
"QRM",
"QRM_FILTER_REMOVE_ERR",
tokens));
}
} row =(FiltersVORowImpl)next();
}
OAException.raiseBundledOAException(exceptions);
}

示例4

下面的代码示例展示了如何在set<Attribute>()注册一个验证异常以便在之后的实体验证中抛出这个异常。

public void setAmount(oracle.jbo.Number amnt)
{ // Clears any old exceptions for a fresh start.
clearAttributeException("Amount");
if(amnt < 0)
{
OAAttrValException attrEx = new OAAttrValException(
OAAttrValException.TYP_ENTITY_OBJECT,
getEntityDef().getFullName(),
getPrimaryKey(),
"Amount",
amnt,
"QRM",
"QRM_AMOUNT_IS_NEGATIVE"); registerAttributeException(getEntityDef().getAttributeDefImpl("Amount"),amnt, attrEx); } }

示例5

下面的代码示例展示了如何注册在validateEntity()过程中抛出的异常以便BC4J在验证结束的时候抛出这些异常。

protected void validateEntity()
{
super.validateEntity(); // Clears all Row and Attribute exceptions registered in validateEntity() for a fresh start. clearAttributeException("FilterNAme"); clearRowExceptions(); //check for duplicate Filter Name
if (getEntityState()==STATUS_NEW)
{
String value = getFilterName();
OADBTransaction tx = getOADBTransaction();
OAApplicationModule vam = getMyValidationAM();
FiltersVOImpl vo = vam.findViewObject("filtersViewUsage"); if(vo == null) {
vo = vam.createViewObject("filtersViewUsage", "oracle.apps.qrm.filter.server.FiltersVO"); } vo.setMaxFetchSize(-1);
vo.initQuery(value,"C");
Row r = vo.first();
if (r != null)
{
OAAttrValException attrEx = new OAAttrValException (
OAException.TYP_ENTITY_OBJECT, // Entity attribute exception.
getEntityDef().getFullName(), //Entity full def name
getPrimaryKey(), //Row primary key
"FilterName", //Attribute Name
value, //Bad Value
"QRM", //Message Application Short Code
"QRM_UNIQUE_FILTERS_ERR")); //Message Code registerAttributeException(getEntityDef().getAttributeDefImpl("FilterName"), value, attrEx);
}
} //check for empty filters(no conditions)
EntityDefImpl def = EntityDefImpl.findDefObject("oracle.apps.qrm.filter.server.QrmFilterConditionsEO");
Iterator iterator = def.getAllEntityInstancesIterator(getDBTransaction());
String flag = "no";
while (iterator.hasNext())
{
QrmFilterConditionsEOImpl fcEO = (QrmFilterConditionsEOImpl)iterator.next();
// only check rows in valid state
if ( fcEO.getEntityState() != STATUS_DELETED && fcEO.getEntityState() != STATUS_DEAD )
flag = "OK";
}
if (flag.equals("no"))
{
registerRowException(
new OARowValException (
getEntityDef().getFullName(),
getPrimaryKey(), //Row primary key
"QRM", //Message Application Short Code
"QRM_NO_CONDITIONS_ERR")); //Message Code
}
}

对话框页面和消息对话框

关于显示模态错误,消息,警告和确认对话框页面的信息,请参考Chapter 4: Implementing Dialog Pages..

关于在页面顶部显示错误,消息,警告和确认消息对话框(但不是像抛出一个异常那样简单自动),请参考Chapter 4: Implementing Message Boxes.

EBS OAF开发中的错误/异常处理(ErrorHandling) (转)的更多相关文章

  1. EBS OAF 开发中的OAMessageRadioGroup控件

    EBS OAF 开发中的OAMessageRadioGroup控件 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 简单介绍 RadioGro ...

  2. EBS OAF开发中怎样通过ReferenceAO进行验证

    EBS OAF开发中怎样通过ReferenceAO进行验证 (版权声明.本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) Reference AO 除了用于 ...

  3. EBS OAF开发中实体对象和视图对象的属性设置器

    EBS OAF开发中实体对象和视图对象的属性设置器 (版权声明.本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 源文: Home > Oracle ...

  4. EBS OAF开发中实现參数式弹出窗体

    EBS OAF开发中实现參数式弹出窗体 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 概览 參数式弹出窗体和嵌入式弹出窗体不一样,它拥有独立 ...

  5. EBS OAF开发中的Java 实体对象&lpar;Entity Object&rpar;验证功能补充

    EBS OAF开发中的Java 实体对象(Entity Object)验证功能补充 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) EO理论上 ...

  6. EBS OAF开发中怎样实现功能页签(Global Tab)

    EBS OAF开发中怎样实现功能页签(Global Tab) (版权声明.本人原创或者翻译的文章如需转载.如转载用于个人学习,请注明出处.否则请与本人联系,违者必究) 功能页签的实现不须要不论什么编码 ...

  7. ios开发——错误总结篇&amp&semi;开发中常见错误和警告总结(四)

    ios开发——开发总结&开发中常见错误和警告总结(四) 网易彩票实战总结(错误) 错误总结之类的实现 经典错误之重复定义与导入错误 经典错误关于父类的实现 通知对象: 控制器的定义 Xcode ...

  8. OAF开发中一些LOV相关技巧 &lpar;转&rpar;

    原文地址:OAF开发中一些LOV相关技巧 在OAF开发中,LOV的使用频率是很高的,它由两部分构成一是页面上的LOV输入框(如OAMESSageLovInputBean),二是弹出的LOV模式窗口(O ...

  9. Python基础教程(011)--程序开发中的错误及原因

    前言 排查代码开发中的错误 内容 1,编写的程序不能正常执行,或者执行的结果不是我们期望的 2,俗称bug,是程序开发常见的,初学常见的原因有 手误 对已经学习的知识点理解不足 对语音还有需要学习和提 ...

随机推荐

  1. Oracle常见授权与回收权限&lpar;grant和revoke&rpar;学习记录

      1.GRANT 赋于权限常用的系统权限集合有以下三个:CONNECT(基本的连接), RESOURCE(程序开发), DBA(数据库管理) 常用的数据对象权限有以下五个:ALL ON 数据对象名, ...

  2. SQLite 入门教程 (终端)命令

    一.基本简介 SQLite 是一个自持的(self-contained).无服务器的.零配置的.事务型的关系型数据库引擎.因为他很小,所以也可以作为嵌入式数据库内建在你的应用程序中.SQLite 被应 ...

  3. 关于表单提交submit的兼容性问题。

    这里的form 表单 点击下载执行的函数名字是submit,这样不规范,submit是提交表单,函数名字不能取名叫submit,如果取名叫submit会在低版本的浏览器上无法识别,导致直接提交表单,无 ...

  4. phpcms v9 后台首页 去掉团队信息等版权

    phpcms\languages\zh-cn\admin.lang.php $LANG['main_product_team'] = 'PHPCMS开发团队'; phpcms\modules\admi ...

  5. python作业设计:输入用户名密码,认证成功后显示欢迎信息,输错三次后锁定

    作业需求: 1.输入用户名密码 2.认证成功后显示欢迎信息 3.输错三次后锁定实现思路: 1.判断用户是否在黑名单,如果在黑名单提示账号锁定. 2.判断用户是否存在,如果不存在提示账号不存在. 3.判 ...

  6. mongodb 在windows下面进行副本建创建

    一:主从复制 1: 首先看看模型图 2: 从上面的图形中我们可以分析出这种架构有如下的好处: <1>  数据备份. <2>  数据恢复. <3>  读写分离. 3: ...

  7. 继承自 DevExpress 17&period;2 的自定义控件如何在工具箱显示

    最近把DevExpress版本从13.1升级到了17.2,结果发现继承自DevExpress的自定义控件居然在工具箱中消失了,弄了两天还是没有任何头绪,部分自定义Dev控件可以正常出现,但大部分自定义 ...

  8. LCA的在线与离线算法

    在线:链接 离线:链接

  9. 高级Linux运维工程师必备技能(扫盲篇)

    高级Linux运维工程师必备技能(扫盲篇) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在了解文件系统之前,我们要学习一下磁盘存储数据的方式,大家都知道文件从内存若要持久化存储的 ...

  10. flask使用配置文件

    引入配置 app = Flask(__name__) app.config.from_pyfile('config.py') config.py DEBUG = True SECRET_KEY = '