zoukankan      html  css  js  c++  java
  • yii2 response多次输出问题的查找

    {
        "IsSuccess": 1,
        "ErrMsg": "OK",
        "Data": {
            "IsSuccess": 1,
            "ErrMsg": "OK",
            "Data": {
                "IsSuccess": 1,
                "ErrMsg": "OK",
                "Data": {
                    "IsSuccess": 1,
                    "ErrMsg": "OK",
                    "Data": {
                        "IsSuccess": 1,
                        "ErrMsg": "OK",
                        "Data": {
                            "error_code": 1,
                            "message": "OK",
                            "res_msg": {
                                "error_code": 1,
                                "message": "OK",
                                "res_msg": {
                                    "error_code": 1,
                                    "message": "OK",
                                    "res_msg": {
                                        "error_code": 1,
                                        "message": "OK",
                                        "res_msg": {
                                            "error_code": 1,
                                            "message": "OK",
                                            "res_msg": {
                                                "error_code": 1,
                                                "message": "OK",
                                                "res_msg": {
                                                    "error_code": 1,
                                                    "message": "OK",
                                                    "res_msg": {
                                                        "error_code": 1,
                                                        "message": "OK",
                                                        "res_msg": {
                                                            "error_code": 1,
                                                            "message": "OK",
                                                            "res_msg": {
                                                                "error_code": 1,
                                                                "message": "OK",
                                                                "res_msg": {
                                                                    "error_code": 1,
                                                                    "message": "OK",
                                                                    "res_msg": {
                                                                        "error_code": 1,
                                                                        "message": "OK",
                                                                        "res_msg": {
                                                                            "error_code": 1,
                                                                            "message": "OK",
                                                                            "res_msg": {
                                                                                "error_code": 1,
                                                                                "message": "OK",
                                                                                "res_msg": {
                                                                                    "error_code": 1,
                                                                                    "message": "OK",
                                                                                    "res_msg": {
                                                                                        "error_code": 1,
                                                                                        "message": "OK",
                                                                                        "res_msg": {
                                                                                            "error_code": 1,
                                                                                            "message": "OK",
                                                                                            "res_msg": {
                                                                                                "error_code": 1,
                                                                                                "message": "OK",
                                                                                                "res_msg": {
                                                                                                    "error_code": 1,
                                                                                                    "message": "OK",
                                                                                                    "res_msg": {
                                                                                                        "error_code": 1,
                                                                                                        "message": "OK",
                                                                                                        "res_msg": {
                                                                                                            "error_code": 1,
                                                                                                            "message": "OK",
                                                                                                            "res_msg": {
                                                                                                                "error_code": 1,
                                                                                                                "message": "OK",
                                                                                                                "res_msg": {
                                                                                                                    "error_code": 1,
                                                                                                                    "message": "OK",
                                                                                                                    "res_msg": {
                                                                                                                        "error_code": 1,
                                                                                                                        "message": "OK",
                                                                                                                        "res_msg": {
                                                                                                                            "error_code": 1,
                                                                                                                            "message": "OK",
                                                                                                                            "res_msg": {
                                                                                                                                "error_code": 1,
                                                                                                                                "message": "OK",
                                                                                                                                "res_msg": {
                                                                                                                                    "error_code": 1,
                                                                                                                                    "message": "OK",
                                                                                                                                    "res_msg": {
                                                                                                                                        "error_code": 1,
                                                                                                                                        "message": "OK",
                                                                                                                                        "res_msg": {
                                                                                                                                            "error_code": 1,
                                                                                                                                            "message": "OK",
                                                                                                                                            "res_msg": {
                                                                                                                                                "available": [
                                                                                                                                                    "/api/auth/view",
                                                                                                                                                ],
                                                                                                                                                "assigned": [
                                                                                                                                                    "/*",
                                                                                                                                                    "/admin/*",
                                                                                                                                                    "/admin/api/*"
                                                                                                                                                ]
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                    }
                                                                                                                                }
                                                                                                                            }
                                                                                                                        }
                                                                                                                    }
                                                                                                                }
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    View Code

    以上是现象。

    action:

    public function actionRefresh()
        {
            $model = new Route();
            $model->invalidate();
            return $model->getRoutes();
        }
    

    访问这个action产生的。因为我这个controller继承了同事写的一个基controller,代码如下:

    public function init()
        {
            parent::init();
            //绑定beforeSend事件,更改数据输出格式
            Yii::$app->getResponse()->on(Response::EVENT_BEFORE_SEND, [$this, 'beforeSend']);
        }
    
        /**
         * 更改数据输出格式
         * 默认情况下输出Json数据
         * @param yiiaseEvent $event
         */
        public function beforeSend($event)
        {
            /* @var $response yiiwebResponse */
            $response = $event->sender;
            $msg = $response->statusText;
            $statusCode = $response->statusCode;
            $isSuccess = $response->getIsSuccessful();
    
            if(isset($response->data['code']) && $response->data['code']==0){
                $code = 0;
            }else{
                if($isSuccess){
                    $code = 1;
                }else{
                    $code = 0;
                }
            }
            if ($response->statusCode>=400) {
                //异常处理
                if (true && $exception = Yii::$app->getErrorHandler()->exception) {
                     $data = $response->data;
                    //$data = $this->convertExceptionToArray($exception);
                }
                //Model出错了
                if ($response->statusCode==422) {
                    $messages=[];
                    foreach ($response->data as $v) {
                        $messages[] = $v['message'];
                    }
                    //请求错误时数据为  {"success":false,"data":{"name":"Not Found","message":"页面未找到。","code":0,"status":404}}
                    $data = [
                        'error_code' =>$code,
                        'message'=> implode("  ", $messages),
                        'res_msg'=>$response->data
                    ];
                }
                $response->isSent = true;
              //  $response->statusCode = 200;
            }
            elseif ($response->statusCode>=300) {
              //  $response->statusCode = 200;
                $data = $this->convertExceptionToArray(new ForbiddenHttpException(Yii::t('yii', 'Login Required')));
            }
            else{
                $data = $response->data;
            }
    
            //请求正确时数据
            $response->data = [
                'error_code' =>$code,
                'message' => $msg,
                'res_msg' => empty($data) ? array('message'=>'暂无数据') : $data,
            ];
    
            $response->format = Response::FORMAT_JSON;
         //   Yii::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Origin', '*');
          //  Yii::$app->getResponse()->getHeaders()->set('Access-Control-Allow-Credentials', 'true');
    
        }
    

    在beforeSend中Yii::info($response->statusCode);

    发现该事件Response::EVENT_BEFORE_SEND被多次触发,这就导致了上面那个现象。

    在基础controller中没有检测该事件是否绑定handler,造成了多次多次重复绑定,因为在该次执行中对多个controller进行了实例化。

    init中改为:

    public function init()
        {
            parent::init();
            //绑定beforeSend事件,更改数据输出格式
            if (!Yii::$app->response->hasEventHandlers(Response::EVENT_BEFORE_SEND)) {
                // 避免重复绑定
                Yii::$app->getResponse()->on(Response::EVENT_BEFORE_SEND, [$this, 'beforeSend']);
            }
        }
    

      方法

    不过在加入了该判断后,发现少了一些输出,不过还有六次输出,如下:

    {
        "IsSuccess": 1,
        "ErrMsg": "OK",
        "Data": {
            "IsSuccess": 1,
            "ErrMsg": "OK",
            "Data": {
                "IsSuccess": 1,
                "ErrMsg": "OK",
                "Data": {
                    "IsSuccess": 1,
                    "ErrMsg": "OK",
                    "Data": {
                        "IsSuccess": 1,
                        "ErrMsg": "OK",
                        "Data": {
                            "error_code": 1,
                            "message": "OK",
                            "res_msg": {
                                "available": [
                                    "/api/auth/view",
                                    "/api/auth/create"
                                ],
                                "assigned": [
                                    "/*",
                                    "/admin/*",
                                    "/admin/api/*",
                                ]
                            }
                        }
                    }
                }
            }
        }
    }
    

    突然发现前面输出的是:

    "IsSuccess": 1,
    "ErrMsg": "OK",
    "Data":{}

    而这是我在另外一个基controller中绑定的事件发挥的结果格式,如下:

    public function init() {
            parent::init();
            Event::on(
                Response::className(),
                Response::EVENT_BEFORE_SEND,
                [$this, 'formatDataBeforeSend']
            );
        }
    

    很奇怪,他为啥跟这个混在一起了?

    对了,这是因为出现这种情况是在获取系统所有route的方法getAppRoutes中,而其中有对所有controller进行实例化的动作。症结就在这里了。 

    将init方法改造为:

    public function init() {
            parent::init();
            if (!Event::hasHandlers(Response::className(), Response::EVENT_BEFORE_SEND)) {
                Event::on(
                    Response::className(),
                    Response::EVENT_BEFORE_SEND,
                    [$this, 'formatDataBeforeSend']
                );
            }
        }
    

    不过在这样处理后,还有问题,如下:

    {
        "IsSuccess": 1,
        "ErrMsg": "OK",
        "Data": {
            "error_code": 1,
            "message": "OK",
            "res_msg": {
                "available": [
                    "/api/auth/view",
                    "/api/auth/create",
                    "/api/auth/update",
                ],
                "assigned": [
                    "/*",
                    "/admin/*"
                ]
            }
        }
    }
    

    还有问题,不过这个问题的原因就在于这里因为对那个作为路由controller的中绑定事件的触发,加上正常的触发,导致了这个问题。

    这个问题除了前面加上判断之外,还得处理一下,如下:

    public function init() {
            parent::init();
            if (
                !Event::hasHandlers(Response::className(), Response::EVENT_BEFORE_SEND)
                && !Yii::$app->response->hasEventHandlers(Response::EVENT_BEFORE_SEND)
            ) {
                Event::on(
                    Response::className(),
                    Response::EVENT_BEFORE_SEND,
                    [$this, 'formatDataBeforeSend']
                );
            }
        }
    

    因为涉及到两种返回格式,且在一次访问中,多次触发controller实例化,这种情况一般是不常见的。所以出现这种现象是特定情况。问题已找到。

  • 相关阅读:
    最大流——poj3308 (模板)
    混合边的欧拉路径——poj1637 最大流
    JBPM FAQ
    spring 读取资源文件方法
    JBPM使用assignHandler进行用户分派思路
    直接修改jpbm xml流程定义字段的方法
    转 java 读取文件的字符集
    JAVA实现AD验证
    找到一篇jbpm session closed解决办法的文章
    dwr 读取cookie
  • 原文地址:https://www.cnblogs.com/jiangtian/p/10991576.html
Copyright © 2011-2022 走看看