php 捕获notice,workerman中捕获notice错误并抛出异常

在workerman中出现了notice错误并不会中断程序运行,这是抛出一个无关紧要的提示,这显然与我们的程序设计初衷不符。

例如我们去获取数组中的一个key-value值,当key不存在的时候只是提示一个notice,而我们要把这个弄成一个异常。

研究了一下,set_error_handler方法可以实现我们想要的功能,来看一下代码吧。

在events.php中的代码<?php

/**

* 用于检测业务代码死循环或者长时间阻塞等问题

* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload

* 然后观察一段时间workerman.log看是否有process_timeout异常

*/

//declare(ticks=1);

use App\Service\MemberService;

use App\Service\InterviewService;

use \GatewayWorker\Lib\Gateway;

use think\facade\Db;

use \App\Library\MyException;

use  \App\Library\Rdb;

define('ping', 1);//ping 心跳  返回1

define('bind', 2);//bind 绑定  返回2

define('interview_admin_bind', 999);//集合室后台管理账户绑定

define('interview_member_join', 1001);//集合室-用户进入集合室

define('interview_member_leave', 1002);//集合室-用户离开集合室

define('interview_change_attribute', 1011);//集合室切换fixed 自由座位 和固定座位

define('interview_seat_order', 1012);//集合室座位排序

define('interview_seat_order_rand', 1013);//集合室座位排序-随机

define('interview_seat_change', 1014);//集合室座位排序-交换

define('interview_member_ban', 1015);//集合室-踢出用户

define('interview_member_voice', 1016);//集合室-用户禁言

define('interview_topic', 1017);//集合室出题

define('interview_voice_order', 1018);//传递麦序

define('interview_update', 1050);//集合室-更新频道属性

define('interview_send_msg', 1051);//集合室发送消息

class Events

{

use \App\Library\Tools;

public static function onWorkerStart()

{

\set_error_handler(function ($type, $msg) {

var_dump($type, $msg);

throw new MyException(400, $msg);

}, E_NOTICE);

Db::setConfig(\App\Config\Config::$db_config);

Rdb::getInstance()->flushAll();

}

public static function onConnect($client_id)

{

}

public static function onMessage($client_id, $message)

{

try {

$message = json_decode($message, true);

if (!is_array($message))

return Gateway::sendToCurrentClient(self::error(400, '参数类型错误'));

if ($message['type'] > 1000 and !isset($_SESSION['member_id'])) {

return Gateway::closeClient($client_id, self::error(400, '未登录'));

}

switch ($message['type']) {

case interview_admin_bind:

InterviewService::admin_bind($client_id, $message);

break;

case interview_voice_order:

InterviewService::voice_order($client_id, $message);

break;

case interview_topic:

InterviewService::topic($client_id, $message);

break;

case interview_member_voice:

InterviewService::member_voice($client_id, $message);

break;

case interview_member_ban:

InterviewService::member_ban($client_id, $message);

break;

case interview_seat_change:

InterviewService::seat_change($client_id, $message);

break;

case interview_seat_order_rand:

InterviewService::seat_order_rand($client_id, $message);

break;

case interview_seat_order:

InterviewService::seat_order($client_id, $message);

break;

case interview_send_msg:

InterviewService::send_msg($client_id, $message);

break;

case interview_change_attribute:

InterviewService::change_attribute($client_id, $message);

break;

case interview_update:

InterviewService::update($client_id, $message);

break;

case interview_member_leave:

InterviewService::leave($client_id);

break;

case interview_member_join:

InterviewService::join($client_id, $_SESSION['member_id'], $_SESSION['member'], $message);

break;

case bind:

MemberService::bind($client_id, $message);

break;

default :

return Gateway::sendToCurrentClient(self::success(1));

break;

}

} catch (Throwable $exception) {

if ($exception instanceof MyException) {

return Gateway::sendToCurrentClient(self::error($exception->type, $exception->getMessage(), $exception->getCode(), $exception->data));

} else {

return Gateway::sendToCurrentClient(self::error(400, $exception->getMessage()));

}

}

}

public static function onClose($client_id)

{

InterviewService::leave($client_id);

}

}

Events.php文件主要看onMessage回调,我们通过传递给服务器的不同type参数作为路由凭据,然后调用不同的方法,处理业务。

在最外层有一个try catch来捕捉异常。注意是捕捉的Throwable 。这是Exception和Error两个不同异常的父类接口,但是并不包含notice和warning这类的错误,所以不能捕获。

所以一旦出现了这类错误并不会中断掉程序,那么要来判断例如key-value是否存在的这类情况就太痛苦了,到处都是isset。。。

public static function onWorkerStart()

