Зачем говорить об обработке исключений в проекте J2EE? Может быть, многие начинающие Java хотят сказать: «Разве обрабатывание исключений просто попробуйте ... поймать ... наконец? Все это знают!» Автор также думает так, когда он новичок в Java. Как определить соответствующий класс исключений в многослойном проекте J2EE? Как справиться с исключениями на каждом уровне в проекте? Когда исключение брошено? Когда записано исключение? Как записать исключения? Когда я должен преобразовать проверенное исключение в неконтролируемое исключение, и когда мне следует преобразовать неверное исключение в проверенное исключение? Следует ли быть представленным на линейной странице? Как разработать структуру исключения? Эти вопросы будут обсуждаться в этой статье.
1. Обработка исключений Java
В языках процедурного программирования мы можем определить, обычно выполняется метод, возвращая значение. Например, в программе, написанной на языке C, если метод будет выполнен правильно, она вернется 1. Если ошибка будет выполнена, она вернет 0. В приложении, разработанном VB или Delphi, когда произойдет ошибка, мы всплываем поле сообщения пользователю.
Мы не можем получить данные ошибки через возвращаемое значение метода. Это может быть связано с тем, что метод записывается разными программистами, когда один и тот же тип ошибки происходит в разных методах, возвращаемые результаты и информация об ошибках не являются согласованными.
Поэтому язык Java принимает единый механизм обработки исключений.
Что такое исключение? Уловимые и обработанные ошибки, возникающие во время выполнения.
На языке Java исключение является родительский класс всех исключений. Любое исключение распространяется на класс исключений. Исключение эквивалентно типу ошибки. Если вы хотите определить новый тип ошибки, расширите новый подкласс исключений. Преимущество использования исключений заключается в том, что он может точно найти местоположение исходного кода, который вызывает ошибку программы и получает подробную информацию об ошибке.
Обработка исключений Java реализуется через пять ключевых слов, попробуйте, ловит, бросает, бросает, наконец. Конкретная структура обработки исключений реализована Try… .catch… .finally Block. Try Block хранят заявления Java, которые могут иметь исключения. Уловка используется, чтобы поймать возникновение исключений и обработки исключений. Окончательный блок используется для очистки необработанных ресурсов в программе. Окончательный блок всегда выполняется, если код, который не управляет тем, как возвращается блок Try Block.
Типичный код обработки исключений
public String getPassword (String userId) Throws DataCcessException {string sql = "Выберите пароль из userInfo, где userId = '" +userId +"'"; string password = null; соединение con = null; оператор s = null; resultset rs = null; try {con = getConnect (); // get connections s = con.createTatation (); while (rs.next ()) {password = rs.getString (1);} rs.close (); s.close ();} catch (sqlexception ex) {throw new DataCcessException (ex);} наконец {try {if (con! Не удалось! », SQLEX);}} вернуть пароль;} Видно, что преимущества механизма обработки исключений Java:
Ошибка классифицируется равномерно и реализуется путем расширения класса исключений или его подкласса. Это избегает того, чтобы одна и та же ошибка может иметь разные сообщения об ошибках в разных методах. Когда такая же ошибка возникает в разных методах, вам нужно только бросить один и тот же объект исключения.
Получите более подробную информацию об ошибках. Благодаря классам исключений информация об ошибках может быть предоставлена исключению, которое является более подробным и более полезным для пользователя. Пользователям легко отслеживать и отлаживать программы.
Разделите правильный результат возврата от сообщения об ошибке. Уменьшает сложность программы. Звониму не нужно больше знать о результате возврата.
Заставляйте вызывающего абонента справиться с исключениями, чтобы улучшить качество программы. Когда декларация метода должно бросить исключение, абонент должен использовать блок Try .... Catch для обработки исключения. Конечно, звонящий также может позволить исключению продолжать быть выброшенным на верхний уровень.
2. Проверено исключение или неконтролируемое исключение?
Исключения Java делятся на две категории: проверенное исключение и неконтролируемое исключение. Все исключения, которые наследуют java.lang.xception, принадлежат проверенным исключениям. Все исключения, которые наследуют java.lang.runtimeexception, принадлежат к неконтролируемым исключениям.
Когда метод вызывает метод, который может выбросить проверенное исключение, исключение должно быть захвачено и обработано или переоборудовано через блок Try ... Catch.
Давайте посмотрим на декларацию метода CenseStatement () интерфейса соединения.
Public Protect CroteStatement () бросает SQLEXCEPTION; SQLEXCEPTION - проверенное исключение. Когда называется метод создания, Java заставляет вызывающего абонента захватить SQLexception. public String getPassword (String userId) {try {... оператор s = con.createStatement (); ... Catch (sqlexception sqlex) {...} ...} или
public String getPassword (String userId) Throws SQLexception {оператор s = con.createStatement ();} (Конечно, такие ресурсы, как соединение и сперент, должны быть закрыты вовремя. Это просто для того, чтобы проиллюстрировать, что проверенное исключение должно заставить вызывающего абонента поймать или продолжать бросать)
Неконтролируемое исключение также называется исключением времени выполнения. Обычно runtimeexception указывает на исключение, которое пользователь не может восстановить, например, неспособность получить подключение к базе данных, неспособность открыть файл и т. Д., Хотя пользователь также может уловить неконтролируемые исключения, такие как контролируемые исключения. Но если звонящий не поймает неконтролируемое исключение, компилятор не заставит вас делать это.
Например, код, который преобразует символы в целочисленные значения, заключается в следующем:
String str = "123"; int value = integer.parseint (str);
Подпись метода Parseint:
Public Staticint Parseint (String S) бросает номеру форматмиксация
Когда пройденные параметры не могут быть преобразованы в соответствующее целое число, будет выброшено числовое формирование. Поскольку numberformatexception распространяется на Runtimeexception, это неконтролируемое исключение. Так что нет необходимости пробовать ... поймать при вызове метода Parseint
Потому что Java не заставляет вызывающего абонента ловить или бросить неконтролируемое исключение. Поэтому программисты всегда любят делать неконтролируемые исключения. Или когда необходим новый класс исключений, он всегда используется для расширения от Runtimeexception. Когда вы называете эти методы, если нет соответствующего блока улова, компилятор всегда позволит вам пройти, и вам не нужно понимать, какое исключение будет бросить этот метод. Похоже, это хорошая идея, но это далеко от реального намерения обработки исключений Java. И это вводит в заблуждение программиста, который называет ваш класс, потому что звонящий не имеет ни малейшего представления, при каких обстоятельствах он должен справиться с исключениями. Проверенное исключение может четко сообщить абоненту, какие исключения должны быть обработаны при вызове этого класса. Если абонент не обрабатывает его, компилятор будет запрашивать и не может компилировать и пройти. Конечно, как решить, как с этим справиться.
Таким образом, Java рекомендует, чтобы люди использовали проверенные исключения в коде своего приложения. Точно так же, как мы упомянули в предыдущем разделе, что преимущество использования исключений заключается в том, что он может заставить вызывающего вызов обрабатывать исключения, которые будут сгенерированы. Проверенные исключения используются в качестве стандарта в официальных документах Java, таких как «Учебное пособие по Java».
Использование проверенных исключений должно означать, что в вашем коде есть много попыток. После написания и обработки все больше и больше пытаться ... поймать блоки, многие люди наконец начали задаваться вопросом, следует ли использовать проверенные исключения в качестве стандарта.
Даже Брюс Экель, автор знаменитого «мышления на Яве», изменил его прежние мысли. Брюс Экель даже выступает за неконтролируемые исключения в качестве стандартного использования. И опубликовать статью, чтобы проверить, следует ли убрать проверенное исключение из Java. Брюс Экель: «Когда небольшое количество кода, проверенные исключения, несомненно, являются очень элегантной концепцией и помогают избежать многих потенциальных ошибок. Но опыт показывает, что результат является точно противоположным для большого количества кода».
Для получения подробных обсуждений об проверенных исключениях и неконтролируемых исключениях, пожалуйста, см.
Учебное пособие Java http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html
Использование проверенных исключений может вызвать многие проблемы.
Проверено исключение вызывает слишком много попыток ... поймать код
Может быть много проверенных исключений, которые не могут быть разумно обработаны разработчиками, такими как SQLexception. Но разработчики должны попробовать ... поймать. Когда разработчики не могут правильно справиться с проверенным исключением, они обычно просто распечатывают исключение или ничего не делают. Особенно для новичков слишком много проверенных исключений заставляют его чувствовать себя в растерянности.
try {… оператор s = con.createStatement ();… Catch (sqlexception sqlex) {sqlex.printstacktrace ();} или
try {... оператор s = con.createStatement (); ... Catch (sqlexception sqlex) {// ничего не делать} Проверенное исключение вызывает много трудного для понимания кода.
Когда разработчики должны поймать проверенное исключение, которое они не могут правильно справиться, они обычно переупаковываются в новое исключение, а затем бросают. Это не приносит никаких преимуществ в программу. Вместо этого он затрудняет понимание кода позже.
Так же, как мы используем код JDBC, есть много попыток ... поймать. Действительно полезный код включен в попытку ... поймать. Затрудняя понимание этого метода
Проверено исключение приводит к постоянному инкапсулированию исключения в другое исключение, а затем брошено
public void methoda () throws exceptiona {… .. .. throw new ExceptionA ();} public void methodb () throws exceptionB {try {methoda ();…} catch (exceptiona ex) {throw nevaleb (ex);}} public void methodc () throws elyinc {try {methodb ();} catch excementb excempt) Мы видим, что исключение инкапсулируется и повторно перетаривается слой по слою.
Проверено исключение вызывает повторение метода интерфейса
Метод на интерфейсе использовался несколькими классами. Когда к этому методу добавляется дополнительное проверяемое исключение, все коды, вызывающие этот метод, необходимо изменить.
Можно видеть, что вышеуказанные проблемы вынуждены ловить и обрабатывать, потому что вызывающий абонент не может правильно обрабатывать проверенное исключение, и вынужден инкапсулировать, а затем пересмотреть. Это очень неудобно и не приносит никаких преимуществ. В этом случае обычно используются неконтролируемые исключения.
Проверенное исключение - еще не все. Проверенное исключение намного проще в использовании, чем возвратное значение ошибки традиционного программирования. Гораздо лучше убедиться, что исключения обрабатываются правильно через компилятор, чем судить по возвратной стоимости.
Если исключение является фатальным, оно невозможно. Или вызывающий абонент улавливает его без каких -либо выгод, используйте неконтролируемое исключение.
Если исключение может быть восстановлено и может быть правильно обработано вызывающим абонент, используйте проверенное исключение.
При использовании неконтролируемого исключения неопределенное исключение, которое может добавить метод, должно быть подробно описано в объявлении метода. Звонящий решает, поймать ли неконтролируемое исключение
Когда использовать проверенные исключения и когда использовать неконтролируемые исключения? Там нет абсолютного стандарта. Но я могу дать несколько предложений
Когда все вызывающие абоненты должны обрабатывать это исключение, вызывающему абоненту может быть разрешено повторно операции; или исключение эквивалентно второму возвращению значения метода. Используйте проверенное исключение.
Это исключение может быть обработано только несколькими более продвинутыми абонентами, и обычные абоненты не могут справиться с ним правильно. Используйте неконтролируемое исключение. Абоненты, которые имеют возможность обрабатывать, могут выполнять расширенную обработку, но, как правило, вызывающие абоненты вообще не справляются с этим.
Это исключение является очень серьезной ошибкой, такой как ошибки подключения к базе данных, неудача файлов открыть и т. Д. Или эти исключения связаны с внешней средой. Невозможно решить проблему повторения. Используйте неконтролируемое исключение. Потому что, как только это исключение происходит, вызывающий абонент не может справиться с этим вообще.
Если это не уверено, используйте неконтролируемое исключение. И подробно опишите исключение, которое может быть брошено, чтобы позвонить вызывающему решению, справиться с этим.
3. Разработка нового класса исключений
При разработке нового класса исключений сначала проверьте, действительно ли этот класс исключений действительно нужен. Вообще говоря, постарайтесь не разрабатывать новые классы исключений, но постарайтесь использовать классы исключений, которые уже существуют в Java.
нравиться
AllogalargumentException, UnsupportedOperationException
Будь то новое исключение, исключение из Chekced или неконтролируемое исключение. Мы все должны рассмотреть проблему гнездования исключений.
public void methoda () выбрасывает exceptiona {… .. trow new Exceptiona ();} Метод Декларация выбрасывает исключение.
public void methodb () бросает exceptionb
Декларация MethodB будет выбросить ExceptionB. Когда Methoda вызывается в методе MethodB, исключение не может быть обработано, поэтому исключение должно продолжать выбросить. Одним из способов является сделать декларацию MethodB, бросая исключение. Но это изменило подпись метода метода. После изменения все методы, которые метод вызова, должны быть изменены.
Другим способом является инкапсулировать исключение в ExceptionB, а затем бросить его. Если мы не инкапсулируем исключение в ExceptionB, мы потеряем информацию об исключении корня, сделав невозможным отслеживать исходный источник исключения.
public void methodb () throws exceptionB {try {methoda (); ...} catch (exceptiona ex) {throw nevaleb (ex);}} Как и в приведенном выше коде, ExceptionB гнездет исключение. Мы будем называть исключением «вызвали исключение» на данный момент, потому что ExceptionA вызывает ExceptionB. Это предотвратит потерянную информацию исключения.
Поэтому, когда мы определяем новый класс исключений, мы должны предоставить такой конструктор, который может содержать вложенные исключения. И есть частный участник, чтобы сохранить это «причинить исключение».
public class ExceptionB Exceptends Exception {private Throwable Case; public exceptionB (String msg, throwable ex) {super (msg); this.cause = ex;} public exceptionB (String msg) {super (msg);} public exceptionb (throwable ex) {this.cause = ex;}} Конечно, когда мы называем метод PrintStackTrace, нам нужно распечатать всю информацию о «вызванном исключении» одновременно. Таким образом, нам нужно переопределить метод PrintStackTrace, чтобы отобразить все трассировки стека исключений. Включает в себя следов стека вложенных исключений.
public void printStackTrace (PrintStrean PS) {if (canece == null) {super.printstacktrace (ps);} else {ps.println (this); canes.printstacktrace (ps);}} Полная поддержка вложенного проверенного исходного кода класса исключений заключается в следующем. Давайте назовем это indestException здесь на данный момент
public indestException расширяет Exception {Private Throwable Case; public nestEdException (String msg) {super (msg);} public indestException (String msg, throwable ex) {super (msg); this.caue = ex;} public throwable getCaue () {return (this.cause = null? this.cause); Super.getMessage (); Throwable case = getCause (); if (canem! null) {super.printstacktrace (ps);} else {ps.println (this); getCause (). null) {super.printstacktrace (pw);} else {pw.println (this); getCause ().Кроме того, вам необходимо разработать неконтролируемый класс исключений, как указано выше. Это просто нужно унаследовать Runtimeexception.
4. Как записать исключения
В качестве большой системы приложений файлы журнала необходимы для записи работы системы для облегчения отслеживания и записи работы системы. Исключения, которые происходят в системе, естественно, необходимо записать в системе журнала.
public String getPassword (String userId) Throws nosuchUserexception {userInfo user = userDao.QueryUserById (userId); if (user == null) {logger.info («Информация пользователя не может быть найдена, userId ="+userId); Till New Nosuchuserexcept user.getPassword ();}} public void sendUserPassword (String userId) Throws Exception {userInfo user = null; try {user = getPassword (userId); //… ..sendmail (); //} catch (nosuchuserexception ex) (Logger.Error («Информация пользователя не может быть найдена:» userid+z); Мы заметили, что ошибка была зарегистрирована дважды. При происхождении ошибки мы записываем только на уровне информации. В методе SendUserPassword мы также записываем всю информацию об исключении.
Автор видел много проектов, которые записывают исключения таким образом, независимо от 3721, и все исключение будет записано только при столкновении с исключением. Если исключение непрерывно инкапсулируется и бросается несколько раз, оно будет записано несколько раз. Итак, где должно быть записано исключение?
Исключение должно быть записано в начальном месте!
Если вам нужно поймать исключение, которое не может быть обработано правильно, просто инкапсулируйте его в другое исключение и бросьте его. Нет необходимости снова записывать записанное исключение.
Если исключение поймано, это исключение может быть обработано. Никаких исключений не должно быть записано
Публичная дата GetDate (String Str) {дата ApplyDate = null; SimpleDateFormat format = new SimpleDateFormat ("mm/dd/yyyy"); try {ApplyDate = format.parse (ApplyDatestr Когда не зарегистрировано не записанное исключение или исключение внешней системы, подробности исключения должны быть записаны.
try {… string sql = ”select * from userInfo»; оператор s = con.createStatement ();… Catch (sqlexception sqlex) {logger.error ("Ошибка выполнения SQL"+SQL+SQLEX);} Где записать информацию об исключении и как записать информацию об исключении может быть вопросом мнения. Некоторые системы даже позволяют исключениям класса исключений. Когда создается новый объект исключения, информация об исключении автоматически записывается.
Public Class BusinessException Excement exection {private void logtrace () {StringBuffer buffer = new StringBuffer (); Buffer.Append («Бизнес -ошибка в классе:»); buffer.append (getClassname ()); Buffer.Append («Метод:»); Buffer.Append (getMethodName ()); ");; buffer.append (this.getMessage ()); logger.error (buffer.tostring ());} public businessexception (String s) {super (s); Race ();} Это кажется очень замечательным, но это неизбежно приведет к исключению, записанного неоднократно. В то же время он нарушает «принцип распространения обязанностей классов» и является плохим дизайном. Запись исключения не принадлежит к поведению класса исключений, и исключения записи должны быть сделаны специальной системой журнала. И ненормальная информация о записи постоянно меняется. Мы записываем исключения, которые должны предоставлять более богатую информацию. Это помогает нам найти основную причину проблемы на основе информации об исключении для решения проблемы.
Хотя мы многое обсудили в записи исключения, слишком много акцента на них делает разработчиков более запутанными. Один хороший способ - обеспечить структуру обработки исключений для системы. Структура решает, следует ли записывать исключения и как записывать исключения. Обычные программисты не должны решать. Но это полезно что -то знать.
5. Обработка исключений в проекте J2EE
В настоящее время проекты J2EE, как правило, логически разделены на несколько слоев. Классические из них делятся на три уровня: уровень презентации, бизнес -уровень и интеграционный уровень (включая доступ к базе данных и доступ к внешнему систему).
Проект J2EE имеет свою сложность, и необходимо уделять особое внимание нескольким вопросам при обработке исключений в проекте J2EE.
При использовании распределенных приложений мы сталкиваемся с многими проверенными исключениями. Все вызовы RMI (включая удаленные интерфейсные вызовы EJB) будут бросать java.rmi.remoteexception; В то же время, RemoteException является проверенным исключением. Когда мы делаем удаленные звонки в бизнес -системе, нам всем нужно написать большое количество кода для обработки этих проверенных исключений. После того, как произойдет remoteexception, эти проверенные исключения очень серьезны для системы, и почти нет возможности повторения. То есть, когда появляются эти ужасные проверенные исключения RemoteException, нам не нужно повторно повторно, но мы должны написать много попыток ... поймать код, чтобы справиться с ним. Как правило, мы делаем вызовы RMI на нижнем уровне. Пока есть вызов RMI, все интерфейсы верхнего уровня потребуют отбрасывания RemoteException. Потому что то, как мы справляемся с RemoteException, - это продолжать бросить его. Это разрушит наш бизнес -интерфейс. Remoteexception эти исключения на уровне системы J2EE серьезно влияют на наши бизнес-интерфейсы. Цель нашего наслоения систем состоит в том, чтобы уменьшить зависимость между системами, и технологические изменения в каждом уровне не будут влиять на другие слои.
// Открытый класс useroaImplimplis useroa {public userInfo getUserinfo (string userid) throws remoteexception {//… remote method call.//……… Точно так же доступ к JDBC вызовет проверенное исключение SQLEXCEPTION.
Чтобы избежать глубокого вторжения проверенных исключений на уровне системного уровня в бизнес-систему, мы можем определить собственное исключение бизнес-системы для бизнес-метода. Для очень серьезных исключений, таких как SQLEXCEPTION и RemoteException, мы можем определить новое неконтролируемое исключение, а затем инкапсулировать SQLEXCEPTION и RemoteException в неконтролируемое исключение и бросить его.
Если это исключение на уровне системы должно быть передано предыдущему абоненту для обработки, вы можете вновь определить проверенное бизнес-исключение, а затем закрепить исключение на уровне системы в исключение на уровне бизнеса, а затем бросить его.
Как правило, нам необходимо определить неконтролируемое исключение, чтобы все методы интерфейса интеграционного уровня объявили, чтобы сделать это неверное исключение.
public DataCcessExceptionExextends runtimeException {...} public interface userdao {public String getPassword (String userId) Throws DataCcessException;} public class userDaoImplimples userDao {public String getPassword (String userId) THROWS THROWS DATACCESSEXCEPT '+userId+"'"; try {… // jdbc вызовы S.ExecUtequery (sql);…} catch (sqlexception ex) {throw new dataaccessexception ("Query базы данных не удалось"+sql, ex);}}}}}}}}}}}}}}}}}}}}}}}} Определите проверенное бизнес -исключение, чтобы все методы интерфейса бизнес -уровня объявили, чтобы выбросить проверенное исключение.
Общедоступный класс BusinessExceptionExtends Exception {… ..} Public Interface userManager {public userInfo copyUserInfo (пользователь userInfo) Throws BusinessException {userInfo newuser = null; try {newuser = (userInfo) user.clone ();} Catch (ClonenotSupportedExexceptexception Exception ex) {Throw New Businessexcepte (). Поддерживается: "+userInfo.class.getName (), ex);}}} Уровень представления J2EE должен быть очень тонким уровнем, а его основными функциями являются: получить запросы страниц, собрать параметры страницы в объекты POJO, вызовать соответствующие бизнес -методы, а затем пересылать страницу, представить соответствующие бизнес -данные на страницу. Уровень презентации должен обратить внимание на одну проблему. Уровень презентации должен проверить легитимность данных, например, некоторые входные поля не могут быть пустыми, проверка длины символов и т. Д.
Все параметры, передаваемые из J2EE на фон со страницы, являются типом символа. Если вам требуется ввод численных параметров или типа даты, значение символа должно быть преобразовано в соответствующее числовое значение или дату.
Если параметры проверки кода уровня представления не являются действительными, его следует возвращать на исходную страницу, позволяя пользователю повторно ввести данные и предпринимать соответствующую информацию об ошибках.
Обычно параметр, выходящий со страницы, преобразуется в числовое значение, мы можем увидеть такой код
ModeAndView handleRequest (httpservletRequest, httpservletresponse response), выбросы исключения {string agest = request.getParameter ("age"); int age = integer.parse (agestr); ……… string hight hightrystr = request.getParameter ("день рождения"); SimpleDateFormat format = new SimpleDateFormat ("Mm/dd/yyyy"); Date Birthday = format.parse (день рождения);} Приведенный выше код следует часто видеть, но когда пользователь вводит символ, который не может быть преобразован в целое число со страницы или неверное значение даты.
Метод integer.parse () брошен неконтролируемым исключением с номером форматхплексия. Тем не менее, это исключение определенно не является фатальным исключением. Как правило, когда значение, введенное пользователем в поле ввода страницы, является незаконным, мы должны предложить пользователю повторно въехать. Но как только не будет брошено неконтролируемое исключение, нет шансов попробовать еще раз. Подобные коды вызывают большое количество информации об исключении на странице. Сделайте нашу систему очень хрупкой.
Аналогичным образом, метод SimpleDateFormat.parse () также вызовет неконтролируемое исключение из ParseException.
В этом случае мы должны поймать эти неконтролируемые исключения и побудить пользователя повторно въехать.
ModeAndView handleRequest (httpservlectrequest, httpservletresponse response) throws Exception {string agest = request.getParameter ("age"); String birthdaystr = request.getParameter ("день рождения"); int age = 0; ex){error.reject("age","is not a legal integer value");}………try{SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");birthDay = format.parse(birthDayStr);}catch(ParseException ex){error.reject("birthDay","is not a legal date, please enter the date in 'MM/dd/yyy' формат ");}} На уровне презентации вы должны выяснить, будет ли вызовный метод выбросить неконтролируемое исключение, при каких обстоятельствах эти исключения будут выброшены, и сделать правильную обработку.
В презентационном уровне нет необходимости улавливать исключения в целом. Если исключение, добавленное вызывающим бизнес -методом, эквивалентно второму возвращению, в данном случае необходимо захватить.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.