GVKun编程网logo

PHP10 错误和异常处理(php异常处理和错误处理)

14

对于想了解PHP10错误和异常处理的读者,本文将提供新的信息,我们将详细介绍php异常处理和错误处理,并且为您提供关于.NET----错误和异常处理机制、Go中的错误和异常处理最佳实践、JavaJSP

对于想了解PHP10 错误和异常处理的读者,本文将提供新的信息,我们将详细介绍php异常处理和错误处理,并且为您提供关于.NET---- 错误和异常处理机制、Go中的错误和异常处理最佳实践、Java JSP 异常处理:处理错误和异常、Koa入门教程[3]-错误和异常处理的有价值信息。

本文目录一览:

PHP10 错误和异常处理(php异常处理和错误处理)

PHP10 错误和异常处理(php异常处理和错误处理)

学习要点

  • 修改错误报告级别
  • 写错误日志
  • 异常处理实现
  • 自定义异常
  • 捕获多路异常

 

错误处理

定义

  • 错误:开发过程中的失误、用户操作引起的错误。
  • 错误产生原因
  1. 语法错误:开发环境提示,未修正则脚本无法运行。
  2. 运行时错误:脚本无法正确运行。例如双引号字符串对变量的解析。
  3. 逻辑错误:常见的逻辑运算错误,循环条件设置错误等等。

错误报告级别

1、WAMP 作为开发环境,在 php.ini 配置文件中,有两个参数设置:

  • display_errors = on

    注释:PHP 解析器将会输出错误报告的功能。如果是产品正式发布部署,需要在 PHP 服务器上把此项值值为 off。

  • error_reporting = E_ALL

    注释:PHP 解析器将输出每个错误。

 

2、PHP 的错误报告级别:

常量

描述

1

E_ERROR

Fatal run-time errors. Errors that can not be recovered from. Execution of the script is halted

2

E_WARNING

Non-fatal run-time errors. Execution of the script is not halted

4

E_PARSE

Compile-time parse errors. Parse errors should only be generated by the parser

8

E_NOTICE

Run-time notices. The script found something that might be an error, but could also happen when running a script normally

16

E_CORE_ERROR

Fatal errors at PHP startup. This is like an E_ERROR in the PHP core

32

E_CORE_WARNING

Non-fatal errors at PHP startup. This is like an E_WARNING in the PHP core

64

E_COMPILE_ERROR

Fatal compile-time errors. This is like an E_ERROR generated by the Zend Scripting Engine

128

E_COMPILE_WARNING

Non-fatal compile-time errors. This is like an E_WARNING generated by the Zend Scripting Engine

256

E_USER_ERROR

Fatal user-generated error. This is like an E_ERROR set by the programmer using the PHP function trigger_error()

512

E_USER_WARNING

Non-fatal user-generated warning. This is like an E_WARNING set by the programmer using the PHP function trigger_error()

1024

E_USER_NOTICE

User-generated notice. This is like an E_NOTICE set by the programmer using the PHP function trigger_error()

2048

E_STRICT

Run-time notices. PHP suggest changes to your code to help interoperability and compatibility of the code

4096

E_RECOVERABLE_ERROR

Catchable fatal error. This is like an E_ERROR but can be caught by a user defined handle (see also set_error_handler())

8191

E_ALL

All errors and warnings, except level E_STRICT (E_STRICT will be part of E_ALL as of PHP 6.0)

3、开启错误报告

处理在 php.ini 文件中配置,如果对服务器权限不够,可以采用 ini_set () 函数设置:

例如:

ini_set(‘display_errors’,1);

  

 

调整错误报告级别

1、在 php.ini 中修改配置指令 error_reporting 的值

默认值:

error_reporting = E_ALL

修改示例 1(结合位运算符 &,|,~):除运行时注意消息外的全部错误报告

error_reporting = E_ALL&~E-NOTICE;

修改示例 2:只考虑运行时错误、解析错误、核心错误

error_reporting = E_ERROR | E_PARSE | E_CORE_ERROR

   

2、在脚本中使用 error_reporting () 函数

  权限不够,或者需要个性化页面错误报告,采用该函数。

error_reporting(0);     //完全关闭错误报告

error_reporting(E_ALL);    //报告任何错误

error_reporting(E_ALL&~E_NOTICE);    //报告除注意外的任何错误

  

示例:

