مثال تعليمي لاستثناء ومعالجة أخطاء السيرفلت

اليوم سنتناول استثناء Servlet ومعالجة الأخطاء. في وقت سابق قمت بكتابة مقال حول معالجة الاستثناءات في لغة الجافا ولكن عندما يتعلق الأمر بتطبيق الويب ، نحتاج إلى أكثر من معالجة استثناء عادية في لغة الجافا.

استثناء Servlet

إذا لاحظت ، تقوم طرق doGet() و doPost() برمي javax.servlet.ServletException و IOException ، دعونا نرى ماذا يحدث عندما نرمي هذه الاستثناءات من تطبيقنا. سأكتب سيرفلت بسيط سيقوم برمي استثناء ServletException.

package com.journaldev.servlet.exception;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/MyExceptionServlet")
public class MyExceptionServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		throw new ServletException("GET method is not supported.");
	}

}

الآن عندما نستدعي هذا السيرفلت من خلال المتصفح بأسلوب GET ، نحصل على استجابة مثل الصورة أدناه. نظرًا لأن المتصفح يفهم فقط لغة HTML ، عندما يقوم تطبيقنا برمي استثناء ، يقوم حاوي سيرفلت بمعالجة الاستثناء وإنشاء استجابة HTML. هذا السياق خاص بحاوي السيرفلت. أنا استخدم تومكات وأحصل على صفحة خطأ بها. إذا كنت ستستخدم بعض الخوادم الأخرى مثل جبوس أو جلاسفيش ، قد تحصل على استجابة HTML مختلفة. المشكلة في هذه الاستجابة هي أنها لا تقدم أي قيمة للمستخدم. أيضًا ، فإنها تعرض فصول تطبيقنا وتفاصيل الخادم للمستخدم ، وهو أمر لا يلم بالمستخدم وليس جيدًا من وجهة نظر الأمان.

خطأ في السيرفلت

I am sure you must have seen 404 error when you are trying to hit a URL that doesn’t exists. Let’s see how our servlet container responds to 404 error. If we send request for an invalid URL, we get response HTML like below image. Again it’s a generic HTML generated by server on our application behalf and hold little to no value to the user.

استثناء السيرفلت ومعالجة الأخطاء

تقدم واجهة برمجة تطبيقات السيرفلت دعمًا للسيرفلتات المخصصة لمعالجة الاستثناءات والأخطاء يمكننا تكوينها في وصف النشر. الغرض الكامل من هذه السيرفلتات هو التعامل مع الاستثناء أو الخطأ الذي يتم إثارته بواسطة التطبيق وإرسال استجابة HTML مفيدة للمستخدم. يمكننا توفير رابط إلى صفحة البداية للتطبيق أو بعض التفاصيل لإعلام المستخدم بما حدث. لذا أولاً وقبل كل شيء ، نحتاج إلى إنشاء سيرفلت مخصص للتعامل مع الاستثناءات والأخطاء. يمكننا أن نمتلك العديد من سيرفلتات معالج الاستثناء والأخطاء للتطبيق ولكن لأسباب بسيطة سأقوم بإنشاء سيرفلت واحد واستخدامه لكل من الاستثناءات والأخطاء. AppExceptionHandler.java

