JavaRush /בלוג Java /Random-HE /יצירת יישום אינטרנט פשוט באמצעות servlets ו-jsp (חלק 2)
fatfaggy
רָמָה
Киев

יצירת יישום אינטרנט פשוט באמצעות servlets ו-jsp (חלק 2)

פורסם בקבוצה
אני ממשיך לתאר את התהליך של יצירת יישום אינטרנט באמצעות servlets, jsp, Maven ו- Tomcat. תחילת המאמר , במידת הצורך.
אנחנו יוצרים ישויות.
בואו ניצור מחלקה User בחבילת entities, בה ניצור שני משתני מחרוזת פרטיים שם וסיסמה. בואו ניצור בנאים (ברירת מחדל וכזה שיקבל את שני הערכים), getters/seters, נעקוף את המתודה toString() למקרה הצורך, וכן את המתודות equals() ו-hashCode() . public class User { private String name; private String password; public User() { } public User(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (name != null ? !name.equals(user.name) : user.name != null) return false; return password != null ? password.equals(user.password) : user.password == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (password != null ? password.hashCode() : 0); return result; } } כעת נוכל להתחיל ליצור רשימת משתמשים, לאן נוסיף את המשתמשים שלנו, ומהיכן ניקח אותם לתצוגה. אבל יש בעיה. אנחנו לא יוצרים את אובייקטי ה-servlet שלנו; Tomcat יוצר אותם עבורנו. גם השיטות שאנו עוקפים בהן כבר מוגדרות עבורנו ואין באפשרותנו להוסיף פרמטר. כיצד אם כן נוכל ליצור רשימה משותפת שתהיה גלויה בשני הסרבלטים שלנו? אם פשוט ניצור אובייקט רשימה משלנו בכל סרבלט, יתברר שנוסיף משתמשים לרשימה אחת, אבל הצגת רשימת משתמשים המשתמשים בשרת ListServlet תהיה שונה לחלוטין. מסתבר שאנחנו צריכים אובייקט שיהיה משותף לשני הסרבלטים. באופן כללי, אנו זקוקים לאובייקט שיהיה משותף לכל הכיתות בתוכנית שלנו; האובייקט היחיד עבור התוכנית כולה. אני מקווה ששמעת משהו על דפוסי עיצוב. ואולי עבור חלק זה הצורך האמיתי הראשון להשתמש בתבנית Singleton בתוכנית שלהם. אתה יכול להיות יצירתי ולהכין איזה סינגלטון מגניב, עם בדיקות כפולות וסנכרון (כן, יש לנו אפליקציה מרובה הליכי, מכיוון ש-Tomcat מריץ servlets בשרשורים שונים), אבל אני אשתמש באפשרות עם אתחול מוקדם, מכיוון שבמקרה זה הוא מתאים למדי.
יצירת מודל.
לאחר מכן ניצור מחלקה (וניישם בה את תבנית הסינגלטון) בחבילת המודל, וגם נקרא לה בצורה די צבעונית Model. בוא ניצור בו אובייקט רשימת משתמשים פרטית, ונעשה בו שתי שיטות: האחת כדי שתוכל להוסיף משתמש, והשנייה - תנו לו פשוט להחזיר רשימה של מחרוזות (שמות משתמשים). מכיוון שאובייקט המשתמש שלנו מורכב משם וסיסמה, לא נרצה "לחשוף" סיסמאות משתמש, לכן נחזיר רק רשימה של שמותיהם. public class Model { private static Model instance = new Model(); private List model; public static Model getInstance() { return instance; } private Model() { model = new ArrayList<>(); } public void add(User user) { model.add(user); } public List list() { return model.stream() .map(User::getName) .collect(Collectors.toList()); } }
קצת על mvc.
מכיוון ששמעתם על סינגלטון, זה אומר שכנראה שמעתם על דפוס עיצובי אחר - MVC (מודל-view-controller, או ברוסית model-view-controller, או ממש כמו באנגלית model-view-controller). המהות שלו היא להפריד בין ההיגיון העסקי למצגת. כלומר, הפרידו את הקוד שקובע מה לעשות מהקוד שקובע איך להציג . התצוגה (תצוגה או רק תצוגות) אחראית לצורה שבה חלק מהנתונים מוצגים. במקרה שלנו, הצפיות הן דפי ה-JSP שלנו. בגלל זה שמתי אותם בתיקייה שנקראת תצוגות. המודל הוא הנתונים בפועל איתם עובדת התוכנית. במקרה שלנו, מדובר במשתמשים (רשימת משתמשים). ובכן, בקרים הם החוליה המקשרת ביניהם. הם לוקחים נתונים מהמודל ומעבירים אותם לתצוגות, או שהם מקבלים כמה נתונים מטומקט, מעבדים אותם ומעבירים אותם למודל. היגיון עסקי (כלומר, מה לעשות ) צריך להיות מתואר בהם, ולא במודל או בתצוגה. אז כל אחד עושה את שלו:
  • הדגם מאחסן נתונים
  • תצוגות משרטטות ייצוג יפה של נתונים
  • בקרים מעבדים נתונים