/* 开启php.ini中的display_errors指令*/

       ini_set ( ''display_errors'', 1);

       /* 通过error_reporting()函数设置在本脚本中,输出所有级别的错误报告 */

       error_reporting ( E_ALL );

//error_reporting ( E_ALL &~(E_WARNING|E_NOTICE));     

       /* “注意(notice)”的报告,不会阻止脚本的执行,并且可能不一定是一个问题 */

       getType ( $var ); // 调用函数时提供的参数变量没有在之前声明    

       /* “警告(warning)”的报告,指示一个问题,但是不会阻止脚本的执行 */

       getType (); // 调用函数时没有提供必要的参数     

       /* “错误(error)”的报告,它会终止程序,脚本不会再向下执行 */

    get_Type (); // 调用一个没有被定义的函数

  

使用 trigger_error () 函数代替 die () 函数

die () 等同于 exit (),会退出程序。而 trigger_error () 可以生成一个用户警告来代替退出程序。

示例代码:

//die("程序运行结束!");

trigger_error("there is a bugbugbug!",E_USER_WARNING);

echo "这里是php文件尾巴";

  

自定义错误处理

1、需要自定义错误信息的情形

    • 记录错误信息
    • 屏蔽错误信息
    • 错误统一输出页面处理或者同一页面位置输出错误信息
    • 调试

2、如何自定义错误处理

用户自定义错误处理函数:set_error_handler ()

语法格式:

mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )

  

参数说明:

error_handler:

handler (int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext]]] )  // 四个参数含义:错误级别、错误信息、错误所在文件,错误所在文件第几行

error_types:

错误报告级别。默认 E_ALL。

示例代码:

// 屏蔽所有错误报告

error_reporting ( 0 );

