استخدام المتغيرات الثابتة في Servlets Java (على سبيل المثال في Appengine)

StackOverflow https://stackoverflow.com/questions/1849491

سؤال

لدي تطبيق حيث يحتوي Servlet على طريقة تسمى Update(ReqIn, ReqOut). وبعد أنا أسميها من doGet & doPost وتمرير متغيرات الطلب والاستجابة، ثم ما يصل إلى Update(...) لملء المتغيرات الثابتة التالية:

...
public class Server extends HttpServlet {

    public static HttpServletRequest In = null;
    public static HttpServletResponse Out = null;

    public static boolean isDebug = true;
    public static boolean isPost = false;

    public static String URL = "";
    public static String IP = "0.0.0.0";
    public static Cookie[] Cookies = null;

    public static UserClass User = null;
    public static boolean isLoggedIn = false;


    ...
}

تجريد أساسا أكثر الأشياء المستخدمة وتحديثها في كل طلب. هذا يسمح لي أيضا بالوصول إلى عنوان IP وبيانات المستخدم الحالية من أي مكان في الموقع، من خلال WRETTITE فقط Server.User.getUsername(); يعزز إنشاء مثيل فئة جديدة في كل مرة يتم فيها تحميل صفحة واستخدام رمز الوصول لفترة أطول بكثير: Server.getUser().getUsername();

الآن السؤال هو: عندما تكون في بيئة مستخدم متعددة (Jetty On Appengine)، هل يمكن أن يقدم هذا أي مشاكل؟ على سبيل المثال، فإن بعض مشكلات الخيوط / السباقات تجعل المستخدم يرى عنوان IP غير صحيح أو في حالة متطرفة يتم تسجيله فجأة كمستخدم مختلف؟

أو يجب علي إعادة كتابة التعليمات البرمجية وتغييرها Public UserClass User بدلا من Public static UserClass User, ، إلخ؟

هل كانت مفيدة؟

المحلول

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

1:public class Server extends HttpServlet {
2:  public static int requestNo = 0;
3:  public void doGet(HttpServletRequest req, HttpServletResponse resp)
4:  {
5:     requestNo++;
6:     resp.getWriter().println(requestNo);
7:  }
8:}

الآن تخيل الجدول الزمني التالي:

الطلب 1 يأتي في، ويعالج، بما في ذلك الخط 5.
طلب 2 يأتي في وعمليات تماما.
طلب 1 يستمر المعالجة.

سيحصل كلا الطلبين على النص "2"، بدلا من الحصول على "1" ويحصل على "2". هذا مثال بسيط للدولة التي تدور عليها.

الآن، للإجابة على الجزء الثاني من سؤالك؛

أو يجب إعادة كتابة التعليمات البرمجية وتغييرها إلى مستخدم UserClass العام بدلا من مستخدم UserClass Static العام، إلخ؟

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

هذا يترك ثلاثة خيارات حقيقية فقط:

  1. يشق كل شيء في httpsession. المشكلة هنا هي أن هذه خريطة، لذلك تفقد السلامة من النوع، ومن الصعب معرفة مكان استخدام الأشياء.
  2. قم بإنشاء فئة حامل لعقد كل حالتك ونقلها في كل مكان. هذا أفضل قليلا، لأنك على الأقل لا تفقد سلامة النوع، لكنك لا تزال لا تملك رؤية كاملة أيضا.
  3. تمرير العناصر الفردية المطلوبة حولها.

نصائح أخرى

نعم، هذه فكرة سيئة للغاية!

ماذا كنت توقع أن يحدث إذا حصلت على طلبتين في نفس الوقت؟ يمكن أن يحمل كل متغير ثابت فقط قيمة واحدة، لذلك ستفقد البيانات.

أنت استطاع استعمال ThreadLocal بحيث كان لكل مؤشر ترابط فقط الوصول إلى الطلب / المستخدم الحالي / إلخ الذي كان يتعامل معه - ولكن هذا لا يزال فكرة سيئة بشكل أساسي. إنه هش، ويخفي حقيقة أن الطبقات السفلى تحتاج إلى المعلومات. اجتياز الحالة وصولا إلى التعليمات البرمجية التي تحتاجها بدلا من ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top