זה מאפשר לכולם להיות די פשוטים וניתנים לתחזוקה. ולא מזבלה מפלצתית של כל הקוד במחלקה אחת. MVC לא רק מתאים לתכנות אינטרנט, אבל הוא עדיין נפוץ מאוד (אם לא תמיד) בתחום זה. במקרה שלנו, servlets ישמשו כבקרים. כן, זה תיאור מאוד שטחי ואפילו גס של הדפוס הזה, אבל המאמר הזה לא עוסק בתבניות עיצוב, אלא על איך לעשות יישום אינטרנט פשוט :) מי שרוצה לדעת יותר - גוגל יודע הכל ! :) בואו נחזור לדעות שלנו.
צור טופס להוספת משתמש.
בואו נוסיף טופס לקובץ add.jsp, המורכב משתי כניסות טקסט (אחד רגיל, השני סוג סיסמה) וכפתור לשליחת נתונים לשרת. כאן יש לטופס מאפיין מתודה עם הערך פוסט. המשמעות היא שהנתונים מטופס זה יישלחו לשרת בצורה של בקשת POST. תכונת הפעולה לא צוינה, מה שאומר שהבקשה הזו תעבור לאותה כתובת שבה הלכנו לדף זה (/add). לפיכך, הסרבלט שלנו, המחובר לכתובת זו, עם קבלת בקשת GET, מחזיר את ה-jsp הזה עם הטופס להוספת משתמשים, ואם הוא מקבל בקשת POST, אז הטופס הזה שלח את הנתונים שלו לשם (שאנו נאחזר מ- את אובייקט הבקשה בשיטת doPost() , עבדו אותו והעבירו אותו למודל לשמירה). ראוי לציין שלקלטים יש כאן פרמטר שם (עבור שדה עם שם יש לו את שם הערך, ולשדה עם סיסמה יש את הערך pass). זו נקודה די חשובה. מכיוון שכדי לקבל את הנתונים הללו (שם וסיסמה שיוזנו) מהבקשה (כבר בתוך ה-servlet), נשתמש בדיוק בשם וב-pass אלו. אבל עוד על כך בהמשך. הכפתור לשליחת הנתונים עצמו נעשה שוב בצורת כפתור, ולא קלט, כמקובל בדרך כלל. אני לא יודע עד כמה האפשרות הזו אוניברסלית, אבל היא עובדת בשבילי בכרום :)
עיבוד בקשת POST עם servlet.
בואו נחזור ל-servlet AddServlet. אנחנו כבר יודעים שכדי שה-servlet שלנו יוכל "לתפוס" בקשות GET, דרפנו את שיטת doGet() מהמחלקה HttpServlet. כדי ללמד את ה-servlet שלנו לתפוס גם בקשות POST, אנו גם עוקפים את שיטת doPost() . הוא מקבל אובייקטי בקשה ותגובה דומים מ-Tomcat, שאיתם נעבוד. ראשית, בואו נחלץ מהבקשה את השם ונעביר פרמטרים שהטופס שלח (אם כיניתם אותם אחרת בטופס, אז אלו השמות שאתם כותבים). לאחר מכן ניצור את אובייקט המשתמש שלנו באמצעות הנתונים שהתקבלו. לאחר מכן נקבל את אובייקט המודל ונוסיף את המשתמש שנוצר למודל. @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); }
העברת נתונים לתצוגה.
כעת נעבור לשרת ListServlet. כבר הטמענו את שיטת doGet(), אשר פשוט מעבירה את השליטה לתצוגת list.jsp. אם עדיין אין לך את זה, עשה זאת באנלוגיה עם אותה שיטה מהשרת AddServlet. עכשיו יהיה נחמד לקבל רשימה של שמות משתמש מהדגם ולהעביר אותם לתצוגה, שיקבל אותם שם ויציג אותם יפה. לשם כך, נשתמש שוב באובייקט הבקשה שקיבלנו מ-Tomcat. אנו יכולים להוסיף לאובייקט הזה תכונה, לתת לו שם כלשהו, ​​ולמעשה, לאובייקט עצמו שנרצה להעביר לתצוגה. בשל העובדה שבעת העברת תהליך הביצוע מ-servlet ל-view, אנו מעבירים לשם את אותם אובייקטי בקשה ותגובה שהסרבל עצמו קיבל, ואז על ידי הוספת רשימת השמות שלנו לאובייקט הבקשה, נוכל לאחר מכן מתוך בקשה זו אובייקט בתצוגה צור את רשימת שמות המשתמש שלנו וקבל. סיימנו עם המחלקה ListServlet, אז הנה הקוד לכל המחלקה. package app.servlets; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; public class ListServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Model model = Model.getInstance(); List names = model.list(); req.setAttribute("userNames", names); RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp"); requestDispatcher.forward(req, resp); } }
ביצוע קוד java בקבצי jsp.
כעת נעבור לקובץ list.jsp. קובץ זה יבוצע רק כאשר ListServlet יעבור כאן את תהליך הביצוע. בנוסף, באותו servlet כבר הכנו רשימה של שמות משתמשים מהמודל והעברנו אותה כאן באובייקט הבקשה. בהינתן רשימה של שמות, נוכל להריץ דרכו לולאת for ולהדפיס כל שם. כפי שכבר אמרתי, קבצי jsp יכולים להפעיל קוד java (באופן עקרוני, זה מה שמבדיל אותם מדפי HTML סטטיים). כדי לבצע קוד כלשהו, ​​מספיק למקם קונסטרוקציה במקום שאנו צריכים, <% // java code %> בתוך קונסטרוקציה כזו אנו מקבלים גישה למספר משתנים: request - request object שלנו, אותו העברנו מהסרבלט, שם הוא נקרא בפשטות req response - אובייקט התגובה, ב-servlet נקרא resp out - אובייקט מסוג JspWriter (הועבר בירושה מה-Writer הרגיל), בעזרתו נוכל "לכתוב" משהו ישירות לעמוד ה-html עצמו. Out.println("Hello world!") דומה מאוד ל-System.out.println("Hello world!"), אבל אל תבלבלו ביניהם! out.println() "כותב" לעמוד ה-html, ו-System.out.println - לפלט המערכת. אם תקרא למתודה System.out.println() בתוך הקטע עם קוד jsp, תראה את התוצאות בקונסולת Tomcat, ולא בדף, כפי שאולי תרצה :) אתה יכול לחפש אובייקטים זמינים אחרים בתוך jsp כאן . באמצעות אובייקט request נוכל לקבל את רשימת השמות שהועברה מה-servlet (צירפנו את התכונה המתאימה לאובייקט זה), ובאמצעות אובייקט ה-out נוכל להציג את השמות הללו. בוא נעשה זאת לעת עתה פשוט בצורת רשימת HTML: אם אנחנו רוצים להציג את הרשימה רק כשיש משתמשים, ובדרך אחרת להציג אזהרה שאין עדיין משתמשים, נוכל לשכתב קצת את הסעיף הזה: עכשיו כשאנחנו לדעת להעביר נתונים מ-servlets לתצוגות - נוכל לשפר מעט את AddServlet שלנו כך שתוצג הודעה על הוספה מוצלחת של משתמש. לשם כך, בשיטת doPost() לאחר הוספת משתמש חדש למודל, נוכל להוסיף את שם המשתמש הזה לתכונות של אובייקט req ולהעביר את השליטה בחזרה לתצוגה add.jsp. ובו כבר עושים קטע עם קוד ג'אווה, שבו אתה יכול לבדוק אם תכונה כזו נמצאת בבקשה, ואם כן, אז להציג הודעה שהמשתמש נוסף בהצלחה. לאחר השינויים האלה, הקוד המלא של ה-AddServlet servlet ייראה בערך כך: כאן, בסוף שיטת doPost() אנו מגדירים תכונה עם שם המשתמש שנוסף למודל, ואז קוראים ל-doGet( ) שיטת, שאליה אנו מעבירים את הבקשה והתגובה הנוכחיים. ומתודה doGet() כבר מעבירה את השליטה לתצוגה, שם היא שולחת אובייקט בקשה עם שם המשתמש שנוסף מצורף כתכונה. נותר לתקן את add.jsp עצמו כך שיציג הודעה כזו אם קיימת תכונה כזו. סופי add.jsp
    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { for (String s : names) { out.println("
  • " + s + "
  • "); } } %>
<% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    package app.servlets; import app.entities.User; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AddServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp"); requestDispatcher.forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); req.setAttribute("userName", name); doGet(req, resp); } } <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("

    User '" + request.getAttribute("userName") + "' added!

    "); } %>

    Add user

    גוף העמוד מורכב מ-div עם כותרת שלאחריו יש מיכל div לתוכן, בו הוא בודק האם קיימת תכונה עם שם המשתמש, לאחר מכן div עם טופס להוספת משתמשים, ובסוף. כותרת תחתונה עם כפתור כדי לחזור לעמוד הראשי. זה אולי נראה כאילו יש יותר מדי divs, אבל נשתמש בהם מאוחר יותר כשנוסיף סגנונות :) ובכן, הגרסה הסופית היא list.jsp. לפיכך, יש לנו אפליקציית אינטרנט שפועלת במלואה שיכולה לאחסן ולהוסיף משתמשים, גם כן כמו להציג רשימה של שמותיהם. כל מה שנשאר זה לייפות אותו... :) <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    הוספת סגנונות. אנו משתמשים במסגרת W3.CSS.
    כרגע האפליקציה שלנו עובדת אבל לגמרי מטורפת :) אנחנו צריכים להוסיף רקע, צבעים לטקסט ולכפתורים, לסגנן רשימות, לעשות יישור, להוסיף כניסות, בכלל הרבה דברים. אם אתה כותב סגנונות באופן ידני, זה יכול לקחת הרבה זמן ועצבים. לכן, אני מציע להשתמש במסגרת CSS W3.CSS . יש לו כבר שיעורים מוכנים עם סגנונות; כל מה שנותר הוא למקם במקומות הנכונים את שיעורי ה-CSS שאנחנו רוצים ליישם במקומות האלה. כדי להוסיף אותם לדפים שלנו, ראשית עלינו לכלול קובץ עם סגנונות. ניתן לעשות זאת בשתי דרכים: 1. עברו על הדפים שלנו ובמדור ראש הכנסו קישור ישיר לקובץ עם סגנונות אפשרות זו מתאימה אם יש לכם חיבור קבוע לאינטרנט. לאחר מכן, כאשר אתה פותח את הדפים שלך בשרת מקומי, הסגנונות יימשכו מהאינטרנט. 2. אם אתה רוצה לקבל את כל הסגנונות באופן מקומי ולא להיות תלוי בחיבור לאינטרנט, אתה יכול פשוט להוריד את הקובץ עם הסגנונות ולמקם אותו איפשהו בתוך תיקיית האינטרנט (לדוגמה web/styles/w3.css), ואז עברו על כל הדפים שלנו (index.html, add.jsp, list.jsp) והכנסו קישור לקובץ הזה עם סגנונות בתוך ה-head. לאחר מכן, פשוט עברו על התגים ותייגו אותם עם הסגנונות שאתם אוהבים . אני לא אתעכב על זה בפירוט, אבל מיד אתן את הגרסאות המוכנות שלי לשלושת הקבצים שלי עם שיעורי סגנון מסודרים. index.html add.jsp list.jsp זה הכל :) אם עדיין יש לך שאלות או הערות, או להיפך, משהו לא מסתדר - השאר תגובה. ובכן, אני אצרף כמה צילומי מסך של מה שיצא מכל זה. ולבסוף. אם אתה רוצה להתאמן עם הפרויקט הזה, אתה יכול לנסות: Super app!

    Super app!

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("
    \n" + " ×\n" + "
    User '" + request.getAttribute("userName") + "' added!
    \n" + "
    "); } %>

    Add user

    <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users list

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println("
      "); for (String s : names) { out.println("
    • " + s + "
    • "); } out.println("
    "); } else out.println("
    \n" + " ×\n" + "
    There are no users yet!
    \n" + "
    "); %>
    דף הבית של האפליקציה הוסף חלון משתמש רשימה של משתמשים
    • צור servlet ו-jsp כדי למחוק משתמש ועוד כמה כדי לשנות/לערוך משתמש קיים. תקבל יישום אינטרנט אמיתי CrUD :) על servlets))
    • החלף רשימה (רשימה ) לעבוד עם מסד הנתונים כדי שמשתמשים שנוספו לא ייעלמו לאחר הפעלה מחדש של השרת :)
    בהצלחה!
    הערות
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION