8.异常处理--Exceptions

REST framework自定义异常处理

REST framework本身在APIView提供了异常处理,但是仅针对drf内部现有的接口开发相关的异常进行格式处理,但是开发中我们还会使用到各种的数据或者进行各种网络请求,这些都有可能导致出现异常,这些异常在drf中是没有进行处理的,所以就会冒泡给django框架了,django框架会进行组织错误信息,作为html页面返回给客户端,所在在前后端分离项目中,可能js无法理解或者无法接收到这种数据,甚至导致js出现错误的情况。因此为了避免出现这种情况,我们可以自定义一个属于自己的异常处理函数,对于drf无法处理的异常,我们自己编写异常处理的代码逻辑。

针对于现有的drf的异常处理进行额外添加属于开发者自己的逻辑代码,一般我们编写的异常处理函数,会写一个公共的目录下或者主应用目录下。这里主应用下直接创建一个excepitions.py,代码:

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
# 针对mysql、mongoDB、redis、第三方数据接口
def custom_exception_handler(exc, context):
    """
    自定义异常函数
    exc: 异常实例对象,发生异常时实例化出来的
    context: 字典,异常发生时python解释器收集的执行上下文信息。
             所谓的执行上下文就是python解释器在执行代码时保存在内存中的变量、函数、类、对象、模块等一系列的信息组成的环境信息。
    """
    response = exception_handler(exc, context)

    if response is None:
        """当前异常,drf无法处理"""
        if isinstance(exc, ZeroDivisionError):
            response = Response({"detail":"数学老师还有30秒达到战场,0不能作为除数!"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    return response

在配置文件中声明自定义的异常处理,settings,代码:

REST_FRAMEWORK = {
    # 异常配置
    'EXCEPTION_HANDLER': 'drfdemo.exceptions.custom_exception_handler'
}

如果未声明自定义异常的话,drf会采用默认的方式,使用自己封装的异常处理函数,rest_frame/settings.py

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}

例如:

补充上处理关于数据库的异常,这里使用其他异常来举例:

主应用.exceptions,代码:

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
from django.db import DatabaseError
# 针对mysql、mongoDB、redis、第三方数据接口
def custom_exception_handler(exc, context):
    """
    自定义异常函数
    exc: 异常实例对象,发生异常时实例化出来的
    context: 字典,异常发生时python解释器收集的执行上下文信息。
             所谓的执行上下文就是python解释器在执行代码时保存在内存中的变量、函数、类、对象、模块等一系列的信息组成的环境信息。
    """
    response = exception_handler(exc, context)
    print(f"context={context}")
    if response is None:
        """当前异常,drf无法处理"""
        view = context["view"] # 获取异常发生时的视图类
        request = context["request"] # 获取异常发生时的客户端请求对象
        if isinstance(exc, ZeroDivisionError):
            response = Response({"detail":"数学老师还有30秒达到战场,0不能作为除数!"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        if isinstance(exc, TypeError):
            print('[%s]: %s' % (view, exc))
            response = Response({'detail': '服务器内部错误'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return response

视图中,故意报错:

from rest_framework.pagination import LimitOffsetPagination, PageNumberPagination

class Hom5PageNumberPagination(PageNumberPagination):
    page_size = 10                  # 默认分页的每一页数据量
    max_page_size = 20              # 设置允许客户端通过地址栏参数调整的最大单页数据量
    page_query_param = "pn"         # 地址栏上代表页码的变量名,默认是 page
    page_size_query_param = "size"  # 地址栏上代表单页数据量的变量名,默认是page_size

class Hom5APIView(ModelViewSet):
    queryset = Student.objects  # 这句话在没有进行分页时不会报错,调用了分页则会报错,所以会进入异常处理!
    # queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    # 局部分页
    # pagination_class = None  # 关闭分页功能
    # 局部分页往往采用自定义分页类,进行分页数据量的配置
    pagination_class = Hom5PageNumberPagination

    def list(self, request, *args, **kwargs):
        # 获取django的配置项
        from django.conf import settings

        # 获取rest_framework的配置项
        # from rest_framework.settings import api_settings
        # print(api_settings.DEFAULT_PAGINATION_CLASS)
        return super().list(request, *args, **kwargs)

REST framework定义的异常

  • APIException 所有异常的父类
  • ParseError 解析错误
  • AuthenticationFailed 认证失败
  • NotAuthenticated 尚未认证
  • PermissionDenied 权限拒绝
  • NotFound 404 未找到
  • MethodNotAllowed 请求方式不支持
  • NotAcceptable 要获取的数据格式不支持
  • Throttled 超过限流次数
  • ValidationError 校验失败
<think>好的,用户提供的日志显示在Android应用中出现了一个未解决的异常,具体是Sm2EncryptException。首先,我需要分析日志错误,找出可能的原因。错误信息是“Unresolvedexception class when findingcatch block”,这通常意味着在尝试捕获某个异常时,该异常的类没有被正确加载或找不到。可能的原因包括类名拼写错误、依赖缺失,或者ProGuard混淆导致类名被更改。接下来,用户可能需要知道如何解决这个问题。首先,检查代码中捕获Sm2EncryptException的地方,确认包路径是否正确,类是否存在。然后查看项目的依赖配置,确保包含该异常的库已正确添加。如果是混淆问题,需要在ProGuard规则中保留该异常类。然后,我需要给出具体的解决步骤,比如检查代码中的catch块,确认异常类的导入,检查build.gradle文件中的依赖,以及配置ProGuard规则。此外,可能还需要建议用户清理并重新构建项目,确保所有依赖项正确加载。 最后,根据这个问题,提出相关的后续问题,帮助用户深入理解可能的原因和解决方案,比如异常处理机制、ProGuard配置、依赖管理以及日志分析技巧等。</think>错误日志表明在尝试处理`Sm2EncryptException`异常时,系统找不到这个异常类的定义。以下是详细分析和解决方案: **原因分析:** 1. **类未正确导入**:可能忘记添加包含该异常类的库依赖 2. **ProGuard混淆问题**:如果启用了代码混淆,可能异常类被混淆后找不到 3. **类路径错误**:异常类的包路径与catch语句中引用的路径不一致 4. **动态类加载失败**:类加载器无法找到该异常类定义 **解决方案:** 1. **检查依赖配置**(build.gradle): ```groovy dependencies { // 确保包含SM2加密库,示例(具体请查看对应库文档): implementation 'org.bouncycastle:bcprov-jdk15on:1.70' implementation 'com.example:sm2-encryption:1.2.0' // 假设的示例库 } ``` 2. **检查异常捕获代码**: ```java try { // 加密操作代码... } catch (Sm2EncryptException e) { // 确认这里的异常类完全限定名正确 e.printStackTrace(); // 需要确认正确的包路径,例如: // catch (com.ctrm.yjhk.exceptions.Sm2EncryptException e) } ``` 3. **ProGuard配置**(proguard-rules.pro): ```proguard # 保留异常类不被混淆 -keep class com.ctrm.yjhk.exceptions.Sm2EncryptException { *; } ``` 4. **类存在性检查**: ```bash # 在APK中检查类是否存在(使用Android Studio的APK Analyzer) # 或者通过命令行: unzip -l your_app.apk | grep Sm2EncryptException ``` **完整异常处理示例:** ```java import com.ctrm.yjhk.exceptions.Sm2EncryptException; // 确认导入路径正确 public class EncryptionHandler { public void performEncryption() { try { // SM2加密操作 SM2Utils.encrypt(...); } catch (Sm2EncryptException e) { Log.e("Encryption", "SM2加密失败", e); // 处理异常逻辑 } catch (Exception e) { Log.e("Encryption", "未知错误", e); } } } ``` **验证步骤:** 1. 执行`./gradlew clean build`清理重建 2. 检查APK中的classes.dex是否包含该异常类 3. 在设备上运行时通过ADB监控日志: ```bash adb logcat -s AndroidRuntime ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值