Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в 21 локации

От 104 рублей в месяц

Безлимитный трафик. Защита от ДДоС.

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Книги: [Классика] [Базы данных] [Internet/WWW] [Сети] [Программирование] [UNIX] [Windows] [Безопасность] [Графика] [Software Engineering] [ERP-системы] [Hardware]

     

Программирование на ColdFusion. Для профессионалов

Брукс-Билсон Р.

Издано: Издательский дом "Питер"
ISBN: 5-94723-005-4
Твердый переплет, 928 стр.

Начало
Cодержание
Отрывок
[Заказать книгу в магазине "Мистраль"]

Отрывок

Глава 9

Ошибки и обработка исключений

Механизм структурной обработки исключений позволяет корректно обнаруживать и обрабатывать аварийные ситуации, возникающие при выполнении приложений ColdFusion. К таким ситуациям может относиться все что угодно, от тайм-аута страницы или отсутствия необходимого файла до ошибки базы данных или проблем, возникающих при обработке внешнего объекта. Используя приемы, описанные в этой главе, вы сможете реализовать в своих приложениях ColdFusion чрезвычайно надежные средства обработки исключений.

Обработка исключений и ошибок производится в приложениях ColdFusion на нескольких разных уровнях. На простейшем уровне в шаблон включаются теги CFTRY и CFCATCH, предназначенные для обнаружения и перехвата исключений в момент их возникновения. Тег CFTHROW позволяет определять, инициировать и перехватывать собственные типы исключений.

Конечно, перехват всех исключений в момент возникновения — занятие весьма утомительное, поэтому в ColdFusion предусмотрены средства перехвата исключений на более высоком уровне. Например, тег CFERROR позволяет назначить общий обработчик для определенной ошибки. Тег CFERROR обычно используется в шаблоне Application.cfm, а обработка ошибок организуется в контексте Web Application Framework. Этот механизм «повсеместного» перехвата ошибок в приложении весьма удобен, а его возможности достаточно широки.

Кроме того, в ColdFusion 4.5 администратор сайта может настроить обработку ошибок на уровне сервера в Администраторе ColdFusion. Все три способа обработки ошибок и исключений будут рассмотрены в этой главе.

Базовая обработка исключений

Механизм обработки исключений позволяет обнаруживать и перехватывать исключения в момент их возникновения. Благодаря этому приложение может должным образом отреагировать на возникшую проблему (по сравнению с простым инициированием ошибки или вызовом отдельного шаблона, предназначенного для обработки ошибок). После обработки исключения приложение обычно может продолжать выполнение в обычном режиме.

Базовая обработка ошибок в ColdFusion основана на использовании тегов CFTRY и CFCATCH. Заключая в эти теги потенциально небезопасные фрагменты приложения, можно выявить проблемы и разрешить их в местах наиболее вероятного возникновения. Базовый синтаксис конструкции CFTRY/CFCATCH выглядит так:

<CFTRY>
Фрагмент, в котором могут возникнуть исключения

<CFCATCH TYPE="тип_исключения">
Фрагмент, выполняемый при перехвате исключения
</CFCATCH>

<CFCATCH TYPE="тип_исключения">
...
</CFCATCH>

</CFTRY>

Конструкция CFTRY/CFCATCH устроена весьма просто. Сначала фрагмент кода, в котором обрабатываются исключения, заключается в теги CFTRY. Сразу же за этим фрагментом следует один или несколько блоков CFCATCH, предназначенных для перехвата исключений разных типов. Таким образом, фрагмент защищается от возникновения сразу нескольких исключений. Блоки CFCATCH могут содержать любой код HTML и CFM, в том числе и ссылки на переменные CFCATCH (см. далее). Блоки CFCATCH могут содержать вложенные конструкции CFTRY/CFCATCH.

Рассмотрим конкретный пример. Допустим, что приложение при помощи тега CFHTTP считывает данные из текстового файла, который регулярно создается и сохраняется на сервере. Существует вероятность того, что приложение попытается обратиться к текстовому файлу во время обновления, что приведет к ошибке. Для предотвращения ошибки тег CFHTTP заключается в теги CFTRY/CFCATCH, что позволяет предотвращать любые исключительные ситуации, возникающие при обращении к текстовому файлу. В листинге 9.1 приведен простейший вариант обработки исключения — вывод сообщения о том, что файл обновляется, и предложения повторить попытку через несколько минут.

Листинг 9.1. Блок CFTRY/CFCATCH, выполняющий обработку любых исключений, возникших при вызове тега CFHTTP

<!--- Попытаться получить информацию из файла биржевых котировок
при помощи тега CFHTTP. --->
<CFTRY>

<CFHTTP URL="http://www.example.com/myfile.txt" METHOD="GET"
COLUMNS="Ticker, Time, Price" DELIMITER=","
RESOLVEURL="false" THROWONERROR="yes">

<!--- Перехватить любые исключения и сообщить пользователю о том,
что файл находится в процессе обновления. --->
<CFCATCH TYPE="Any">
<CENTER>
<H2>Stock quotes are currently being updated. Please check back again in a few
minutes...</H2>
</CENTER>
</CFCATCH>

</CFTRY>

При вызове тега CFCATCH передается единственный атрибут TYPE, определяющий тип исключения. Ниже приведен список допустимых значений атрибута TYPE.

  • Any (используется по умолчанию). Перехват любых исключений. При наличии нескольких блоков CFCATCH в блоке CFTRY тип Any указывается в последнем блоке CFCATCH.
  • Application. Перехват исключений уровня приложения, определяемых с типом Application в теге CFTHROW. Эта разновидность исключений подробно рассматривается в следующем разделе.
  • Нестандартный_тип. Перехват исключений, инициируемых программистом в теге CFTHROW.
  • Database. Перехват исключений, возникших при взаимодействии с источниками данных.
  • Expression. Перехват исключений, возникающих при обработке выражений.
  • Lock. Перехват исключений, связанных с тегом CFLOCK (тайм-ауты и т. д.)
  • MissingInclude. Перехват исключений, возникающих из-за отсутствия включаемого шаблона. Исключения, относящиеся к этой категории, инициируются тегами CFINCLUDE, CFMODULE и CFERROR.
  • Object. Перехват исключений, связанных с внешними объектами (в частности, объектами COM/DCOM, CORBA и Java).
  • Security. Перехват исключений, возникающих при неудачной аутентификации.
  • Template. Перехват общих ошибок приложений, возникающих в шаблонах ColdFusion.

    Кроме исключений, соответствующих значениям атрибута TYPE, в ColdFusion поддерживаются и другие типы структурных исключений, возникающие в крайне специфических условиях, например, при тайм-ауте обращений к страницам или в результате вызова некоторых тегов ColdFusion. Эти типы исключений перечислены в описании тега CFTRY, находящегося в приложении А.

    Как упоминалось ранее, блок CFCATCH может содержать ссылки на переменные CFCATCH. Эти переменные автоматически генерируются при перехвате исключения блоком CFCATCH и хранятся в структуре CFCATCH. Переменные CFCATCH доступны только в блоке CFCATCH и используются при выполнении разных операций — принятия решений, влияющих на обработку, записи данных в журнал, а также для вывода специализированных сообщений об ошибках или информации для пользователей. Кроме того, в блоках CATCH может использоваться любой допустимый код HTML, CFML и JavaScript. Переменные, перечисленные ниже, доступны для всех типов исключений.

  • CFCATCH.Type. Тип исключения.
  • CFCATCH.Message. Сообщение об ошибке, сгенерированное исключением (наличие не гарантировано).
  • CFCATCH.Detail. Подробное сообщение об ошибке, сгенерированное интерпретатором CFML.
  • CFCATCH.TagContext. Массив структур с именем и позицией каждого тега в стеке тегов и уточненными полными именами файлов, содержащих теги. Каждая структура массива TagContext содержит следующие поля:
  • ID. Имя тега в стеке;
  • TEMPLATE. Уточненное имя шаблона, содержащего тег;
  • LINE. Номер строки, в которой находится тег;
  • COLUMN. Номер столбца, в котором начинается тег.

    Для присвоения значений переменной CFCATCH.TagContext в разделе Debugging Администратора ColdFusion должен быть установлен флажок CFML Stack Trace. Если флажок не установлен, с помощью переменной CFCATCH.TagContext возвращается массив нулевой длины.

    Кроме перечисленных переменных, существуют и другие, доступные только для конкретных видов исключений. Они перечислены в описании тега CFTRY в приложении А.

    В следующих примерах продемонстрирована методика перехвата различных типов исключений и другие возможности их обработки. В листинге 9.2 исключение возникает при попытке использования в выражении неопределенной переменной (y). Поскольку в перехватчике указан универсальный тип исключения (атрибут TYPE="Any"), в данном примере тег CFCATCH является примером общего обработчика исключений.

    Листинг 9.2. Перехват исключений с использованием тегов CFTRY/CFCATCH

    <CFTRY>
    <CFSET x=y+1>

    <CFCATCH TYPE="Any">
    <H2>An unknown exception has occurred! Diagnostic information is shown
    below:</H2>

    <BR>
    <H3>CFCATCH Exception Information</H3>

    <TABLE BORDER="0">
    <TR BGCOLOR="#0000FF">
    <TH><FONT COLOR="#FFFFFF">Variable</FONT></TH>
    <TH><FONT COLOR="#FFFFFF">Value</FONT></TH>
    </TR>
    <CFOUTPUT>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.Type</TD><TD>#CFCATCH.Type#</TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.Message</TD><TD>#CFCATCH.Message#</TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.Detail</TD><TD>#CFCATCH.Detail#</TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.TagContext</TD>
    <TD>
    <TABLE BORDER="0">
    <TR>
    <TH COLSPAN="3">Tag Stack</TH>
    </TR>
    <TR BGCOLOR="##0000FF">
    <TH><FONT COLOR="##FFFFFF">Tag</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Position</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Template</FONT></TH>
    </TR>
    <CFLOOP index="element" from="1" TO="#ArrayLen(CFCATCH.TagContext)#">
    <CFSET TheStack = #CFCATCH.TagContext[element]#>
    <TR BGCOLOR="##D3D3D3">
    <TD>#TheStack["ID"]#</TD>
    <TD>(#TheStack["Line"]#:#TheStack["Column"]#)</TD>
    <TD>#TheStack["Template"]#</TD>
    </TR>
    </CFLOOP>
    </TABLE>
    </TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.ErrNumber </TD><TD>#CFCATCH.ErrNumber #</TD>
    </TR>
    </CFOUTPUT>
    </TABLE>

    </CFCATCH>
    </CFTRY>

    Блок CFCATCH перехватывает все возникающие исключения (TYPE="Any"). На практике тегу CFCATCH, перехватывающему все исключения, обычно предшествуют теги CFCATCH для конкретных типов исключений. Иначе говоря, в конструкциях с несколькими тегами CFCATCH тег для перехвата «всех остальных» исключений (если он присутствует) находится на последнем месте. В этом примере он использован только в демонстрационных целях.

    При выполнении этого шаблона вступает в действие блок CFCATCH, в котором тег CFMAIL автоматически создает сообщение электронной почты и отправляет его администратору сайта, оповещая его о возникшей ошибке. В сообщение включается имя отсутствующего шаблона. Несмотря на генерируемое исключение, благодаря конструкции CFTRY/CFCATCH шаблон может продолжать выполнение.

    Как упоминалось ранее, один блок CFTRY может содержать несколько тегов CFCATCH. Такая ситуация продемонстрирована в листинге 9.4, где для одного фрагмента кода определяются обработчики двух различных типов исключений.

    Листинг 9.4. Перехват нескольких типов исключений в конструкциях CFTRY/CFCATCH <CFTRY>

    <!--- По умолчанию переменной LogFileStatus присваивается признак
    успешной записи в журнал. --->
    <CFPARAM NAME="LogFileStatus" DEFAULT="Log entry successful.">

    <H2>Attempting to write a log file entry...</H2>

    <!--- Заблокировать вызов CFFILE, чтобы в любой момент времени
    выполнялась только одна попытка записи.
    Если вы захотите намеренно сгенерировать исключение, перехватываемое
    вторым тегом CFCATCH, отредактируйте атрибут FILE тега CFFILE
    и укажите в нем каталог, не существующий на вашем сервере. --->
    <CFLOCK TIMEOUT="30" THROWONTIMEOUT="Yes" TYPE="EXCLUSIVE">

    <!--- Записать данные в журнал. --->
    <CFFILE ACTION="Append" FILE="c:\temp\logfile.txt"
    OUTPUT="This is a test entry" ADDNEWLINE="Yes">
    </CFLOCK>

    <!--- Перехватывать исключения блокировки. --->
    <CFCATCH TYPE="Lock">
    <CFSET LogFileStatus = "There was a problem obtaining a file lock. Log
    entry <B>NOT</B> written.">
    </CFCATCH>

    <!-- Перехватывать исключения всех остальных типов. --->
    <CFCATCH TYPE="Any">
    <CFSET LogFileStatus = "An unknown exception occurred. Log entry <B>NOT</B>
    written.">
    </CFCATCH>
    </CFTRY>

    <P>
    <CFOUTPUT>
    Processing Complete: #LogFileStatus#
    </CFOUTPUT>

    В этом шаблоне тег CFFILE пытается создать в журнале новую запись. Он находится внутри тега CFFILE, поэтому файл журнала в любой момент времени доступен только для одного процесса. Отсутствие тега CFLOCK приведет к ошибкам доступа к файлу или к искажению содержимого журнала. Тег CFFILE также находится внутри конструкции CFTRY с двумя тегами CFCATCH. Первый тег CFCATCH перехватывает исключения тега CFLOCK, внутри которого находится тег CFFILE. Для этого в теге CFCATCH указывается атрибут TYPE="Lock". Все исключения, относящиеся к блокировке (например, тайм-аут), будут обрабатываться с помощью этого тега. При возникновении исключения переменной LogFileStatus назначается сообщение о неудачной попытке блокировки файла.

    Второй тег CFCATCH используется для страховки и обеспечивает перехват всех непредвиденных исключений, для чего атрибуту TYPE второго тега присваивается значение Any. При генерировании любого исключения, не перехваченного первым тегом CFCATCH, переменной LogFileStatus назначается сообщение о неизвестном исключении. После конструкции CFTRY/CFCATCH в браузере выводится итоговое значение LogFileStatus.

    Обработка нестандартных прерываний

    В предшествующем разделе были рассмотрены основные принципы перехвата стандартных исключений, возникающих в приложениях ColdFusion, с помощью тегов CFTRY/CFCATCH. Хотя стандартные исключения позволяют справиться с любой аварийной ситуацией, они не обеспечивают универсальное решение на все случаи жизни. К счастью, в ColdFusion программист может определять собственные, нестандартные исключения, которые перехватываются той же конструкцией CFTRY/CFCATCH.

    Как упоминалось в предыдущем разделе, в атрибуте TYPE тега CFCATCH может передаваться нестандартный тип исключения. Нестандартные типы исключений определяются при помощи тега CFTHROW. Этот тег инициирует нестандартное исключение, перехватываемое тегом CFCATCH, атрибут которого, TYPE, содержит Application, Any или нестандартный тип, указанный в теге CFTHROW. Иначе говоря, если в приложении возникла аварийная ситуация и требуется сгенерировать нестандартное исключение, воспользуйтесь тегом CFTHROW. Общий синтаксис тега CFTHROW:

    <CFTHROW TYPE="тип_нестандартного_исключения"
    MESSAGE="сообщение_об_ошибке"
    DETAIL="подробное_описание"
    ERRORCODE="код_ошибки"
    EXTENDEDINFO="расширенная_информация">

    При вызове тега CFTHROW могут определяться необязательные атрибуты:

  • TYPE — название типа исключения. Исключению можно присвоить специальное имя или воспользоваться стандартным типом Application;
  • MESSAGE — сообщение с описанием события, приведшего к возникновению исключения;
  • DETAIL — дополнительная информация об исключении;
  • ERRORCODE — числовой код ошибки, используемый в программе;
  • EXTENDEDINFO — дополнительная информация об ошибке.

    Разумеется, если некоторый фрагмент кода CFML инициирует нестандартное исключение тегом CFTHROW, в шаблон нужно включить блок CFCATCH для перехвата этого исключения. Для этого в атрибуте TYPE тега CFCATCH указывается имя, заданное в атрибуте TYPE тега CFTHROW, или стандартный тип Application (используется по умолчанию).

    Начиная с версии 4.5, в ColdFusion поддерживаются иерархии нестандартных типов исключений, поэтому один тег CFCATCH может перехватывать целую группу нестандартных исключений, при этом проверка производится в направлении от наиболее полного имени к наименее полному. Рассмотрим следующий тег CFTHROW:

    <CFTHROW TYPE="MyApp.RequiredParameters.MyVar">

    Исключение будет перехвачено любым из следующих тегов CFCATCH:

    <CFCATCH TYPE="MyApp.RequiredParameters.MyVar">
    <CFCATCH TYPE="MyApp.RequiredParameters">
    <CFCATCH TYPE="MyApp">

    Обратите внимание: эта новая особенность ColdFusion версии 4.5 (и выше) приводит к потенциальной несовместимости с версией 4.01. В версии 4.01 нестандартное исключение

    <CFTHROW TYPE="MyApp.RequiredParameters.MyVar">

    перехватывалось только тегом CFCATCH с точно совпадающим типом исключения:

    <CFCATCH TYPE="MyApp.RequiredParameters.MyVar">

    Следующие два варианта были неработоспособными:

    <CFCATCH TYPE="MyApp.RequiredParameters">
    <CFCATCH TYPE="MyApp">

    Иерархическую проверку типов исключений в ColdFusion версии 4.5 (и выше) можно временно отключить в программе. Для этого в шаблон Application.cfm включается тег CFSETTING с атрибутом CATCHEXCEPTIONSBYPATTERN, равным No:

    <CFAPPLICATION NAME="MyApplication">
    <CFSETTING CATCHEXCEPTIONSBYPATTERN="No">

    Разобравшись с теоретическими принципами использования тега CFTHROW с конструкцией CFTRY/CFCATCH, перейдем к рассмотрению практического примера, иллюстрирующего теоретические построения. В листинге 9.5 тег CFTHROW определяет нестандартное исключение, которое инициируется в том случае, если переменная Form.MyVar не существует.

    Листинг 9.5. Перехват нестандартных исключений, инициированных тегом CFTHROW <CFTRY>

    <!--- Проверить, существует ли переменная формы MyVar.
    Если переменная не существует, инициировать нестандартное исключение. --->

    <CFIF NOT IsDefined('Form.MyVar')>
    <CFTHROW TYPE="MyApp.RequiredParameters.MissingMyVar"
    MESSAGE="The form variable MyVar does not exist!"
    DETAIL="This variable must be present for this template to
    function"
    ERRORCODE="10"
    EXTENDEDINFO="This is all the information available.">
    </CFIF>

    <!--- Перехватить нестандартное исключение. --->
    <CFCATCH TYPE="MyApp.RequiredParameters.MissingMyVar">
    <H2>Ooops - your variable (Form.MyVar) was not found! Diagnostic
    information is shown below:</H2>

    <BR>
    <H3>CFCATCH Exception Information</H3>

    <TABLE BORDER="0">
    <TR BGCOLOR="#0000FF">
    <TH><FONT COLOR="#FFFFFF">Variable</FONT></TH>
    <TH><FONT COLOR="#FFFFFF">Value</FONT></TH>
    </TR>

    <CFOUTPUT>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.Type</TD><TD>#CFCATCH.Type#</TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.Message</TD><TD>#CFCATCH.Message#</TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.Detail</TD>
    <TD>#CFCATCH.Detail#</TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.TagContext</TD>
    <TD>
    <TABLE BORDER="0">
    <TR>
    <TH COLSPAN="3">Tag Stack</TH>
    </TR>
    <TR BGCOLOR="##0000FF">
    <TH><FONT COLOR="##FFFFFF">Tag</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Position</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Template</FONT></TH>
    </TR><
    <CFLOOP index="element" from="1" TO="#ArrayLen(CFCATCH.TagContext)#">
    <CFSET TheStack = #CFCATCH.TagContext[element]#>
    <TR BGCOLOR="##D3D3D3">
    <TD>#TheStack["ID"]#</TD>
    <TD>(#TheStack["Line"]#:#TheStack["Column"]#)</TD>
    <TD>#TheStack["Template"]#</TD>
    </TR>
    </CFLOOP>
    </TABLE>
    </TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.ErrorCode</TD><TD>#CFCATCH.ErrorCode#</TD>
    </TR>
    <TR BGCOLOR="##C0C0C0">
    <TD>CFCATCH.ExtendedInfo</TD><TD>#CFCATCH.ExtendedInfo#</TD>
    </TR>
    </TABLE>
    </CFOUTPUT>
    </CFCATCH>

    </CFTRY>

    В этом примере тег CFIF в блоке CFTRY проверяет существование переменной с именем Form.MyVar. Если переменная формы не существует, тег CFTHROW генерирует нестандартное исключение. Дополнительные атрибуты описывают исключение и содержат расширенную информацию об ошибке. Созданное исключение перехватывается блоком CFCATCH, у которого атрибут TYPE совпадает с одноименным атрибутом тега CFTHROW. Блок CFCATCH перехватывает ошибку и выводит в окне браузера таблицу с информацией об исключении.

    При использовании тега CFTHROW в сочетании с CFTRY и CFCATCH автоматически определяются некоторые переменные. Вероятно, они покажутся вам знакомыми. Такие же переменные определялись и для обычного тега CFCATCH, но на этот раз большая часть информации берется из тега CFTHROW вместо того, чтобы генерироваться интерпретатором CFML.

  • CFCATCH.Type. Тип исключения.
  • CFCATCH.Message. Сообщение об ошибке, содержащееся в атрибуте MESSAGE тега CFTHROW (если этот атрибут присутствует).
  • CFCATCH.Detail. Подробное сообщение об ошибке, сгенерированное интерпретатором CFML.
  • CFCATCH.TagContext. Массив структур с именем и позицией каждого тега в стеке тегов, а также с уточненными полными именами файлов, содержащих теги. Для заполнения этой переменной в разделе Debugging Администратора ColdFusion должен быть установлен флажок CFML Stack Trace.
  • CFCATCH.ErrorCode. Значение атрибута ErrorCode тега CFTHROW (если этот атрибут присутствует).
  • CFCATCH.ExtendedInfo. Значение атрибута ExtendedInfo тега CFTHROW (если этот атрибут присутствует).

    Повторное инициирование исключений

    Итак, мы рассмотрели базовые средства обработки ошибок и исключений в приложениях ColdFusion. Методика, описанная в этом разделе, позволяет создавать более совершенные системы обработки исключений. В некоторых ситуациях исключение, которое не удается должным образом обработать в теге CFCATCH, требуется передать для дальнейшей обработки. Допустим, блок CFCATCH перехватил ошибку, на обработку которой он не рассчитан. В этом случае исключение приходится инициировать заново, чтобы оно было перехвачено другим, более компетентным обработчиком. Эта задача решается с помощью тега CFRETHROW. Этот тег используется в блоках CFCATCH с целью повторного инициирования активного исключения с сохранением значений переменных CFCATCH.Type и CFCATCH.TagContext. Таким образом, в обработчиках исключений обеспечивается дополнительный уровень принятия решений.

    Использование тега CFRETHROW лучше рассмотреть на конкретном примере. Предположим, что требуется обеспечить резервный источник данных на случай, если запрос к основному источнику данных завершится неудачей. Такую возможность желательно предусмотреть при работе с файловыми базами данных (такими, как MS Access или FoxPro), когда обновление базы часто сопряжено с перезаписью существующих файлов их обновленными версиями. Подобная страховка пригодится в приложениях электронной коммерции либо в любой программе, которая выполняет ответственную задачу и должна находиться в стадии постоянной готовности.

    В листинге 9.6 показано, как эта задача решается при помощи вложенных тегов CFTRY/CFCATCH и тега CFRETHROW.

    Листинг 9.6. Применение тега CFRETHROW

    <CFTRY>

    <!--- Попытка обращения к первой базе данных. В запросе
    указана несуществующая таблица, поэтому попытка
    заведомо обречена на неудачу. --->
    <CFTRY>
    <CFQUERY NAME="GetData" DATASOURCE="ProgrammingCF">
    SELECT * FROM BogusTable
    </CFQUERY>

    <!--- Перехватить ошибки, возникающие при обращении
    к первой базе данных. --->
    <CFCATCH TYPE="database">
    <H3>First data source failed. Attempting to use alternate...</H3>

    <!--- Создать таблицу со всеми переменными CFCATCH. --->
    <CFSET MYKEYARRAY = STRUCTKEYARRAY(CFCATCH)>
    <TABLE BORDER="0">
    <TR BGCOLOR="#0000FF">
    <TH>Name</TH><TH>Value</TH>
    </TR>
    <CFLOOP INDEX="position" FROM="1" TO="#ArrayLen(MyKeyArray)#">
    <CFOUTPUT>
    <TR BGCOLOR="##C0C0C0">
    <TD>#MyKeyArray[position]#</TD>
    <TD><CFIF ISSIMPLEVALUE(CFCATCH[MYKEYARRAY[POSITION]])>
    #CFCATCH[MyKeyArray[position]]# </TD>
    <CFELSE>
    <TABLE BORDER="0">
    <TR>
    <TH COLSPAN="3">Tag Stack</TH>
    </TR>
    <TR BGCOLOR="##0000FF">
    <TH><FONT COLOR="##FFFFFF">Tag</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Position</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Template</FONT></TH>
    </TR>
    <CFLOOP INDEX="element" FROM="1"
    TO="#ArrayLen(CFCATCH.TagContext)#">
    <CFSET THESTACK = #CFCATCH.TAGCONTEXT[ELEMENT]#>
    <TR BGCOLOR="##D3D3D3">
    <TD>#TheStack["ID"]#</TD>
    <TD>(#TheStack["Line"]#:#TheStack["Column"]#)</TD>
    <TD>#TheStack["Template"]#</TD>
    </TR>
    </CFLOOP>
    </TABLE></TD>
    </CFIF>
    </TR>
    </CFOUTPUT>
    </CFLOOP>
    </TABLE>

    <CFTRY>
    <!--- Попытка обращения с запросом ко второй базе данных.
    Несуществующий источник данных указан и на этот раз,
    поэтому попытка завершится неудачей. Это делается лишь
    для демонстрации использования тега CFRETHROW. --->
    <CFQUERY NAME="GetData" DATASOURCE="ProgrammidngCF">
    SELECT * FROM EmployeeDirectory
    </CFQUERY>

    <!--- При возникновении проблем со второй базой данных
    исключение инициируется заново, что позволяет его обработать с помощью
    общего обработчика CFCATCH. --->
    <CFCATCH TYPE="database">
    <H3>Alternate data source failed. Rethrowing exception...</H3>
    <CFSET MYKEYARRAY = STRUCTKEYARRAY(CFCATCH)>
    <TABLE BORDER="0">
    <TR BGCOLOR="#0000FF">
    <TH>Name</TH>
    <TH>Value</TH>
    </TR>
    <CFLOOP INDEX="position" FROM="1" TO="#ArrayLen(MyKeyArray)#">
    <CFOUTPUT>
    <TR BGCOLOR="##C0C0C0">
    <TD>#MyKeyArray[position]#</TD>
    <TD><CFIF ISSIMPLEVALUE(CFCATCH[MYKEYARRAY[POSITION]])>
    #CFCATCH[MyKeyArray[position]]# </TD>
    <CFELSE>
    <TABLE BORDER="0">
    <TR>
    <TH COLSPAN="3">Tag Stack</TH>
    </TR>
    <TR BGCOLOR="##0000FF">
    <TH><FONT COLOR="##FFFFFF">Tag</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Position</FONT></TH>
    <TH><FONT COLOR="##FFFFFF">Template</FONT></TH>
    </TR>
    <CFLOOP INDEX="element" FROM="1"
    TO="#ArrayLen(CFCATCH.TagContext)#">
    <CFSET THESTACK = #CFCATCH.TAGCONTEXT[ELEMENT]#>
    <TR BGCOLOR="##D3D3D3">
    <TD>#TheStack["ID"]#</TD>
    <TD>(#TheStack["Line"]#:#TheStack["Column"]#)</TD>
    <TD>#TheStack["Template"]#</TD>
    </TR>
    </CFLOOP>
    </TABLE></TD>
    </CFIF>
    </TR>
    </CFOUTPUT>
    </CFLOOP>
    </TABLE>
    </CFCATCH>
    </CFTRY>

    Сначала шаблон пытается обратиться к основному источнику данных. При возникновении исключения делается попытка переадресовать запрос резервному источнику данных. Если при обращении к резервному источнику данных генерируется исключение, тег CFRETHROW инициирует его повторно для перехвата общим обработчиком CFCATCH с атрибутом TYPE="Any". Чтобы лучше разобраться в происходящем, обратитесь к следующему фрагменту, написанному на псевдокоде:

    try {
    обратиться к базе данных
    }
    catch(ошибки базы данных){
    вывести информацию об исключении
    try{
    обратиться к резервной базе данных
    }
    catch(ошибки базы данных){
    вывести информацию об исключении
    инициировать исключение заново
    }
    }
    catch(любые исключения){
    вывести информацию об исключении
    }

    При каждом перехвате исключения листинг 9.6 выводит в окне браузера значения всех переменных CFCATCH. Анализ этих переменных поможет вам понять, что при этом происходит.

    Обработка ошибок в Web Application Framework

    Теги CFTRY и CFCATCH обеспечивают высокую степень контроля обработки ошибок и исключений, однако они неудобны в программировании. Задача усложняется еще и тем, что вам придется выявить все места приложения, где могут возникнуть потенциальные проблемы, и заключить их в теги CFTRY/CFCATCH. К счастью, в ColdFusion существует механизм обработки ошибок, реализованный на более общем уровне. Включение тега CFERROR в шаблон Application.cfm позволяет определить обработчики ошибок на уровне приложения, то есть независимо от точки их возникновения.

    Хотя тег CFERROR может использоваться не только в Application.cfm, но и в других шаблонах, здесь его присутствие представляется наиболее логичным. Обычно тег CFERROR следует сразу же после тега CFAPPLICATION:

    <CFAPPLICATION NAME="MyApplication">

    <!--- Обработка ошибок --->
    <CFERROR TYPE="Exception" TEMPLATE="MyRequestHandler.cfm"
    EXCEPTION="Any" MAILTO="webmaster@example.com">

    В зависимости от значения атрибута TYPE тег CFERROR позволяет организовать четыре разновидности обработки ошибок. Обязательный атрибут TEMPLATE задает относительный путь к шаблону, который должен быть выполнен в случае возникновения ошибки или исключения. Ниже перечислены значения атрибута TYPE и задачи, решаемые шаблонами-обработчиками соответствующих типов.

  • Exception. Обработка конкретного типа исключения, заданного атрибутом EXCEPTION тега CFERROR. Шаблон-обработчик может содержать любые теги ColdFusion. Он также может вызываться назначением обработчика ошибок уровня сайта в разделе Server Settings Администратора ColdFusion.
  • Monitor. Установка монитора для исключения, тип которого задается атрибутом EXCEPTION тега CFERROR. Используется при отслеживании и отладке приложений ColdFusion. При реализации этого варианта обработки исключений ColdFusion вызывает заданный шаблон перед выполнением кода CFTRY/CFCATCH, присутствующего в выполняемом шаблоне.
  • Request (значение по умолчанию). Обработка любых ошибок, возникших в процессе обращения к шаблону. В шаблоне-обработчике доступны лишь переменные Error. Кроме того, в нем не могут присутствовать другие теги CFML.
  • Validation. Обработка ошибок проверки полей, происходящих при отправке данных формы. Этот тип приносит практическую пользу лишь в том случае, если тег включается в шаблон Application.cfm. В шаблоне-обработчике доступны лишь переменные Error. Кроме того, в нем не могут присутствовать другие теги или функции CFML.

    Если атрибуту TYPE присваивается значение Exception или Monitor, то в атрибуте EXCEPTION должен быть указан тип исключения, перехватываемого тегом CFERROR. Допускаются те же значения, что и в теге CFCATCH: Any (по умолчанию), Application, нестандартный_тип, Database, Expression, Lock, MissingInclude, Object, Security и Template. Тег CFERROR, по аналогии с CFCATCH, поддерживает и другие типы исключений, перечисленные при описании тега CFTRY в приложении А.

    Последний атрибут, MAILTO, не обязателен. В нем передается адрес электронной почты, по которому отправляется сообщение о возникшей ошибке. Значение MAILTO доступно в обработчике, указанном в атрибуте TEMPLATE.

    В зависимости от выбранного типа обработки ошибок (атрибут TYPE) ColdFusion предоставляет шаблону, указанному в атрибуте TEMPLATE, доступ к нескольким переменным, на которые можно ссылаться в блоке CFOUTPUT. На эти переменные можно ссылаться по именам или по ассоциированным ключам из структуры ColdFusion с именем Error. При обработке типов Exception, Monitor и Request доступны следующие переменные:

  • Error.Browser — браузер, используемый при возникновении ошибки;
  • Error.DateTime — дата и время возникновения ошибки;
  • Error.Diagnostics — подробное сообщение об ошибке, предоставленное сервером ColdFusion;
  • Error.HTTPReferer — страница, содержащая ссылку на шаблон, в котором возникла ошибка;
  • Error.MailTo — адрес электронной почты, заданный в атрибуте MAILTO тега CFERROR;
  • Error.RemoteAddress — IP-адрес удаленного клиента;
  • Error.QueryString — строка запроса URL из клиентского обращения;
  • Error.Template — страница, выполнявшаяся в момент возникновения ошибки.

    Если атрибут TYPE равен Monitor или Exception, также доступна следующая переменная:

  • Error.GeneratedContent — информация, сгенерированная при неудачном обращении.

    Кроме перечисленных переменных, в шаблоне-обработчике могут использоваться переменные CFCATCH для исключения, указанного в атрибуте EXCEPTION тега CFERROR, — Error.Type, Error.Message, Error.Detail, Error.TagContext, Error.ErrorCode, Error.NativeErrorCode, Error.SQLState, Error.ErrNumber, Error.LockName, Error.LockOperation, Error.MissingFileName и Error.ExtendedInfo1.

    Для типа Validation доступны следующие переменные:

  • Error.ValidationHeader — стандартный заголовочный элемент страницы проверки данных;
  • Error.InvalidFields — неупорядоченный список HTML, содержащий информацию об ошибках проверки (<UL>);
  • Error.ValidationFooter — стандартный завершающий элемент страницы проверки данных;
  • Error.MailTo — адрес электронной почты, переданный в атрибуте MAILTO тега CFERROR.

    От теоретического описания тега CFERROR мы переходим к конкретным примерам его использования. В оставшейся части этой главы описаны все три типа обработки исключений.

    Ошибки при проверке форм

    Ошибки проверки возникают лишь при использовании встроенных средств проверки данных в заполненных формах. Как упоминалось в главе 3, для проверки введенных данных ColdFusion позволяет создавать в формах HTML специальные скрытые поля с суффиксами _required, _date, _eurodate, _time, _integer, _float и _range.

    Обычно при нарушении правила проверки ColdFusion выводит обобщенную страницу с информацией о нарушении правила. Иногда это удобно, но, как правило, страница, сгенерированная ColdFusion, оставляет желать лучшего. Программист не располагает средствами, которые позволяли бы изменить эту страницу при нарушении определенного правила. Тем не менее, тег CFERROR с атрибутом TYPE="Validation" помогает решить эту проблему (в определенной степени). Хотя тег CFERROR может находиться прямо в странице, обрабатывающей полученные данные формы, лучше поместить его в шаблоне Application.cfm, поскольку подобные обработчики ошибок обычно устанавливаются на уровне всего приложения, а не на уровне отдельной формы. В следующих примерах показывается, как организуется нестандартная обработка ошибок проверки в приложении. Прежде всего,создается шаблон Application.cfm с тегом CFERROR, обеспечивающим кодом вызова шаблона-обработчика (листинг 9.7).

    Листинг 9.7. Тег CFERROR, используемый для обработки ошибок проверки форм

    <CFAPPLICATION NAME="MyApplication">

    <!--- Обработка ошибок при заполнении формы. --->
    <CFERROR TYPE="Validation" TEMPLATE="ValidationHandler.cfm"
    MAILTO="webmaster@example.com">

    Пользовательский обработчик ошибок при заполнении формы создается всего лишь при помощи одного тега CFERROR. Атрибут TYPE="Validation" говорит о том, что любые ошибки проверки должны обрабатываться с помощью шаблона, указанного в теге. Атрибут TEMPLATE задает относительный путь к шаблону ColdFusion, вызываемому при возникновении ошибки. В приведенном примере вызывается шаблон ValidationHandler.cfm, находящийся в одном каталоге с шаблоном Application.cfm. Последний необязательный атрибут MAILTO содержит адрес электронной почты лица, которое следует известить о факте возникновения ошибки. Значение MAILTO доступно в шаблоне-обработчике, указанном в атрибуте TEMPLATE.

    На этом будет завершено рассмотрение шаблона Application.cfm. А теперь рассмотрим шаблон ValidationHandler.cfm, который должен вызываться при возникновении ошибок проверки (листинг 9.8).

    Листинг 9.8. Шаблон ValidationHandler.cfm (нестандартная обработка ошибок проверки)

    <BODY BGCOLOR="#FFFFCC">

    <CENTER>
    <H2>Validation Handler</H2>

    <TABLE BORDER="1" CELLPADDING="10">
    <TR>
    <TD>
    #Error.ValidationHeader#<BR>
    #Error.InvalidFields#<BR>
    #Error.ValidationFooter#
    <P>
    Please send any questions or comments to
    <A HREF="mailto:#Error.Mailto#">#Error.Mailto#</A>
    </TD>
    </TR>
    </TABLE>
    </CENTER>

    </BODY>

    Как упоминалось ранее, в шаблоне ValidationHandler.cfm могут использоваться только переменные, содержащие сведения об ошибке. Использовать тег CFOUTPUT не нужно; более того, в этом шаблоне вообще не могут присутствовать функции и теги CFML. В приведенном примере задается цвет фона и создается таблица HTML, выровненная по центру. Эта таблица применяется для вывода информации об ошибке. На странице выводится сообщение о наличии неполной или неправильной информации, хранящееся в переменной Error.ValidationHeader. Если вы предпочитаете вывести другой заголовок для формы, просто замените ссылку на эту переменную собственным текстом. Далее в таблице выводится неупорядоченный (маркированный) список ошибок проверки с использованием переменной Error.InvalidFields. Маркеры автоматически создаются ColdFusion, изменить их невозможно. Завершающая надпись («Use the Back button on your web browser to return to the previous page and correct the listed problems»1) автоматически создается по ссылке на переменную Error.Footer. Страница завершается ссылкой на контактный адрес электронной почты, хранящийся в переменной Error.MailTo. Как упоминалось ранее, значение этой переменной передается в атрибуте MAILTO тега CFERROR.

    Шаблоны Application.cfm и ValidationHandler.cfm спроектированы, остается лишь создать шаблон для их тестирования. Код проверяемой формы приведен в листинге 9.9. Тестовый шаблон должен храниться под именем ValidationTest.cfm в одном каталоге с другими шаблонами этого примера.

    Листинг 9.9. Тестовая форма HTML

    <H2>Article Submission Form</H2>
    <FORM ACTION="ValidationTest.cfm" METHOD="post">
    <INPUT TYPE="hidden" NAME="ArticleDate_date" VALUE="You must supply a valid date
    format (ex. 11/11/2000).">
    <INPUT TYPE="hidden" NAME="Title_required" VALUE="You must enter a title for the
    article.">
    <INPUT TYPE="hidden" NAME="Priority_required" VALUE="You must enter a priority
    for the article.">
    <INPUT TYPE="hidden" NAME="Priority_range" VALUE="Min=1 Max=100">

    <TABLE>
    <TR>
    <TD>Date:</TD>
    <TD><INPUT TYPE="text" NAME="ArticleDate" SIZE="12" MAXLENGTH="10"></TD>
    </TR>
    <TR>
    <TD>Title:</TD>
    <TD><INPUT TYPE="text" NAME="Title" SIZE="50" MAXLENGTH="255"></TD>
    </TR>
    <TR>
    <TD>Article:</TD>
    <TD><TEXTAREA COLS="43" ROWS="5" NAME="Article"></TEXTAREA></TD>
    </TR>
    <TR>
    <TD>Priority (1-100):</TD>
    <TD><INPUT TYPE="text" NAME="Priority" SIZE="4" MAXLENGTH="3"></TD>
    </TR>
    <TR>
    <TD COLSPAN="2"><INPUT TYPE="submit" NAME="Submit" VALUE="submit"></TD>
    </TR>
    </TABLE>
    </FORM>

    Обратите внимание на объявления четырех скрытых полей за тегом FORM. Стандартные суффиксы определяют правила проверки полей, с имен которых начинается атрибут NAME. При отправке данных формы ColdFusion проверяет, соответствует ли значение указанного поля правилу, установленному при помощи скрытого поля. Если какие-либо правила нарушаются, тег CFERROR в шаблоне Application.cfm вызывает шаблон ValidationHandler.cfm с выводом нестандартного сообщения об ошибке. Соответствующий пример показан на рис. 9.1.

    Рис. 9.1. Страница с сообщением об ошибке, вызванная в результате проверки данных

  • Начало
    Cодержание
    Отрывок
    [Заказать книгу в магазине "Мистраль"]

     

    Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

    Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

    Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

    Виртуальные VPS серверы в РФ и ЕС

    Dedicated серверы в РФ и ЕС

    По промокоду CITFORUM скидка 30% на заказ VPS\VDS

    VPS/VDS серверы. 30 локаций на выбор

    Серверы VPS/VDS с большим диском

    Хорошие условия для реселлеров

    4VPS.SU - VPS в 17-ти странах

    2Gbit/s безлимит

    Современное железо!

    Новости мира IT:

    Архив новостей

    IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
    тел. +7 495 7861149
    Пресс-релизы — pr@citforum.ru
    Обратная связь
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...