diff --git a/install.php b/install.php
index 06b05ee6..362cee78 100644
--- a/install.php
+++ b/install.php
@@ -205,8 +205,8 @@ function install_get_default_routers(): array
         'comment_page'       =>
             [
                 'url'    => '[permalink:string]/comment-page-[commentPage:digital]',
-                'widget' => '\Widget\Archive',
-                'action' => 'render',
+                'widget' => '\Widget\CommentPage',
+                'action' => 'action',
             ],
         'feed'               =>
             [
diff --git a/var/Typecho/Router.php b/var/Typecho/Router.php
index 35a013da..8b4d8f6d 100644
--- a/var/Typecho/Router.php
+++ b/var/Typecho/Router.php
@@ -15,7 +15,6 @@ class Router
     /**
      * 当前路由名称
      *
-     * @access public
      * @var string
      */
     public static $current;
@@ -23,24 +22,34 @@ class Router
     /**
      * 已经解析完毕的路由表配置
      *
-     * @access private
-     * @var mixed
+     * @var array
      */
     private static $routingTable = [];
 
     /**
-     * 解析路径
+     * 是否已经匹配过,防止递归匹配
      *
-     * @access public
+     * @var bool
+     */
+    private static $matched = false;
+
+    /**
+     * 解析路径
      *
      * @param string|null $pathInfo 全路径
      * @param mixed $parameter 输入参数
-     *
+     * @param bool $once 是否只匹配一次
      * @return false|Widget
      * @throws \Exception
      */
-    public static function match(?string $pathInfo, $parameter = null)
+    public static function match(?string $pathInfo, $parameter = null, bool $once = true)
     {
+        if ($once && self::$matched) {
+            throw new RouterException("Path '{$pathInfo}' not found", 404);
+        }
+
+        self::$matched = true;
+
         foreach (self::$routingTable as $key => $route) {
             if (preg_match($route['regx'], $pathInfo, $matches)) {
                 self::$current = $key;
@@ -122,7 +131,6 @@ class Router
      * @param string $name 路由配置表名称
      * @param array|null $value 路由填充值
      * @param string|null $prefix 最终合成路径的前缀
-     *
      * @return string
      */
     public static function url(string $name, ?array $value = null, ?string $prefix = null): string
@@ -141,10 +149,7 @@ class Router
     /**
      * 设置路由器默认配置
      *
-     * @access public
-     *
      * @param mixed $routes 配置信息
-     *
      * @return void
      */
     public static function setRoutes($routes)
@@ -162,9 +167,6 @@ class Router
      * 获取路由信息
      *
      * @param string $routeName 路由名称
-     *
-     * @static
-     * @access public
      * @return mixed
      */
     public static function get(string $routeName)
diff --git a/var/Widget/Archive.php b/var/Widget/Archive.php
index b454ff27..9a93caad 100644
--- a/var/Widget/Archive.php
+++ b/var/Widget/Archive.php
@@ -187,7 +187,8 @@ class Archive extends Contents
             'pageSize'       => $this->options->pageSize,
             'type'           => null,
             'checkPermalink' => true,
-            'preview'        => false
+            'preview'        => false,
+            'commentPage'    => 0
         ]);
 
         /** 用于判断是路由调用还是外部调用 */
@@ -512,7 +513,6 @@ class Archive extends Contents
             'page'               => 'singleHandle',
             'post'               => 'singleHandle',
             'attachment'         => 'singleHandle',
-            'comment_page'       => 'singleHandle',
             'category'           => 'categoryHandle',
             'category_page'      => 'categoryHandle',
             'tag'                => 'tagHandle',
@@ -794,7 +794,7 @@ class Archive extends Contents
             'parentId'      => $this->hidden ? 0 : $this->cid,
             'parentContent' => $this->row,
             'respondId'     => $this->respondId,
-            'commentPage'   => $this->request->filter('int')->commentPage,
+            'commentPage'   => $this->parameter->commentPage,
             'allowComment'  => $this->allow('comment')
         ];
 
@@ -1358,41 +1358,6 @@ class Archive extends Contents
         return $commentUrl;
     }
 