function error_handler($error_level, $error_message, $file, $line) {

   $EXIT = false;

   $error_type='''';

   switch ($error_level) {

      //提醒

      case E_NOTICE :

      case E_USER_NOTICE :

         $error_type = ''Notice'';

         break;

      //警告

      case E_WARNING :

      case E_USER_WARNING :

         $error_type = ''Warning'';

         break;

      //错误

      case E_ERROR :

      case E_USER_ERROR :

         $error_type = ''Fatal Error'';

         break;

      //未知错误

      default:

         $error_type = ''Unknown'';

         $EXIT=true;

         break;

   }

  

   //打印错误信息,可以自定义错误格式

   printf("%s,%s,%s,%d",$error_type,$error_message,$file,$line);

   if(true==$EXIT){

      echo ''<script>location="error.php";</script>'';

   }

}

 

set_error_handler(''error_handler'');

//echo $novar;

echo 3/0;

  

注意:

1、set_error_handler () 不处理以下错误报告:E_ERR0R、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING。不处理不等于不显示错误信息,它不会按照用户设定格式显示。

2、除了第 1 条中列出的错误,在使用了 set_error_handler () 函数后,所有的错误都交给用户处理。

上机练习 1:自定义错误处理

1、  set_error_handler () 函数的用法

2、  自定义回调函数

3、  错误报告格式:

 

写错误日志

PHP 项目部署运行后,一般 display_errors = off。程序日常运行的错误信息是需要记录下来,作为运维参考,如何处理?有两种记录日志的方式:

1、使用指定的文件记录错误报告日志

php.ini 配置

error_reporting = E_ALL

display_errors = off

log_errors=on

log_errors_max_len = 1024

error_log = "d:/wamp/logs/php_error.log"

error_log () 函数

//写入操作系统日志 (需要php.ini中设置error_log=syslog)

error_log("error message",0);

//发送到电子邮件(需要邮件服务器)

error_log("error message",1,"2083967667@qq.com");

//发送到某个ip的某个端口

error_log("error message",2,"localhost:5000");

//写入到某个路径文件中

error_log("error message",3,"er.log");

  

2、错误信息记录到操作系统日志中

php.ini 配置

error_reporting = E_ALL

display_errors = off

log_errors=on

log_errors_max_len = 1024

error_log = syslog

使用 syslog 向系统发送订制消息

//php5.3开始,已经废除相关函数

define_syslog_variables();

……

  

 

异常处理

定义

Exception:在程序执行过程中出现的一个例外或是一个事件,它中断了正常指令的运行,跳转到其他程序模块继续执行。

简单异常处理

1、语法结构

try{

//需要捕获异常的代码块

}catch (Exception $ex1){

//处理异常

} finally {

//始终被执行的代码

}

  

2、示例代码

 

try {

   $number = 100;

   $div = 0;

   if ($div == 0) {

      throw new Exception ( "除数不能为0" );

   }

   $result=$number/$div;

   echo ''计算结果''.$result;

} catch ( Exception $e ) {

   echo ''程序异常:''.$e->getMessage();

}finally {

   echo ''<br>finally代码始终执行'';

}

echo ''<br>程序继续执行'';

  

自定义异常处理类

1、内置 Exception 类结构

class Exception {

 

   protected $message = ''Unknown exception''; // 异常信息

   protected $code = 0; // 用户自定义异常代码

   protected $file; // 发生异常的文件名

   protected $line; // 发生异常的代码行号

 

   function __construct($message = null, $code = 0);

 

   final function getMessage(); // 返回异常信息

   final function getCode(); // 返回异常代码

   final function getFile(); // 返回发生异常的文件名

   final function getLine(); // 返回发生异常的代码行号

   final function getTrace(); // backtrace() 数组

   final function getTraceAsString(); // 已格成化成字符串的 getTrace() 信息

   /* 可重载的方法 */

   function __toString(); // 可输出的字符串

}

  

2、自定义异常处理类

/* 自定义异常处理类 */

class MyException extends Exception {

   // 重写构造函数

   public function __construct($message, $code = 0) {

      parent::__construct ( $message, $code );

   }

  

   /*重写父类__toString魔术方法*/

   public function __toString() {

      return __CLASS__ . ":[" . $this->code . "]:" . $this->message . "<br>";

   }

  

   /*自定义异常方法*/

   public function customFunction() {

      echo "按自定义的方法处理出现的这个类型的异常<br>";

   }

}

 

try {

   $error = ''允许抛出这个错误'';

   throw new MyException ( $error );

   echo ''出现异常,不被执行的代码.....'';

} catch ( MyException $e ) {

   echo ''捕获异常: '' . $e;

   $e->customFunction ();

}

echo ''程序继续执行......'';

  

 

上机练习 2:自定义异常处理

 

多路异常捕获

class MyException extends Exception {

   public function __construct($message, $code = 0) {

      parent::__construct ( $message, $code );

   }

   public function __toString() {

      return __CLASS__ . ":[" . $this->code . "]:" . $this->message . "<br>";

   }

   public function customFunction() {

      echo "按自定义的方法处理出现的这个类型的异常";

   }

}

 

class TestException {

   public $var;

   function __construct($value = 0) {

      switch ($value) {

         case 1 :

            throw new MyException ( "传入的值“1” 是一个无效的参数", 5 );

            break;

         case 2 :

            throw new Exception ( "传入的值“2”不允许作为一个参数", 6 );

            break;

         default :

            $this->var = $value;

            break;

      }

   }

}

// 示例1,在没有异常时,程序正常执行,try中的代码全部执行并不会执行任何catch区块

$testObj=null;

try {

   $testObj = new TestException (); // 使用默认参数创建异常的测试类对象

   echo "***********<br>"; // 没有抛出异常这条语句就会正常执行

} catch ( MyException $e ) { // 捕获用户自定义的异常区块

   echo "捕获自定义的异常:$e <br>"; // 按自定义的方式输出异常消息

   $e->customFunction (); // 可以调用自定义的异常处理方法

} catch ( Exception $e ) { // 捕获PHP内置的异常处理类的对象

   echo "捕获默认的异常:" . $e->getMessage () . "<br>"; // 输出异常消息

}

var_dump ( $testObj ); // 判断对象是否创建成功,如果没有任何异常,则创建成功

                   

// 示例2,抛出自定义的异常,并通过自定义的异常处理类捕获这个异常并处理

$testObj1=null;

try {

   $testObj1 = new TestException ( 1 ); // 传入参数1时,创建测试类对象抛出自定义异常

   echo "***********<br>"; // 这个语句不会被执行

} catch ( MyException $e ) { // 这个catch区块中的代码将被执行

   echo "捕获自定义的异常:$e <br>";

   $e->customFunction ();

} catch ( Exception $e ) { // 这个catch区块不会执行

   echo "捕获默认的异常:" . $e->getMessage () . "<br>";

}

var_dump ( $testObj1 ); // 有异常产生,这个对象没有创建成功

                    

//示例2,抛出内置的异常,并通过自定义的异常处理类捕获这个异常并处理

$testObj2=null;

try {

   $testObj2 = new TestException ( 2 ); // 传入参数2时,创建测试类对象抛出内置异常

   echo "***********<br>"; // 这个语句不会被执行

} catch ( MyException $e ) { // 这个catch区块不会执行

   echo "捕获自定义的异常:$e <br>";

   $e->customFunction ();

} catch ( Exception $e ) { // 这个catch区块中的代码将被执行

   echo "捕获默认的异常:" . $e->getMessage () . "<br>";

}

var_dump ( $testObj2 ); // 有异常产生,这个对象没有创建成功

  

.NET---- 错误和异常处理机制

.NET---- 错误和异常处理机制

前言

  错误的出现并不总是编写程序的人的原因,有时应用程序会因为应用程序的最终用户引发的动作或运行代码的环境发生错误。无论如何,我们都应预测应用程序中出现的错误,并相应的进行编码。

  .Net 改进了处理错误的方式。C# 处理错误的机制可以为每种错误提供自定义处理方式,并把识别错误的代码与处理错误的代码分别开来。

异常类

  在 C# 中当出现某个特殊的异常错误条件时,就会创建抛出一个异常对象,这个对象包含有助于跟踪问题的信息。.Net 提供了许多预定义的异常类,我们下面看看一些常见特别的异常类吧(异常类太多了,这里就介绍几个常见的)。

  对于.Net 类,一般的异常类 System.Exception 派生自 System.Object, 通常不在代码中抛出 System.Exception 泛型对象,因为他们无法确定错误情况的本质。

  在该层次中有两个重要的类,他们派生自 System.Exception 类:

    •  SystemException------ 该类用于通常由.NET 允许库抛出的异常,或者由几乎所有的应用程序抛出的异常。例如,如果.NET 运行库检测到栈已满,他就会抛出 StackOverflowException 异常。另一方面,如果检测到调用方法时参数不对,就可以在自己的代码中选择抛出 ArgumentException 异常或其子类。SystemException 异常的子类包括表示致命错误和非致命错误的异常。
    •  ApplicationException---- 在.NET Framework 最初的设计中,是打算把这个类作为自定义应用程序异常类的基类的。不过,CLR 抛出的一些异常类也派生自这个类。应用程序抛出的异常则派生自 SystemException。因此从 ApplicationException 派生自自定义异常类型没有任何好处,取而代之的是,可以直接从 Exception 基类派生自定义异常类。

  其他可能会用到的异常类包括:

    •  StackOverflowException------- 如果分配给栈的内存区域已满,就会抛出这个异常。如果一个方法连续地递归调用自己,就可能发生栈溢出。这一般是一个致命错误,因为它禁止应用程序执行除了中断以外的其他任务。在这种情况下,甚至也不可能执行到 finally 块。通常用户自己不能处理像这样的错误,而应退出应用程序。
    •  EndOfStreamException------- 这个异常通常是因为读到文件末尾而抛出的,流表示数据源之间的数据流。
    •  OverflowException----- 如果要在 checked 上下文中把包含 - 40 的 int 类型数据强制转换为 uint 数据,就会抛出这个异常
    •  MemberAccessException---------- 该类用于处理访问类的成员失败时所引发的异常。失败的原因可能的原因是没有足够的访问权限,也可能是要访问的成员根本不存在(类与类之间调用时常用)
    •  IndexOutOfException------- 该类用于处理下标超出了数组长度所引发的异常

使用 try...catch...finally 捕获异常

  • try 块包含的代码组成了程序的正常操作部分,但这部分程序可能会遇到某些严重的错误。
  • catch 块包含的代码处理各种错误,这些错误是执行 try 块中的代码时遇到的问题。这个快可以用来记录错误。
  • finally 快包含的代码清理资源或执行通常要在 try 块或者 catch 块末尾执行的其他操作。无论是否抛出异常,都会执行 finally 块。finally 块中防止 return 语句,编译器会标记一个错误。另外此块可以如果没有需要关闭或者处理的其他操作可以省略此块。

 

  异常处理具有性能含义,在常见的情况下,不应该使用异常处理错误。应尽量编写好避免错误出现的代码。

  在异常捕获中,我们可以实现多个 catch 块来针对不同的错误做出对应的错误处理。下面我们看一个例子:

class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                try
                {
                    string userInput;
                    Console.WriteLine("请输入0-5之间任意一个数字:");
                    userInput = Console.ReadLine();
                    if (string.IsNullOrWhiteSpace(userInput))
                    {
                        break;
                    }


                    if (int.TryParse(userInput, out int index))
                    {
                        if (index < 0 || index > 5)
                        {

                            throw new IndexOutOfRangeException($"你输入的数字是{index}");

                        }
                        Console.WriteLine($"你输入的数字是{index}");
                    }
                    else
                    {
                        throw new Exception("请输入数字");
                    }
                }
                catch (IndexOutOfRangeException ex)
                {
                    Console.WriteLine($"你输入的数字不在此范围内.{ex.Message}");
                }
                catch (Exception ex)
                {

                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    Console.WriteLine("谢谢合作");
                }

               
            }
        }
    }

 

  在此事例中,定义了两个 catch 块。如果输入的超过规定返回的数字,则会抛出超出范围的错误也就进入对应的 catch 块。而输入的非数字也就进入了另外一个 catch 块进行处理。

  下面我们看一看关于 System.Exception 属性。熟悉了解其中熟悉能更好的去观察理解抛出的异常错误。


  

过滤异常、创建用户定义的异常

  自从 C#6 开始就支持异常过滤器。Catch 块仅在过滤器但会 true 时执行。捕获不同的异常类型时,可以有行为不同的代码块。在某些情况下,catch 块基于异常的内容执行不同的操作。下面我们看下如何来使用异常过滤器吧:

public class MyIndexOutOfException :SystemException
    {
        public MyIndexOutOfException(string message) : base(message)
        {

        }

        public int ErrorCode { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int steInput = 12;

                if (steInput > 10)
                {
                    throw new MyIndexOutOfException("数据超出了范围") { ErrorCode = 1 };
                }

            }

            catch (MyIndexOutOfException ex) when (ex.ErrorCode!=1)

            {
                Console.WriteLine("出现了自定义错误");
            }

            catch (MyIndexOutOfException ex) when (ex.ErrorCode == 1)
            {
                Console.WriteLine(ex.Message);
            }

            catch (Exception ex)
            {

                throw;
            }
        }
    }

 

  上面例子中,自定义了一个异常处理,同时增加 ErrorCode,以此来作为过滤条件,利用关键字 When + 条件来进行过滤。

总结

  本篇文章介绍了异常处理错误的情况及机制,我们不仅可以输出代码好难过的一般错误代码,也可以输出我们自己定义的特殊错误情况。无论编程技术有多好,程序都必须能处理可能出现的任何错误。对不同的错误采取相应的应对措施,才是正确编码的其中一步。

 

      不是井里没有水,而是你挖的不够深。不是成功来得慢,而是你努力的不够多。


 

 

               c# 基础知识详解系列

 

欢迎大家扫描下方二维码,和我一起学习更多的 C# 知识

  

  

原文出处:https://www.cnblogs.com/hulizhong/p/11316352.html

Go中的错误和异常处理最佳实践

Go中的错误和异常处理最佳实践

本文已收录编程学习笔记。涵盖PHP、JavaScript、Linux、Golang、MySQL、Redis和开源工具等等相关内容。

错误

认识错误

在Go中,错误是一种表示程序错误状态。包含了在程序在运行时、编译时的状态信息。一般我们在编写Go代码中,都会碰到如下的处理方式。

file, err := os.Create("test.txt")

fmt.Println(file)

if err != nil {
  fmt.Println(err)
  return
}

我们使用os库创建一个名为test.txt的文件,该方法返回一个文件指针或err的错误信息。

err表示文件创建失败时的错误信息。当存储错误时,我们则对程序做错误处理;不存在错误时,则正常执行其他的逻辑代码。

自定义错误

在Go中是允许我们自定义错误信息的。自定义错误信息需要利用自带的error报中的New()函数。如下示例代码:

package main

import (
    "errors"
    "fmt"
)

func printError() (a int, err error) {
    err = errors.New("打印错误信息")
    a = 1
    return
}

func main() {
    i, err := printError()
    fmt.Println("i value is", i)
    if err != nil {
        fmt.Println(err)
        return
    }
}

具体的打印信息:i value is 1 打印错误信息

实现原理

在使用errors.New()函数时,该包中声明了一个结构体errorString并且实现了error接口体中的方法Error()

// errors包
package errors

func New(text string) error {
    return &errorString{text}
}

type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}
// error接口
type error interface {
    Error() string
}

异常

认识异常

异常是程序在编译时或者运行时发生的异常信息。如果不对异常做处理,可能导致程序终止程序或者抛出异常信息,导致程序无法正常运行。不管是在程序编译或者运行时,都需要对异常进行严格处理。如下代码,程序在编译时就会触发异常,导致无法进行正常编译:

package main

import "fmt"

func main() {
    panic("print panic")
    fmt.Println("end")
}

打印结果

╰─ go run demo6.go 
panic: print panic

goroutine 1 [running]:
main.main()
        /usr/local/var/www/go/golang_code/src/syntax/err/demo6.go:20 +0x39
exit status 2
  1. Go 运行时会触发运行时 panic,伴随着程序的崩溃抛出一个 runtime.Error 接口类型的值。这个错误值有个 RuntimeError() 方法用于区别普通错误。
  2. panic 可以直接从代码初始化:当错误条件(我们所测试的代码)很严苛且不可恢复,程序不能继续运行时,可以使用 panic 函数产生一个中止程序的运行时错误。
  3. panic 接收一个做任意类型的参数,通常是字符串,在程序死亡时被打印出来。Go 运行时负责中止程序并给出调试信息。
  4. 在多层嵌套的函数调用中调用 panic,可以马上中止当前函数的执行。

处理异常

当程序在运行过程中发生异常,会终止程序的正常运行。需要严格处理异常信息。Go中可以使用recover()将程序从panic中获取异常信息,并获取程序的执行权。

  1. 正如名字一样,这个(recover)内建函数被用于从 panic 或 错误场景中恢复:让程序可以从 panicking 重新获得控制权,停止终止过程进而恢复正常执行。
  2. recover只能在defer修饰的函数中使用:用于取得panic调用中传递过来的错误值,如果是正常执行,调用recover会返回 nil,且没有其它效果。
  3. panic 会导致栈被展开直到defer修饰的recover()被调用或者程序中止。
  4. 所有的 defer 语句都会保证执行并把控制权交还给接收到 panic 的函数调用者。这样向上冒泡直到最顶层,并执行(每层的) defer,在栈顶处程序崩溃,并在命令行中用传给 panic 的值报告错误情况:这个终止过程就是 panicking。

异常处理原则

  1. 在包内部,应该从panic中recover:不允许显式的超出包范围的panic()。在包内部,特别是在非导出函数中有很深层次的嵌套调用时,对主调函数来说用 panic 来表示应该被翻译成错误的错误场景是很有用的(并且提高了代码可读性)。
  2. 在包外部,向包的调用者返回错误值(而不是panic)。
  3. Go 库的原则是即使在包的内部使用了 panic,在它的对外接口(API)中也必须用 recover 处理成返回显式的错误。

异常处理实践

下面的示例代码,在被调用函数printPanic()中触发一个panic(),在main()函数中使用defer中接收panic()信息,并对panic()做异常处理。

package main

import "fmt"

func printPanic() {
    panic("panic exception")
}

func main() {
    defer func() {
        err := recover()
        if err != nil {
            fmt.Println("panic is", err)
        }
    }()

    printPanic()

    fmt.Println("end")
}

打印结果

╰─ go run demo5.go
i value is 1
打印错误信息

Java JSP 异常处理:处理错误和异常

Java JSP 异常处理:处理错误和异常

java jsp 异常处理:处理错误和异常

Java JSP 异常处理是在开发过程中必不可少的一部分,能有效处理错误和异常,提高系统的稳定性和可靠性。php小编苹果将为大家详细介绍Java JSP中异常处理的技巧和方法,帮助开发者更好地应对各种意外情况,确保系统正常运行。通过本文的学习,读者将能够掌握Java JSP异常处理的核心概念和实际操作技巧,为项目开发提供有力支持。

JSP 中的异常处理

JSP 提供了三种主要机制来处理异常:

  1. page 指令:该指令指定处理某个页面上所有未处理异常的错误处理页面。
  2. try-catch 块:该块允许开发人员定义特定的处理程序,用于处理特定类型的异常。
  3. JavaBean:异常处理逻辑可以封装在 JavaBean 中,然后在 JSP 页面中使用。

page 指令

立即学习“Java免费学习笔记(深入)”;

page 指令的语法如下:

<%@ page errorPage="error-handler.jsp" %>
登录后复制

errorPage 属性指定在发生任何未处理异常时应加载的错误处理页面。

try-catch 块

try-catch 块允许开发人员定义处理特定异常情况的特定代码块。其语法如下:

<jsp:useBean id="calculator"scope="page" />

<jsp:setProperty name="calculator" property="operand1" value="10" />
<jsp:setProperty name="calculator" property="operand2" value="0" />

<%
try {
int result = calculator.divide();
out.println("Result: " + result);
} catch (ArithmeticException e) {
out.println("Error: Arithmetic exception occurred.");
}
%>
登录后复制

在上面的示例中,try 块包含可能引发异常的代码,而 catch 块定义了处理 ArithmeticException 异常的代码块。

JavaBean

异常处理逻辑还可以封装在 JavaBean 中。JSP 页面可以使用 setProperty 和 getProperty 动作访问 JavaBean 的属性和方法。

例如,以下 JavaBean 定义了一个 handleException() 方法来处理异常:

public class ErrorHandlerBean {

public void handleException(Exception e) {
// PerfORM custom error handling logic here
}
}
登录后复制

然后,可以在 JSP 页面中使用该 Bean:

<jsp:useBean id="errorBean"scope="page" />

<jsp:setProperty name="errorBean" property="exception" value="${exception}" />

<%
errorBean.handleException();
%>
登录后复制

结论

JSP 中的异常处理对于构建健壮且用户友好的应用程序至关重要。通过使用 page 指令、try-catch 块和 JavaBean,开发人员可以优雅地处理错误和异常,确保应用程序在各种情况下都能正常运行。

以上就是Java JSP 异常处理:处理错误和异常的详细内容,更多请关注php中文网其它相关文章!

Koa入门教程[3]-错误和异常处理

Koa入门教程[3]-错误和异常处理

Node.js 中的异常

Node.js 跟 JavaScript一样,同步代码中的异常我们可以通过 try catch 来捕获.

异步回调异常

但异步代码呢? 我们来看一个 http server 启动的代码,这个也是个典型的异步代码。

const http = require(''http'')
try {
    const server = http.createServer(function (req, res) {
        console.log(''来了'')
        throw new Error(''hi'')
        res.end(''helo'')
    })
    server.listen(3002)
}
catch (err) {
    console.log(''出错了'')
}

我们发现异步代码的异常无法直接捕获。这会导致 Node.js 进程退出。最明显的就是 web server 直接挂掉了。

异步代码也有解决办法,我们直接把try catch 写在异步代码的回调里面:

const http = require(''http'')
try {
    const server = http.createServer(function (req, res) {
        try {
            throw new Error(''hi'')
        }
        catch (err) {
            console.log(''出错了'')
        }
        res.end(''helo'')
    })
    server.listen(3002)
}
catch (err) {
    console.log(''出错了'')
}

这样也能catch到错误。

然而业务代码非常复杂,并不是所有的情况我们都能预料到。比如在try...catch之后又出现一个throw Error.

所有没有catch 的Error都会往上冒泡直到变成一个全局的 uncaughtException。 Node.js里对未捕获的异常会检查有没有监听该事件,如果没有就把进程退出:

function _MyFatalException(err){
    if(!process.emit(''uncaughtException'',err)){
        console.error(err.stack);
        process.emit(''exit'',1);
    }
}

因此,防止异步回调异常导致进程退出的办法仿佛就是监听该事件

process.on(''uncaughtException'', function(err) {
    console.log(''出错了,我记录你,并吃掉你'')
})

const http = require(''http'')
try {
    const server = http.createServer(function (req, res) {
        try {
            throw new Error(''hi'')
        }
        catch (err) {
            console.log(''出错了'')
        }
        throw new Error(''有一个error'')
        res.end(''helo'')
    })
    server.listen(3002)
}
catch (err) {
    console.log(''出错了'')
}

这样进程不会退出。但 极其不优雅 。 因为 uncaughtException 中没有了req和res上下文,无法友好响应用户。另外可能造成内存泄漏(具体参考网络其他资料)

因此,uncaughtException 适合用来做Node.js 整个应用最后的兜底。(记录日志or重启服务)

Promise的reject异常

如果使用了promise,且非异步reject了。在 Node.js 中,这个promise reject 行为会在控制台打印,但目前Node版本不会造成进程退出,也不会触发全局 uncaughtException.

promise最有争议的地方就是当一个promise失败但是没有rejection handler处理错误时静默失败。不过浏览器和Node.js都有相应的处理机制,两者大同小异,都是通过事件的方式监听. 有两个全局事件可以用来监听 Promise 异常:
  • unhandledRejection:当promise失败(rejected),但又没有处理时触发,event handler 有2个参数: reason,promise;
  • rejectionHandled: 当promise失败(rejected),被处理时触发,hanler 有1个参数: promise;

到底该如何处理异常

最好的处理方式,就是应该感知到自己业务代码中的异常。这样的话,无论业务开发人员自己处理了还是没处理,都能在应用上层catch到进行日志记录。 更佳的情况是:在感知到错误后,能给浏览器一些默认的提示。

可是业务代码里有同步有异步,如此复杂的代码如何能全部cover住呢?

这个会有一些技巧:比如假设我们的业务代码全部被包裹在自己的一个Promise中,且业务代码的每一个异步函数都可以被我们注入catch回调。在这样完美的情况下,我们就能在最外层捕获内部发生的所有异常了。

Koa 就是这么干的。Koa1 用 co来运行中间件,co就可以把generator运行起来且捕获其中的异步错误。想了解具体原理的,可能要去看更详细的资料了

Koa 中捕获异常和错误的机制

  • 业务自己try catch

这种方式任何JavaScript程序都可以使用,是业务开发人员自己要做的。不多说了

  • 写前置中间件

由于Koa是洋葱模型,因此可以在业务逻辑的前置中间件里捕获后面中间件的错误。这里是基于 yield 异步异常可以被try catch的机制。例如:

app.use(function *(next) {
  try {
    yield next;
  } catch (err) {
    console.log(''哇哈 抓到一个错误'')
    // 友好显示给浏览器
    this.status = err.status || 500;
    this.body = err.message;
    this.app.emit(''error'', err, this);
  }
});

实际上,上述中间件的工作 ctx.onerror 已经做了。 Koa 内核会自动把中间件的错误交给 ctx.onerror 处理,因此这个中间件我感觉没必要写了(除非要自定义这个默认的错误处理逻辑)。

  • 监听app.on(''error'')

如果所有中间件都没有捕获到某个异常,那么co会捕获到。co会调用context对象的onerror, 从而做一些处理(例如返回给浏览器500错误),同时触发 app.onerror

因此,在app.onerror里,你可以做些日志记录或自定义响应

  • uncaughtException

如果 Koa 都没有捕获到异常,那么就由Node来兜底了。不过这个一般不会发生,除非你在app.onerror里还要扔出异常(然而这是个promise异常,也不会触发uncaughtException)。

Koa错误处理最佳实践

  • 抛出异常

在 Koa1 中间件里,你可以使用 this.throw(status, msg) 抛出异常。 Koa的底层其实本质上会使用 http-errors模块包装这个Error, 并直接 throw这个异常。

以下是 this.throw 函数源码:

  // 将你传递的错误码和msg包装为一个 Error对象
  throw: function(){
    throw createError.apply(null, arguments);
  }

其中 createError函数相当于:

var err = new Error(msg);
err.status = status;
throw err; // 包装后再抛出,ctx.onerror才能正确响应错误码给浏览器,否则都是500

因此 中间件 中你调用 this.throw 函数实际上就是真的 throw了一个异常,最终会导致 co 异常。

由于前文讲到的 Koa co 错误捕获机制(co-->catch-->ctx.onerror-->app.onerror),因此,你在任何中间件中throw的异常都可以被app.onerror捕获到。

  • 逃逸的异常

co在运行generator时,如果某个yield右侧又是一个generator,那么co也会递归地去运行它。当然也会捕获这个嵌套的异步异常。但有些情况下嵌套异步会逃出一个异步的错误检测机制。

比如在Promise里做了另外一个异步操作, 在另外的异步操作里抛出了异常。

var fn = function () {
    return new Promise (function (resolve, reject) {
        setTimeout(function(){throw new Error(''inner bad'')})
    })
}

这个异常,Promise就无法catch到。 同样,在generator里如果用了这样的方式,异常也会逃逸导致无法捕获。

问题:逃逸出Koa 的 co异步调用链的代码,会导致co无法catch异常。

不如去看看egg怎么做的吧

关于PHP10 错误和异常处理php异常处理和错误处理的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于.NET---- 错误和异常处理机制、Go中的错误和异常处理最佳实践、Java JSP 异常处理:处理错误和异常、Koa入门教程[3]-错误和异常处理等相关内容,可以在本站寻找。

本文标签: