|
| ||||||||||||
| ||||||||||||
|
Книги: [Классика] [Базы данных] [Internet/WWW] [Сети] [Программирование] [UNIX] [Windows] [Безопасность] [Графика] [Software Engineering] [ERP-системы] [Hardware]
Отрывок
Глава 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 TYPE="тип_исключения"> </CFTRY> Конструкция CFTRY/CFCATCH устроена весьма просто. Сначала фрагмент кода, в котором обрабатываются исключения, заключается в теги CFTRY. Сразу же за этим фрагментом следует один или несколько блоков CFCATCH, предназначенных для перехвата исключений разных типов. Таким образом, фрагмент защищается от возникновения сразу нескольких исключений. Блоки CFCATCH могут содержать любой код HTML и CFM, в том числе и ссылки на переменные CFCATCH (см. далее). Блоки CFCATCH могут содержать вложенные конструкции CFTRY/CFCATCH. Рассмотрим конкретный пример. Допустим, что приложение при помощи тега CFHTTP считывает данные из текстового файла, который регулярно создается и сохраняется на сервере. Существует вероятность того, что приложение попытается обратиться к текстовому файлу во время обновления, что приведет к ошибке. Для предотвращения ошибки тег CFHTTP заключается в теги CFTRY/CFCATCH, что позволяет предотвращать любые исключительные ситуации, возникающие при обращении к текстовому файлу. В листинге 9.1 приведен простейший вариант обработки исключения — вывод сообщения о том, что файл обновляется, и предложения повторить попытку через несколько минут. Листинг 9.1. Блок CFTRY/CFCATCH, выполняющий обработку любых исключений, возникших при вызове тега CFHTTP <!--- Попытаться получить информацию из файла биржевых котировок <CFHTTP URL="http://www.example.com/myfile.txt" METHOD="GET" <!--- Перехватить любые исключения и сообщить пользователю о том, </CFTRY> При вызове тега CFCATCH передается единственный атрибут TYPE, определяющий тип исключения. Ниже приведен список допустимых значений атрибута TYPE. Кроме исключений, соответствующих значениям атрибута TYPE, в ColdFusion поддерживаются и другие типы структурных исключений, возникающие в крайне специфических условиях, например, при тайм-ауте обращений к страницам или в результате вызова некоторых тегов ColdFusion. Эти типы исключений перечислены в описании тега CFTRY, находящегося в приложении А. Как упоминалось ранее, блок CFCATCH может содержать ссылки на переменные CFCATCH. Эти переменные автоматически генерируются при перехвате исключения блоком CFCATCH и хранятся в структуре CFCATCH. Переменные CFCATCH доступны только в блоке CFCATCH и используются при выполнении разных операций — принятия решений, влияющих на обработку, записи данных в журнал, а также для вывода специализированных сообщений об ошибках или информации для пользователей. Кроме того, в блоках CATCH может использоваться любой допустимый код HTML, CFML и JavaScript. Переменные, перечисленные ниже, доступны для всех типов исключений. Для присвоения значений переменной CFCATCH.TagContext в разделе Debugging Администратора ColdFusion должен быть установлен флажок CFML Stack Trace. Если флажок не установлен, с помощью переменной CFCATCH.TagContext возвращается массив нулевой длины. Кроме перечисленных переменных, существуют и другие, доступные только для конкретных видов исключений. Они перечислены в описании тега CFTRY в приложении А. В следующих примерах продемонстрирована методика перехвата различных типов исключений и другие возможности их обработки. В листинге 9.2 исключение возникает при попытке использования в выражении неопределенной переменной (y). Поскольку в перехватчике указан универсальный тип исключения (атрибут TYPE="Any"), в данном примере тег CFCATCH является примером общего обработчика исключений. Листинг 9.2. Перехват исключений с использованием тегов CFTRY/CFCATCH <CFTRY> <CFCATCH TYPE="Any"> <BR> <TABLE BORDER="0"> </CFCATCH> Блок CFCATCH перехватывает все возникающие исключения (TYPE="Any"). На практике тегу CFCATCH, перехватывающему все исключения, обычно предшествуют теги CFCATCH для конкретных типов исключений. Иначе говоря, в конструкциях с несколькими тегами CFCATCH тег для перехвата «всех остальных» исключений (если он присутствует) находится на последнем месте. В этом примере он использован только в демонстрационных целях. При выполнении этого шаблона вступает в действие блок CFCATCH, в котором тег CFMAIL автоматически создает сообщение электронной почты и отправляет его администратору сайта, оповещая его о возникшей ошибке. В сообщение включается имя отсутствующего шаблона. Несмотря на генерируемое исключение, благодаря конструкции CFTRY/CFCATCH шаблон может продолжать выполнение. Как упоминалось ранее, один блок CFTRY может содержать несколько тегов CFCATCH. Такая ситуация продемонстрирована в листинге 9.4, где для одного фрагмента кода определяются обработчики двух различных типов исключений. Листинг 9.4. Перехват нескольких типов исключений в конструкциях CFTRY/CFCATCH <CFTRY> <!--- По умолчанию переменной LogFileStatus присваивается признак <H2>Attempting to write a log file entry...</H2> <!--- Заблокировать вызов CFFILE, чтобы в любой момент времени <!--- Записать данные в журнал. ---> <!--- Перехватывать исключения блокировки. ---> <!-- Перехватывать исключения всех остальных типов. ---> <P> В этом шаблоне тег 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="тип_нестандартного_исключения" При вызове тега CFTHROW могут определяться необязательные атрибуты: Разумеется, если некоторый фрагмент кода CFML инициирует нестандартное исключение тегом CFTHROW, в шаблон нужно включить блок CFCATCH для перехвата этого исключения. Для этого в атрибуте TYPE тега CFCATCH указывается имя, заданное в атрибуте TYPE тега CFTHROW, или стандартный тип Application (используется по умолчанию). Начиная с версии 4.5, в ColdFusion поддерживаются иерархии нестандартных типов исключений, поэтому один тег CFCATCH может перехватывать целую группу нестандартных исключений, при этом проверка производится в направлении от наиболее полного имени к наименее полному. Рассмотрим следующий тег CFTHROW: <CFTHROW TYPE="MyApp.RequiredParameters.MyVar"> Исключение будет перехвачено любым из следующих тегов CFCATCH: <CFCATCH TYPE="MyApp.RequiredParameters.MyVar"> Обратите внимание: эта новая особенность ColdFusion версии 4.5 (и выше) приводит к потенциальной несовместимости с версией 4.01. В версии 4.01 нестандартное исключение <CFTHROW TYPE="MyApp.RequiredParameters.MyVar"> перехватывалось только тегом CFCATCH с точно совпадающим типом исключения: <CFCATCH TYPE="MyApp.RequiredParameters.MyVar"> Следующие два варианта были неработоспособными: <CFCATCH TYPE="MyApp.RequiredParameters"> Иерархическую проверку типов исключений в ColdFusion версии 4.5 (и выше) можно временно отключить в программе. Для этого в шаблон Application.cfm включается тег CFSETTING с атрибутом CATCHEXCEPTIONSBYPATTERN, равным No: <CFAPPLICATION NAME="MyApplication"> Разобравшись с теоретическими принципами использования тега CFTHROW с конструкцией CFTRY/CFCATCH, перейдем к рассмотрению практического примера, иллюстрирующего теоретические построения. В листинге 9.5 тег CFTHROW определяет нестандартное исключение, которое инициируется в том случае, если переменная Form.MyVar не существует. Листинг 9.5. Перехват нестандартных исключений, инициированных тегом CFTHROW <CFTRY> <!--- Проверить, существует ли переменная формы MyVar. <CFIF NOT IsDefined('Form.MyVar')> <!--- Перехватить нестандартное исключение. ---> <BR> <TABLE BORDER="0"> <CFOUTPUT> </CFTRY> В этом примере тег CFIF в блоке CFTRY проверяет существование переменной с именем Form.MyVar. Если переменная формы не существует, тег CFTHROW генерирует нестандартное исключение. Дополнительные атрибуты описывают исключение и содержат расширенную информацию об ошибке. Созданное исключение перехватывается блоком CFCATCH, у которого атрибут TYPE совпадает с одноименным атрибутом тега CFTHROW. Блок CFCATCH перехватывает ошибку и выводит в окне браузера таблицу с информацией об исключении. При использовании тега CFTHROW в сочетании с CFTRY и CFCATCH автоматически определяются некоторые переменные. Вероятно, они покажутся вам знакомыми. Такие же переменные определялись и для обычного тега CFCATCH, но на этот раз большая часть информации берется из тега CFTHROW вместо того, чтобы генерироваться интерпретатором CFML. Повторное инициирование исключений Итак, мы рассмотрели базовые средства обработки ошибок и исключений в приложениях ColdFusion. Методика, описанная в этом разделе, позволяет создавать более совершенные системы обработки исключений. В некоторых ситуациях исключение, которое не удается должным образом обработать в теге CFCATCH, требуется передать для дальнейшей обработки. Допустим, блок CFCATCH перехватил ошибку, на обработку которой он не рассчитан. В этом случае исключение приходится инициировать заново, чтобы оно было перехвачено другим, более компетентным обработчиком. Эта задача решается с помощью тега CFRETHROW. Этот тег используется в блоках CFCATCH с целью повторного инициирования активного исключения с сохранением значений переменных CFCATCH.Type и CFCATCH.TagContext. Таким образом, в обработчиках исключений обеспечивается дополнительный уровень принятия решений. Использование тега CFRETHROW лучше рассмотреть на конкретном примере. Предположим, что требуется обеспечить резервный источник данных на случай, если запрос к основному источнику данных завершится неудачей. Такую возможность желательно предусмотреть при работе с файловыми базами данных (такими, как MS Access или FoxPro), когда обновление базы часто сопряжено с перезаписью существующих файлов их обновленными версиями. Подобная страховка пригодится в приложениях электронной коммерции либо в любой программе, которая выполняет ответственную задачу и должна находиться в стадии постоянной готовности. В листинге 9.6 показано, как эта задача решается при помощи вложенных тегов CFTRY/CFCATCH и тега CFRETHROW. Листинг 9.6. Применение тега CFRETHROW <CFTRY> <!--- Попытка обращения к первой базе данных. В запросе <!--- Перехватить ошибки, возникающие при обращении <!--- Создать таблицу со всеми переменными CFCATCH. ---> <CFTRY> <!--- При возникновении проблем со второй базой данных Сначала шаблон пытается обратиться к основному источнику данных. При возникновении исключения делается попытка переадресовать запрос резервному источнику данных. Если при обращении к резервному источнику данных генерируется исключение, тег CFRETHROW инициирует его повторно для перехвата общим обработчиком CFCATCH с атрибутом TYPE="Any". Чтобы лучше разобраться в происходящем, обратитесь к следующему фрагменту, написанному на псевдокоде: try { При каждом перехвате исключения листинг 9.6 выводит в окне браузера значения всех переменных CFCATCH. Анализ этих переменных поможет вам понять, что при этом происходит. Обработка ошибок в Web Application Framework Теги CFTRY и CFCATCH обеспечивают высокую степень контроля обработки ошибок и исключений, однако они неудобны в программировании. Задача усложняется еще и тем, что вам придется выявить все места приложения, где могут возникнуть потенциальные проблемы, и заключить их в теги CFTRY/CFCATCH. К счастью, в ColdFusion существует механизм обработки ошибок, реализованный на более общем уровне. Включение тега CFERROR в шаблон Application.cfm позволяет определить обработчики ошибок на уровне приложения, то есть независимо от точки их возникновения. Хотя тег CFERROR может использоваться не только в Application.cfm, но и в других шаблонах, здесь его присутствие представляется наиболее логичным. Обычно тег CFERROR следует сразу же после тега CFAPPLICATION: <CFAPPLICATION NAME="MyApplication"> <!--- Обработка ошибок ---> В зависимости от значения атрибута TYPE тег CFERROR позволяет организовать четыре разновидности обработки ошибок. Обязательный атрибут TEMPLATE задает относительный путь к шаблону, который должен быть выполнен в случае возникновения ошибки или исключения. Ниже перечислены значения атрибута TYPE и задачи, решаемые шаблонами-обработчиками соответствующих типов. Если атрибуту 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 доступны следующие переменные: Если атрибут TYPE равен Monitor или Exception, также доступна следующая переменная: Кроме перечисленных переменных, в шаблоне-обработчике могут использоваться переменные 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 доступны следующие переменные: От теоретического описания тега 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 задает относительный путь к шаблону ColdFusion, вызываемому при возникновении ошибки. В приведенном примере вызывается шаблон ValidationHandler.cfm, находящийся в одном каталоге с шаблоном Application.cfm. Последний необязательный атрибут MAILTO содержит адрес электронной почты лица, которое следует известить о факте возникновения ошибки. Значение MAILTO доступно в шаблоне-обработчике, указанном в атрибуте TEMPLATE. На этом будет завершено рассмотрение шаблона Application.cfm. А теперь рассмотрим шаблон ValidationHandler.cfm, который должен вызываться при возникновении ошибок проверки (листинг 9.8). Листинг 9.8. Шаблон ValidationHandler.cfm (нестандартная обработка ошибок проверки) <BODY BGCOLOR="#FFFFCC"> <CENTER> <TABLE BORDER="1" CELLPADDING="10"> </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> <TABLE> Обратите внимание на объявления четырех скрытых полей за тегом FORM. Стандартные суффиксы определяют правила проверки полей, с имен которых начинается атрибут NAME. При отправке данных формы ColdFusion проверяет, соответствует ли значение указанного поля правилу, установленному при помощи скрытого поля. Если какие-либо правила нарушаются, тег CFERROR в шаблоне Application.cfm вызывает шаблон ValidationHandler.cfm с выводом нестандартного сообщения об ошибке. Соответствующий пример показан на рис. 9.1. ![]() Рис. 9.1. Страница с сообщением об ошибке, вызванная в результате проверки данных
Начало
|
|
CITForum © 1997–2025