{

\set_error_handler(function ($type, $msg) {

var_dump($type, $msg);

throw new MyException(400, $msg);

}, E_NOTICE);

Db::setConfig(\App\Config\Config::$db_config);

Rdb::getInstance()->flushAll();

}

在来分析一下onWorkerStart()方法中,我们用set_error_handler来设置E_NOTICE类型的错误交给一个闭包来处理,该闭包抛出一个MyExcepetion异常,这个异常就是继承了Throwable接口,是可以被正常捕获的。同时中断程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Java,当程序出现异常时,可以使用throws关键字抛出该异常异常被抛出之后,可以在调用此方法的地方使用try-catch语句来捕获并处理该异常。 例如: ``` public class Test { public void method1() throws Exception { throw new Exception("An exception occurred"); } public static void main(String[] args) { Test test = new Test(); try { test.method1(); } catch (Exception e) { System.out.println("An exception was caught: " + e.getMessage()); } } } ``` 上面的代码,method1()方法抛出了一个Exception异常,在main()方法使用try-catch语句捕获并处理该异常。 注意,如果一个方法抛出异常,它的调用者需要使用try-catch语句或者在它的方法声明使用throws来捕获和处理该异常。 ### 回答2: Java异常处理的throws关键字是一种将异常抛出的方法。当我们使用throws关键字时,我们可以将异常从一个方法传递到另一个方法或类,以便在这些方法或类异常进行处理或捕获。 throws关键字的作用是通知调用者或调用链的其他方法,在当前方法可能会抛出异常,以便在调用者或调用链的方法进行处理。这种处理方式比较适用于多层调用的情况,因为这样可以让异常从底层方法向上层调用链传递,直到被处理或抛到最上层,如果到了最上层都没有被处理,那么程序将会终止。 当我们使用throws关键字时,需要在抛出异常的方法明确声明可能会抛出的异常类型。例如,我们可以使用throws关键字将IOException从一个方法抛出如下: public void readFile() throws IOException { //read file code } 在这个方法,我们明确声明了IOException异常可能会被抛出。这样,当这个方法被调用的时候,在方法体内部可能会抛出IOException的代码就可以被包装在try-catch块或者再使用throws关键字将此异常抛给上层方法。 在对抛出异常进行处理时,我们可以使用try-catch块捕获异常,也可以再次通过throws将异常抛给上层方法。但是,在处理异常的过程,我们需要注意以下几点: 1. 如果使用throws将异常抛给上层方法,在上层方法应该继续进行异常处理,否则程序将会终止。 2. 在进行异常处理时,应该根据具体的业务场景来选择合适的处理方式,例如,可以通过记录日志来及时发现和解决异常问题。 3. 在捕获异常时,应该尽可能地减少代码的执行,以便在出现问题时及时发现并解决。 总之,throws关键字是Java异常处理非常重要的语法结构之一,它能够使程序更加健壮和安全。但是,在实际使用时,我们需要根据具体的业务需求和代码逻辑来合理使用,并注意异常处理的规范和安全性。 ### 回答3: Java异常处理是Java编程一个非常重要的方面。异常处理通过try-catch块来捕获和处理异常。而throws语句则是用于在方法签名指明该方法可能会抛出的异常。本文将重点探讨throws语句的使用。 当一个方法可能会抛出异常时,使用throws语句来声明异常是一个非常好的编程习惯。使用throws语句,可以将控制权交给方法的调用者来处理异常,而不是在方法内部处理异常。使用throws语句,可以使代码更加清晰,也可以提高代码的重用性。 下面是一个简单的例子: ```java public void readFile(String path) throws FileNotFoundException { File file = new File(path); Scanner scanner = new Scanner(file); while(scanner.hasNextLine()) { System.out.println(scanner.nextLine()); } scanner.close(); } ``` 在这个例子,readFile方法可能会抛出FileNotFoundException异常。因此,在方法签名使用了throws语句来声明这个异常。当调用这个方法时,调用者可以选择捕获这个异常或者再将这个异常抛出给更高级的调用者。 调用readFile方法的代码可以像这样: ```java public static void main(String[] args) { String path = "input.txt"; try { readFile(path); //调用方法 } catch (FileNotFoundException e) { System.out.println("文件不存在!"); } } ``` 在这个例子,调用readFile方法时,在try块调用。如果readFile方法抛出FileNotFoundException异常,会被catch块捕获并输出错误信息。这样,程序就不会在运行过程抛出未捕获异常。 总之,在Java开发过程,使用throws语句来声明异常是一个非常重要的语言特性。这样可以使代码更加清晰,也可以提高代码的重用性。同时,在调用带有throws语句的方法时,需要在调用代码处处理可能抛出的异常

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值