-    /**
-     * 导入对象
-     *
-     * @param Archive $widget 需要导入的对象
-     */
-    private function import(Archive $widget)
-    {
-        $currentProperties = get_object_vars($this);
-
-        foreach ($currentProperties as $name => $value) {
-            if (false !== strpos('|request|response|parameter|feed|feedType|currentFeedUrl|', '|' . $name . '|')) {
-                continue;
-            }
-
-            if (isset($widget->{$name})) {
-                $this->{$name} = $widget->{$name};
-            } else {
-                $method = ucfirst($name);
-                $setMethod = 'set' . $method;
-                $getMethod = 'get' . $method;
-
-                if (
-                    method_exists($this, $setMethod)
-                    && method_exists($widget, $getMethod)
-                ) {
-                    $value = $widget->{$getMethod}();
-
-                    if ($value !== null) {
-                        $this->{$setMethod}($widget->{$getMethod}());
-                    }
-                }
-            }
-        }
-    }
-
     /**
      * 检查链接是否正确
      *
@@ -1404,7 +1369,7 @@ class Archive extends Contents
             $type = $this->parameter->type;
 
             if (
-                in_array($type, ['index', 'comment_page', 404])
+                in_array($type, ['index', 404])
                 || $this->makeSinglePageAsFrontPage    // 自定义首页不处理
                 || !$this->parameter->checkPermalink
             ) { // 强制关闭
@@ -1500,17 +1465,6 @@ class Archive extends Contents
      */
     private function singleHandle(Query $select, bool &$hasPushed)
     {
-        if ('comment_page' == $this->parameter->type) {
-            $params = [];
-            $matched = Router::match($this->request->permalink);
-
-            if ($matched && $matched instanceof Archive && $matched->is('single')) {
-                $this->import($matched);
-                $hasPushed = true;
-                return;
-            }
-        }
-
         /** 将这两个设置提前是为了保证在调用query的plugin时可以在插件中使用is判断初步归档类型 */
         /** 如果需要更细判断,则可以使用singleHandle来实现 */
         $this->archiveSingle = true;
diff --git a/var/Widget/CommentPage.php b/var/Widget/CommentPage.php
new file mode 100644
index 00000000..be6bd1b2
--- /dev/null
+++ b/var/Widget/CommentPage.php
@@ -0,0 +1,50 @@
+<?php
+
+namespace Widget;
+
+use Exception;
+use Typecho\Router;
+use Typecho\Widget\Exception as WidgetException;
+
+/**
+ * Comment Page Widget
+ */
+class CommentPage extends Base implements ActionInterface
+{
+    /**
+     * Perform comment page action
+     *
+     * @throws Exception
+     */
+    public function action()
+    {
+        $page = abs($this->request->filter('int')->get('commentPage'));
+
+        $archive = Router::match($this->request->permalink, [
+            'checkPermalink'    =>  false,
+            'commentPage'       =>  $page
+        ]);
+
+        if (!($archive instanceof Archive) || !$archive->is('single')) {
+            throw new WidgetException(_t('请求的地址不存在'), 404);
+        }
+
+        $currentCommentUrl = Router::url('comment_page', [
+            'permalink'     =>  $archive->pathinfo,
+            'commentPage'   =>  $page
+        ], $this->options->index);
+
+        $this->checkPermalink($currentCommentUrl);
+        $archive->render();
+    }
+
+    /**
+     * @param string $commentUrl
+     */
+    private function checkPermalink(string $commentUrl)
+    {
+        if ($commentUrl != $this->request->getRequestUrl()) {
+            $this->response->redirect($commentUrl, true);
+        }
+    }
+}
diff --git a/var/Widget/XmlRpc.php b/var/Widget/XmlRpc.php
index 3bd06b18..b1153fd0 100644
--- a/var/Widget/XmlRpc.php
+++ b/var/Widget/XmlRpc.php
@@ -181,7 +181,7 @@ class XmlRpc extends Contents implements ActionInterface, Hook
             'link'                   => $page->permalink,
             'permaLink'              => $page->permalink,
             'categories'             => $page->categories,
-            'excerpt'                => $page->description,
+            'excerpt'                => $page->plainExcerpt,
             'text_more'              => $more,
             'mt_allow_comments'      => intval($page->allowComment),
             'mt_allow_pings'         => intval($page->allowPing),
@@ -287,7 +287,7 @@ class XmlRpc extends Contents implements ActionInterface, Hook
                 'link'                   => $pages->permalink,
                 'permaLink'              => $pages->permalink,
                 'categories'             => $pages->categories,
-                'excerpt'                => $pages->description,
+                'excerpt'                => $pages->plainExcerpt,
                 'text_more'              => $more,
                 'mt_allow_comments'      => intval($pages->allowComment),
                 'mt_allow_pings'         => intval($pages->allowPing),
@@ -1256,7 +1256,7 @@ class XmlRpc extends Contents implements ActionInterface, Hook
             'link'                   => $post->permalink,
             'permaLink'              => $post->permalink,
             'categories'             => $categories,
-            'mt_excerpt'             => $post->description,
+            'mt_excerpt'             => $post->plainExcerpt,
             'mt_text_more'           => $more,
             'mt_allow_comments'      => intval($post->allowComment),
             'mt_allow_pings'         => intval($post->allowPing),
@@ -1306,7 +1306,7 @@ class XmlRpc extends Contents implements ActionInterface, Hook
                 'link'                   => $posts->permalink,
                 'permaLink'              => $posts->permalink,
                 'categories'             => $categories,
-                'mt_excerpt'             => $posts->description,
+                'mt_excerpt'             => $posts->plainExcerpt,
                 'mt_text_more'           => $more,
                 'wp_more_text'           => $more,
                 'mt_allow_comments'      => intval($posts->allowComment),