Coremail_XT_高级API使用手册(Java版).doc_第1页
Coremail_XT_高级API使用手册(Java版).doc_第2页
Coremail_XT_高级API使用手册(Java版).doc_第3页
Coremail_XT_高级API使用手册(Java版).doc_第4页
Coremail_XT_高级API使用手册(Java版).doc_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

广州:+86(20)85106566北京:+86(10)64097551上海:+86(21)64262839盈世信息科技(北京)有限公司Coremail. Copyright 2000-2009 Mailtech.Coremail XT高级API(Java)使用手册Nx 盈世信息科技(北京)有限公司版权声明本文档版权归盈世信息科技(北京)有限公司所有,并保留一切权利。未经书面许可,任何公司和个人不得将此文档中的任何部分公开、转载或以其他方式散发给第三方。否则,必将追究其法律责任。免责声明本文档仅提供阶段性信息,所含内容可根据产品的实际情况随时更新,恕不另行通知。如因文档使用不当造成的直接或间接损失,本公司不承担任何责任。文档更新本文档由盈世信息科技(北京)有限公司于2009年1月最后修订。公司网站销售咨询热线800-830-7652技术支持热线800-830-5422联系方式广州地址:广州市中山大道科韵路16号广州信息港网易大厦3楼邮编:510665联系电话:+86(20)85106566传真:+86(20)85106595北京地址:北京市东城区安定门东大街28号雍和大厦B座1208室邮编:100013联系电话:+86(10)64097551传真:+86(10)64097550上海地址:上海市徐汇区斜土路2601弄嘉汇广场T3座6G室邮编:200030联系电话:+86(21)64262839传真:+86(21)64262836目录1Coremail XT API通用函数说明11.1getClient(连接APIServer使用的socket)11.2getRetCode(获取操作的返回值)11.3getResult(操作的返回结果)21.4getResultEx(返回操作的返回结果)21.5getErrorInfo(描述操作失败原因)21.6toString(返回操作结果的字符串表示)21.7close(释放连接与资源)32API函数的使用步骤33Coremail XT API具体功能应用43.1登录43.1.1用户登录43.1.2检查用户是否存在53.1.3验证用户密码63.1.4检查用户的session,返回用户信息63.1.5检查用户的session,并刷新访问时间73.1.6获取用户session中的变量73.1.7用户退出83.2组织维护83.2.1创建组织83.2.2获取组织属性93.2.3修改组织属性103.2.4组织域名分配(添加/删除)113.2.5组织COS分配(添加/修改/删除)113.2.6根据COS获取用户列表123.2.7获取站点所有组织标识列表133.3部门维护133.3.1创建部门133.3.2删除部门143.3.3获取部门属性143.3.4设置部门属性143.4用户维护153.4.1创建用户153.4.2删除用户163.4.3用户属性获取163.4.4用户属性变更173.4.5用户是否存在判定173.4.6别名维护(添加/删除/获取)183.4.7把用户设置为管理员193.4.8修改用户主标识193.4.9用户跨组织移动193.5域名维护203.5.1检查域名或者域名别名是否存在203.5.2列出系统所有域名203.5.3增加域名213.5.4删除域名213.5.5增加域别名213.5.6删除域别名224附录224.1API配置文件说明224.2返回信息表234.3用户属性表24II共 29 页1 Coremail XT API通用函数说明APIContext类提供一个工厂方法,产生一个的客户端连接IClient类型的实例,即API客户端对象。客户端对象可以进行多次调用APIServer的方法,进行操作,操作完成后客户端请求对象 IClient使用close方法关闭连接。同时,IClient类型的实例操作通常返回一个APIContext类型的对象,它记录客户端与API Server之间的连接信息。可以通过APIContext.getRetCode以及APIContext.getResult等方法,获取IClient调用APIServer所得的结果。以下为APIContext所提供的方法:1.1 getClient(连接APIServer使用的socket)public static final IClient getClient(.Socket socket) throws java.io.IOException功能:根据socket获取API客户对象,客户对象可以进行多次API操作,操作完成后请使用 IClient.close() 来关闭连接。请注意, 每个client(socket)只能在一个thread中使用, 如果需要并发请为每个thread申请单独的连接 入口参数:socket连接APIServer使用的socket 返回值类型:客户对象抛出异常类型:java.lang.NullPointerException: 当传入的socket为null java.io.IOException1.2 getRetCode(获取操作的返回值)public final int getRetCode() 功能:获取操作的返回值返回值类型:使用类的静态常量定义(例如:public static final int RC_NORMAL),各自的含义为:RC_NORMAL:操作成功RC_ASSWORD_ERR:用户密码错误RC_SES_ERRORSession: 错误RC_SESID_NOT_FOUND:Session ID 不存在或已经过时RC_USER_EXIST:用户已存在RC_USER_NOT_FOUND:用户不存在1.3 getResult(操作的返回结果)public final java.lang.String getResult()功能:操作的返回结果(只对有返回结果的操作才有意义)返回值类型:请参考各个API函数调用的说明1.4 getResultEx(返回操作的返回结果)public final Object getResultEx()功能: 返回操作的返回结果. 和getResult不同的是, 此方法可以返回其它数据类型. 返回值类型: 操作的返回结果.1.5 getErrorInfo(描述操作失败原因)public final java.lang.String getErrorInfo()功能:操作失败时对操作失败原因的描述字符串返回值类型:失败原因的描述字符串1.6 toString(返回操作结果的字符串表示)public final String toString()功能:返回操作结果的字符串表示返回值类型:操作结果的字符串表示1.7 close(释放连接与资源)public void close() throws java.io.IOException 功能:释放连接,并释放执行中申请的资源抛出异常类型:Java.io.IOException2 API函数的使用步骤配置访问Coremail API 服务器的ip用户通过调用API接口函数进行二次开发前,请用户预先配置好要访问API机器的ip。 如果不设置访问机器的ip,用户将不允许进行API访问。配置方法如下:1. 登录系统管理界面,点击配置管理功能2. 选择配置管理中的“安全配置”如下图,在“允许API访问”一栏中设置好要访问机器的ip使用Coremail XT的API库:1. 将所提供的APIClient.jar添加到的运行环境中(classpath)2. 参考实例程序:APIDemo.java程序过程:1 实例化.Socket 类,建立网络连接2 利用1建立的Socket实例,使用APIContext.getClient(.Socket socket)提供的工厂方法,获取客户端的IClient的对象实例3 用IClient的createUser,changeAttrs,setTimeOut等成员函数执行具体任务,返回APIContext类型的对象,通过APIContext.getRetCode以及APIContext.getResult方法获取返回结果。4 用IClient的实例的close方法关闭连接范例:(可参考APIDemo.java) Socket socket = new Socket(, 9999); IClient client = APIContext.getClient(socket); try APIContext ret = client.createUser(1, a, foo, domain_name=&cos_id=1&user_status=0"a_delta=0); if (ret.getRetCode() = APIContext.RC_NORMAL) System.out.println(User created: ); else System.out.println(User create failed, code= + ret.getRetCode() + , msg= + ret.getErrorInfo(); finally client.close(); 3 Coremail XT API具体功能应用3.1 登录3.1.1 用户登录public APIContext userLogin(java.lang.String userAtDomain) throws java.io.IOException功能:用户登录, 使用所有缺省参数. 入口参数:userAtDomain用户邮件地址: user_iddomain_name返回值类型:操作成功时,返回到APIContext:result的是用户的session ID抛出异常类型:java.io.IOExceptionpublic APIContext userLogin(java.lang.String userAtDomain, java.lang.String language, java.lang.String style, java.lang.String remoteIP, java.lang.String IpCheck, java.lang.String cookieCheck) throws java.io.IOException功能:用户登录, 使用其他参数. 入口参数:userAtDomain用户邮件地址: user_iddomain_namelanguage界面使用的语言style界面风格remote_ip:用户的ip地址(用于webmail的ip 检查)ipcheck:0不检查IP,1检查。不设置则根据系统配置决定是否检查cookiecheck:没有设置本项,或者值为空表示不检查cookie,否则存放web server 设置的cookie变量 Coremail的值(用于安全检查)返回值类型:APIContext的retCode是操作结果,0表示操作成功,其他值代表操作失败,请参考返回信息表。抛出异常类型:java.io.IOException3.1.2 检查用户是否存在public APIContext userExist(java.lang.String userAtDomain) throws java.io.IOException功能:检验用户是否存在入口参数:userAtDomain用户邮件地址: user_iddomain_name返回值类型:APIContext的retCode是操作结果,0表示操作成功,其他值代表操作失败,请参考返回信息表。抛出异常类型:java.io.IOException3.1.3 验证用户密码public APIContext authenticate(java.lang.String userAtDomain, java.lang.String password) throws java.io.IOException功能:验证用户密码. 入口参数: userAtDomain用户邮件地址: user_iddomain_namepassword 用户密码 返回值类型:APIContext的retCode是验证结果,0表示验证通过,35表示验证失败,其它返回值参照说明 。关键错误代码包括:APIContext.RC_USER_NOT_FOUND: 用户不存在APIContext.RC_PASSWORD_ERR: 密码验证失败抛出异常类型:java.io.IOException3.1.4 检查用户的session,返回用户信息public APIContext sesTimeOut(java.lang.String sid) throws java.io.IOException功能:检查用户session,并返回用户的信息. 入口参数:sid 用户session ID返回值类型:操作成功时,返回到APIContext:result的格式为: uid=.&domain_id=.&org_id=.,而uid为userdomain的格式,即用户的邮件地址 关键错误代码包括:APIContext.RC_SESID_NOT_FOUND: session ID 不存在或已经过时APIContext.RC_SES_ERROR 或其它值: 其它的session错误 抛出异常类型:java.io.IOException3.1.5 检查用户的session,并刷新访问时间public APIContext sesRefresh(Stringsid) throws IOException功能:检查用户session,并刷新访问时间.入口参数: Sid用户session id 返回值类型:操作成功时,除了返回值没有其它信息,表示传入的是合法的session,并且已经刷新. 关键错误代码:APIContext.RC_SESID_NOT_FOUND: session id 不存在或已经过时APIContext.RC_SES_ERROR 或其它值: 其它的session错误 操作结果, 见附录的说明抛出异常类型:java.io.IOException3.1.6 获取用户session中的变量public APIContext getSesssionVar(Stringsid,Stringkey) throws IOException功能:获取用户session中的变量.入口参数: Sid用户session id Key 要获取的变量名返回值类型:操作成功时,变量的值直接返回到APIContext:result 关键错误代码: 关键错误代码:APIContext.RC_SESID_NOT_FOUND: session id 不存在或已经过时APIContext.RC_SES_ERROR 或其它值: 其它的session错误 操作结果, 见附录的说明抛出异常类型:java.io.IOException3.1.7 用户退出public APIContext userLogout(java.lang.String sid) throws java.io.IOException功能:结束用户session入口参数:sid 用户session ID返回值类型:APIContext的retCode是操作结果,0表示操作成功,其他值代表操作失败,请参考返回信息表。抛出异常类型:java.io.IOException3.2 组织维护3.2.1 创建组织public APIContext addOrg(StringorgId,Stringattrs) throws IOException功能:创建企业组织入口参数: orgId - String 企业ID attrs - String 企业属性串 attrs的格式,&号分隔的key=value,例如: cos_id=1&number_of_classes=100. 可用属性(可选)如下表: 属性名 属性含义 org_name 企业名称, 如果不提供则 org_name=OrgID domain_name 企业的许可域名。如果是不存在的域名会先自动创建域名 res_grp_id 资源组ID, 如果不填则使用programs/RmiServer/APIDefaultRes下的配置值 cos_id 创建企业时可指定一个COS ID, 并分配数量。 缺省取programs/RmiServer/APIDefaultCos下的配置值(配置值用cos_name指定COS) num_of_classes 指定的COS ID类型用户数限制, org_assignable_quota 可分配容量 org_status 企业状态(0正常1暂停2锁定) org_expiry_date 过期日期。NULL或者空表示不过期。 格式为: yyyy-mm-dd org_address 地址 org_phone_number 电话 org_contact 联系人 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.2.2 获取组织属性public APIContext getOrgInfo(StringorgId, Stringattrs) throws IOException功能:获取企业组织属性入口参数: orgId - String 企业ID attrs - String 企业属性串 可修改属性 属性名 属性含义 org_name 企业名称 org_assignable_quota 可分配容量 org_status 企业状态(0正常1暂停2锁定) org_expiry_date 过期日期。NULL或者空表示不过期。 格式为: yyyy-mm-dd org_address 地址 org_phone_number 电话 org_contact 联系人 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.2.3 修改组织属性public APIContext alterOrg(StringorgId,Stringattrs) throws IOException功能:修改企业组织属性入口参数: orgId - String 企业ID attrs - String 企业属性串 可获取属性(可选)如下表: 属性名 属性含义 org_name 企业名称 domain_name 企业的许可域名列表, 以逗号,分隔 res_grp_id 资源组ID org_assignable_quota 可分配容量 org_status 企业状态(0正常1暂停2锁定) org_expiry_date 过期日期。NULL或者空表示不过期。格式为: yyyy-mm-dd org_address 地址 org_phone_number 电话 org_contact 联系人 not_used_quota 此ORG还剩余的容量,单位M 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.2.4 组织域名分配(添加/删除)public APIContext addOrgDomain(StringorgId,StringdomainName) throws IOException功能:添加组织企业的许可域名入口参数: orgId - 企业ID domainName - 要分配的许可域名 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOExceptionpublic APIContext delOrgDomain(StringorgId,StringdomainName) throws IOException功能:添加组织企业的许可域名入口参数: orgId - 企业ID domainName - 要分配的许可域名 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.2.5 组织COS分配(添加/修改/删除)public APIContext addOrgCos(StringorgId,StringcosName,intcount) throws IOException功能:为指定组织企业添加一种COS(服务等级).入口参数: orgId - 企业ID cosName - 服务等级名称 count - 该服务等级的用户数 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOExceptionpublic APIContext alterOrgCos(StringorgId,StringcosName,intcount) throws IOException功能:修改指定组织企业一种COS(服务等级).入口参数: orgId - 企业ID cosName - 服务等级名称 count - 该服务等级的用户数 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOExceptionpublic APIContext delOrgCos(StringorgId,StringcosName) throws IOException功能:删除指定组织企业一种COS(服务等级).入口参数: orgId - 企业ID cosName - 服务等级名称 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.2.6 根据COS获取用户列表public APIContext getOrgCosUser(StringorgId,intcosId) throws IOException功能:列出指定企业某服务等级(COS)下的所有用户名列表.入口参数: orgId - 企业ID cosId - 服务等级ID 返回值类型:用户名不包含“domain信息操作成功时,返回到APIContext:result为要获取的用户列表,,分隔,如user1,user2,user3操作结果, 见附录的说明抛出异常类型:java.io.IOException3.2.7 获取站点所有组织标识列表public APIContext getOrgList() throws IOException功能:列出所有企业ID.返回值类型:操作成功时,返回到APIContext:result为要获取的用户列表,,分隔,如user1,user2,user3操作结果, 见附录的说明抛出异常类型:java.io.IOException3.3 部门维护3.3.1 创建部门public APIContext addUnit(StringorgId,StringouId,Stringattrs) throws IOException功能:创建企业部门。 如果不设置 parent_org_unit_id 属性则表示创建直属部门。入口参数: orgId - 企业ID ouId - 部门ID attrs - 要设置的部门属性, parent_org_unit_id 设置上级 部门的ID, org_unit_name 设置部门名称返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.3.2 删除部门public APIContext delUnit(StringorgId,StringouId) throws IOException功能:删除组织企业部门。入口参数: orgId - 企业ID ouId - 部门ID 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.3.3 获取部门属性public APIContext getUnit(StringorgId,StringouId,Stringattrs) throws IOException功能:获取企业部门信息。 如果不设置 parent_org_unit_id 属性则表示创建直属部门。入口参数: orgId - 企业ID ouId - 部门ID attrs -要获取的部门属性, parent_org_unit_id 获取上级 部门的ID, org_unit_name 获取部门名称返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.3.4 设置部门属性public APIContext setUnit(StringorgId,StringouId,Stringattrs) throws IOException功能:设置组织企业部门。如果设置 parent_org_unit_id 属性则相当于移动部门, 如果想移动到根成为直属部门, 可以使用 parent_org_unit_id= 作为 attrs 参数。例如:要想部门在排序中排在前面,则须设置 org_unit_list_rank =,排序以数字大的优先,即数字越大,排位越靠前。入口参数: orgId - 企业ID ouId - 部门ID attrs - 要设置的部门属性, parent_org_unit_id 设置上级 部门的ID, org_unit_name 设置部门名称返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.4 用户维护3.4.1 创建用户public APIContext createUser(java.lang.String providerId, java.lang.String orgId, java.lang.String userId, java.lang.String attrs) throws java.io.IOException功能:创建用户入口参数:providerId 用户的provider id, 必须为存在的provider,属性password如果不设置将使用缺省值为随机密码orgId 用户的企业id, 必须为存在的企业userId用户id, 满足rfc规定的用户名attrs用户的其它属性,如:domain_name=163.com&user_status=0&cos_id=1"a_delta=0,属性值中如果有特殊字符必须用URL的方式编码, 如等于号 = 编码为 %3C。welcome_index 用户可通过传递welcome_index参数配置是否发送欢迎信,如:当不传递 welcome_index 或者传递 welcome_index=-1 (任意小于等于0的值),都会发送普通的欢迎信;而当传递 welcome_index=1 时发送Welcome1 对应的欢迎信,其他大于0的值welcome_index都不发送欢迎信。返回值类型:APIContext的retCode是操作结果,0表示操作成功,其他值代表操作失败,请参考返回信息表。抛出异常类型:java.io.IOException3.4.2 删除用户public APIContext deleteUser(java.lang.String userAtDomain) throws java.io.IOException功能:删除用户入口参数:userAtDomain用户邮件地址: user_iddomain_name 返回值类型:APIContext的retCode是操作结果,0表示操作成功,其他值代表操作失败,请参考返回信息表。关键错误代码包括:APIContext.RC_USER_NOT_FOUND: 用户不存在抛出异常类型:java.io.IOException3.4.3 用户属性获取public APIContext getAttrs(java.lang.String userAtDomain, java.lang.String attrs) throws java.io.IOException功能:获取用户属性. 入口参数:userAtDomain 用户邮件地址: user_iddomain_nameattrs 要获取的用户属性(说明), 只有名称, 属性值可以为空例如:truename="a_delta= 。返回值类型:操作成功时,返回到APIContext:result为encode的用户属性字符串,如: truename=abc"a_delta=100 APIContext的retCode是操作结果,0表示操作成功,其它返回值参照说明。关键错误代码包括:APIContext.RC_USER_NOT_FOUND: 用户不存在抛出异常类型:java.io.IOException3.4.4 用户属性变更public APIContext changeAttrs(java.lang.String userAtDomain, java.lang.String attrs) throws java.io.IOException功能:设置用户属性. 入口参数:userAtDomain 用户邮件地址: user_iddomain_nameattrs用户的其它属性,如:domain_name=163.com&user_status=0&cos_id=1"a_delta=0,属性值中如果有特殊字符必须用URL的方式编码, 如等于号 = 编码为 %3C。例如:如果用户在排序中排在前面,可以设置“user_list_rank=”,排序以数字大的优先,即数字越大,排位越靠前。返回值类型:APIContext的retCode是操作结果,0表示操作成功,其他值代表操作失败,请参考返回信息表。抛出异常类型:java.io.IOException3.4.5 用户是否存在判定public APIContext userExist(java.lang.String userAtDomain) throws java.io.IOException功能: 检验用户是否存在入口参数:userAtDomain 用户邮件地址: user_iddomain_name返回值类型:APIContext的retCode是操作结果,0表示操作成功,其他值代表操作失败,请参考返回信息表。抛出异常类型:java.io.IOException3.4.6 别名维护(添加/删除/获取)public APIContext addDomainAlias(StringdomainName,StringaliasName) throws IOException功能:增加指定域的别名入口参数: domainName - 域名 aliasName - 要增加的域名别名返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOExceptionpublic APIContext delDomainAlias(StringdomainName,StringaliasName) throws IOException功能:删除指定域的别名入口参数: domainName - 域名 aliasName - 要删除的域名别名返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOExceptionpublic APIContext getDomainAlias(StringdomainName) throws IOException功能:列出指定域的所有域名别名入口参数: domainName - 域名 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.4.7 把用户设置为管理员public APIContext setOA(String userAtDomain) throws IOException功能:设置指定用户为企业管理员入口参数: userAtDomain 用户名 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.4.8 修改用户主标识public APIContext renameUser(String userAtDomain,String newUserID) throws IOException功能:修改用户ID入口参数: userAtDomain 用户名 newUserId - 新的用户ID 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.4.9 用户跨组织移动public APIContext moveUser(String userAtDomain,String attrs) throws IOException功能:用户跨组织移动入口参数: userAtDomain 用户名 attrs - 用户新位置/属性返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.5 域名维护3.5.1 检查域名或者域名别名是否存在public APIContext domainExist (String DomainName) throws IOException功能:检查域名或者域名别名是否存在入口参数: DomainName 要检查的域名或者域名别名 返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.5.2 列出系统所有域名public APIContext getDomainList() throws IOException功能:列出系统中所有的域名操作成功时,返回到APIContext:result为域名列表,分隔 如:,返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.5.3 增加域名public APIContext addDomain25 (String DomainName) throws IOException功能:增加指定的域名入口参数: DomainName 域名返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.5.4 删除域名public APIContext delDomain25 (String DomainName) throws IOException功能:删除指定的域名入口参数: DomainName 要删除的域名返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.5.5 增加域别名public APIContext addDomainAlias (String DomainName,StringaliasName) throws IOException功能:增加指定域名别名入口参数: DomainName 域名aliasName - 要增加的域名别名返回值类型:操作结果, 见附录的说明抛出异常类型:java.io.IOException3.5.6 删除域别名public APIConte

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论