package com.journaldev.servlet.exception;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/AppExceptionHandler")
public class AppExceptionHandler extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processError(request, response);
	}

	private void processError(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		// تحليل استثناء السيرفلت
		Throwable throwable = (Throwable) request
				.getAttribute("javax.servlet.error.exception");
		Integer statusCode = (Integer) request
				.getAttribute("javax.servlet.error.status_code");
		String servletName = (String) request
				.getAttribute("javax.servlet.error.servlet_name");
		if (servletName == null) {
			servletName = "Unknown";
		}
		String requestUri = (String) request
				.getAttribute("javax.servlet.error.request_uri");
		if (requestUri == null) {
			requestUri = "Unknown";
		}
		
		// تعيين نوع محتوى الاستجابة
	      response.setContentType("text/html");
	 
	      PrintWriter out = response.getWriter();
	      out.write("Exception/Error Details");
	      if(statusCode != 500){
	    	  out.write("

Error Details

"); out.write("Status Code:"+statusCode+"
"); out.write("Requested URI:"+requestUri); }else{ out.write("

Exception Details

"); out.write("
  • Servlet Name:"+servletName+"
  • "); out.write("
  • Exception Name:"+throwable.getClass().getName()+"
  • "); out.write("
  • Requested URI:"+requestUri+"
  • "); out.write("
  • Exception Message:"+throwable.getMessage()+"
  • "); out.write("
"); } out.write("

"); out.write("Home Page"); out.write(""); } }

لنرى كيف يمكننا تكوينه في وصف النشر، ثم سنفهم تنفيذه وكيف يعمل.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>ServletExceptionHandling</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <error-page>
  	<error-code>404</error-code>
  	<location>/AppExceptionHandler</location>
  </error-page>
  
  <error-page>
  <exception-type>javax.servlet.ServletException</exception-type>
  <location>/AppExceptionHandler</location>
  </error-page>
</web-app>

كما يمكنك رؤية، فمن السهل جدًا تحديد سجلات استثناء المضيف للتطبيق باستخدام عنصر error-page. يجب أن يحتوي كل عنصر error-page على عنصر error-code أو exception-type. نحدد سجل المعالجة استثناء في عنصر location. بناءً على التكوين أعلاه، إذا أثر التطبيق خطأ 404 أو ServletException، فسيتم التعامل معه بواسطة مضيف استثناء التطبيق. عند ظهور مثل هذا الاستثناء وسيناريو الخطأ، سيقوم حاوي الخدمة بالاستجابة للطريقة HTTP المقابلة لسجل معالج الاستثناء وتمرير كائن الطلب والاستجابة. لاحظ أنني قدمت تنفيذًا لكل من طريقتي doGet() وdoPost() بحيث يمكنها التعامل مع طلبات GET و POST واستخدام طريقة مشتركة لمعالجتها. قبل أن يقوم حاوي الخدمة باستدعاء السيرفلت للتعامل مع الاستثناء، يقوم بتعيين بعض السمات في الطلب للحصول على معلومات مفيدة حول الاستثناء، بعضها javax.servlet.error.exception، javax.servlet.error.status_code، javax.servlet.error.servlet_name و javax.servlet.error.request_uri. بالنسبة للاستثناء، يكون رمز الحالة دائمًا 500 الذي يتوافق مع “خطأ الخادم الداخلي”، بالنسبة لأنواع الأخطاء الأخرى نحصل على رموز أخطاء مختلفة مثل 404، 403 إلخ. باستخدام رمز الحالة، يقدم تنفيذنا أنواعًا مختلفة من الاستجابات HTML للمستخدم. كما يوفر رابطًا للصفحة الرئيسية للتطبيق. الآن عندما نصل إلى سيرفلتنا التي تثير ServletException، سنحصل على استجابة مثل الصورة أدناه. إذا حاولنا الوصول إلى عنوان URL غير صالح سيؤدي ذلك إلى استجابة 404، سنحصل على استجابة مثل الصورة أدناه. ألا يبدو جيدًا ويساعد المستخدم على فهم ما حدث بسهولة ويوفر لهم طريقة للانتقال إلى الموقع الصحيح. كما يتجنب إرسال معلومات حساسة للتطبيق إلى المستخدم. يجب علينا دائمًا وضع معالجي استثناءات في مكان لتطبيق الويب الخاص بنا. إذا كنت ترغب في التعامل مع استثناءات التشغيل وجميع الاستثناءات الأخرى في معالج استثناء واحد، يمكنك تحديد نوع الاستثناء كـ Throwable.

<error-page>
  <exception-type>java.lang.Throwable</exception-type>
  <location>/AppExceptionHandler</location>
</error-page>

إذا كانت هناك مداخل خطأ متعددة، فلنقل أن هناك واحدة لـ Throwable وواحدة لـ IOException وتطبيق يلقي FileNotFoundException، فسيتم التعامل معها بواسطة معالج الأخطاء لـ IOException. يمكنك أيضًا استخدام صفحة JSP كمعالج استثناء، فقط قم بتوفير موقع ملف jsp بدلاً من تعيين الخدمة. هذا كل شيء بخصوص معالجة استثناء السيرفلت في تطبيق الويب، أتمنى أن يعجبك.

تنزيل مشروع مثال على معالجة استثناء السيرفلت

تحقق من المقالات الأخرى في هذه السلسلة:

  1. تطبيق الويب في جافا
  2. دليل سيرفلت جافا
  3. إدارة الجلسة في جافا
  4. فلتر السيرفلت
  5. مستمعو السيرفلت
  6. ملفات تعريف الارتباط في سيرفلت
  7. مثال على تحميل وتنزيل الملفات في سيرفلت

Source:
https://www.digitalocean.com/community/tutorials/servlet-exception-and-error-handling-example-tutorial