Einführung
Technologien verwendet
Anforderungsanalyse
Datenmodell
Anwendungsarchitektur
Datenschicht
Controller
Action -Handler
Ansichten
Filter
Ergebnisse
Eine Java -basierte Webanwendung für Todo -Aktivitäten. Mit dieser Webanwendung kann man ihre Todos über einen modernen Webbrowser erstellen, lesen und aktualisieren. Die Anwendung implementiert auch AAA, was bedeutet, dass jeder Benutzer sein eigenes Konto hat und seine Todo -Liste usw. privat für ihn ist.
Dieses Dokument ist nicht für die Neulinge. Sie müssen über gute Kenntnisse der folgenden Technologien verfügen, um dieses Dokument und die damit verbundene Anwendung zu verstehen:
Java
Servlet, jsp
Apache Tomcat
Mysql
Html
Apache Netbeans IDE
Firefox
Dies ist völlig ein Back-End-Projekt. Daher werden Front-End-Technologien wie CSS, JavaScript, nicht verwendet. Ziel des Projekts ist es, effektiv zu lernen und zu zeigen, wie unterschiedliche Teile der Java -Servlet -API zusammenarbeiten.
Wir werden die Webanwendung entwickeln, beginnend mit Anforderungenanalyse. Dann werden wir zum Datenbankdesign übergehen. Daten sind für jede Webanwendung von zentraler Bedeutung. Fast alle Anwendungsfälle befassen sich mit Daten. Sobald das Datenmodell der Webanwendung fertig ist, werden wir die Architektur der Anwendung entwerfen. In dieser Phase werden wir sehen, wie sich unsere Anwendung mit verschiedenen HTTP -Aktionen verhält. Da alle von den Benutzern der Anwendung ausgeführten Aktionen über HTTP erfolgen. Wir werden an alle möglichen Benutzeraktionen denken und sie klar definieren. Als nächstes werden wir mit dem Entwerfen der Schnittstellen und Klassen fortfahren.
Für unsere Bewerbung beginnen wir mit der Definition, was ein Todo für uns ist. Ein Todo ist eine Aufgabe, die erledigt werden muss. Wir erstellen eine Liste solcher Aufgaben, um uns zu helfen, ein prdozutives Leben zu führen. Wir verfolgen die Liste immer wieder, während wir die Aufgaben nacheinander erledigen. Ein Todo -Element für uns hat unteren Eigenschaften:
Zunächst hat eine Aufgabe den Status "Todo". Wenn wir anfangen, daran zu arbeiten, ändern wir es in "laufend". Sobald die Aufgabe erledigt ist, markieren wir ihren Status als "fertig".
Wir möchten, dass unsere Anwendung auch mehrere Benutzer unterstützt. Und jeder Benutzer hat eine eigene private Liste. Daher können Benutzer die Todo -Liste anderer nicht sehen. Ein Benutzer wird durch seinen Benutzernamen identifiziert, der für uns gültige E -Mail -Adresse ist. Benutzer erhalten Konten in unserer Anwendung. Somit hat ein Konto unter den Eigenschaften:
Wir möchten, dass ein "Administrator" -Konto nur Konten verwaltet. Das Administratorkonto verwendet den Benutzernamen "Administrator". Der Administrator Benutzer kann:
Die letzten beiden Artikel sind es wert, beobachtet zu werden. Normalerweise wird angenommen, dass ein Benutzer mit "Administratorrechten" Zugriff auf die Informationen aller hat. Wir wollen das nicht. Außerdem haben wir bereits definiert, dass das "Admin" -Konto für uns nur die Verwaltung von Konten ist. Es dient nicht zum Verwalten von TODO -Listen von Benutzern. Das Benutzerkonto von 'Admin' wird nicht oft verwendet. Es ist nur für besondere Zwecke gedacht. Für unsere Anwendung erwarten wir, dass ein Benutzerkonto auch das "Administrator" -Konto verarbeitet. Es ist also dieselbe Person, die bei Bedarf nur bei Bedarf 'Admin -Anmeldeinformationen angemeldet wird. Da es sich um ein vorhandenes Benutzerkonto handelt, das "Administrator" nur zum Verwalten aller Konten verwendet, möchten wir keine separate Aufgabenliste für das Administratorkonto. Das erfüllt keinen Zweck.
Wir möchten, dass die Todo -Listen immer bestehen bleiben. Dies bedeutet, dass ein Benutzer von einem Benutzer erfolgreich erstellt wurde, so dass es niemals gelöscht werden kann. Ebenso möchten wir auch kein Benutzerkonto löschen. Abschließend möchten wir in unserer Bewerbung keine "Löschen" -Operationen unterstützen. So unterstützen wir Cru nur aus Crud.
Da wir möchten, dass unsere Bewerbung private Todo -Listen verwaltet, möchten wir, dass die Anwendung Anmelde- und Abmeldemechanismen bereitstellt. Dies nennt man "Authentifizierung". Jeder Benutzer, einschließlich "Admin", sollte sich zunächst authentifizieren. Nach einer erfolgreichen Authentifizierung wird ein Benutzer in seinen Arbeitsbereich umgeleitet. Da wir zwei Arten von Benutzern diskutieren (ein Administrator und einen anderen Normalwert), werden wir zwei Arten von Arbeitsbereichen in unserer Anwendung haben. Ein Administrator -Benutzer arbeitet nur mit dem Arbeitsbereich der Benutzerkontoverwaltung. Ein normaler Benutzer muss nur mit dem Arbeitsbereich des TODO List Managements arbeiten. Beide sind exklusiv. Ein normaler Benutzer kann den Arbeitsbereich eines Administrators nicht sehen. Der Administrator -Benutzer kann den Arbeitsbereich des normalen Benutzers nicht sehen. Dies wird als "Autorisierung" bezeichnet.
Zusätzlich zu den oben genannten Anforderungen möchten wir, dass unsere Anwendung die Details der Login- und Abmeldungstempel der Benutzer speichert. Dadurch verfolgen wir die Aktivitäten der Benutzer in unserer Anwendung. Dies ist nicht genau das Rechnungswesen von AAA, aber für unsere Bewerbung dient dies dem Zweck, es als "Buchhaltung" zu bezeichnen.
Basierend auf den Anforderungen, die wir bisher gesammelt haben, verstehen wir, dass wir Daten für die folgenden Einheiten der Anwendung speichern müssen:
Beispieldaten für wenige Konten:
| Konto -ID | Benutzername | Vorname | Nachname | Passwort | Erstellt at | Status |
|---|---|---|---|---|---|---|
| 1 | Administrator | Administrator | Benutzer | Passwort | 2020-05-06 17:34:04 | ermöglicht |
| 2 | [email protected] | John | Johnsson | OneWord | 2020-05-07 12:34:04 | deaktiviert |
| 3 | [email protected] | Eric | Ericsson | Twoword | 2020-05-08 13:34:04 | ermöglicht |
| 4 | [email protected] | Ana | Maria | Dreiwort | 2020-05-09 11:34:04 | ermöglicht |
Wir sehen, dass die Kontostatus in der gesamten Tabelle wiederholt werden. Im Rahmen der Datenbanknormalisierung ist es also besser, die wiederholten Daten in eine separate Tabelle zu setzen. Es gibt einen guten Grund dafür. Nehmen wir an, wir haben 100 Benutzer. Und wir möchten die aktivierten Wörter ersetzen und mit 1 bzw. 2 deaktiviert. Wir müssen die Statusspalte aller Zeilen der Tabelle ändern. Stellen Sie sich vor, wie mühsam es ist, eine solche Änderung für einen Tisch mit Tausenden von Zeilen vorzunehmen! Datenbanknormalisierung bei Rettung zum Glück!
Nach der Normalisierung werden wir zwei Tabellen haben - Account_statuss und Konten:
Account_status
| AUSWEIS | Status |
|---|---|
| 1 | ermöglicht |
| 2 | deaktiviert |
Konten
| Konto -ID | Benutzername | Vorname | Nachname | Passwort | Status -ID |
|---|---|---|---|---|---|
| 1 | Administrator | Administrator | Benutzer | Passwort | 1 |
| 2 | [email protected] | John | Johnsson | OneWord | 2 |
| 3 | [email protected] | Eric | Ericsson | Twoword | 1 |
| 4 | [email protected] | Ana | Maria | Dreiwort | 2 |
In ähnlicher Weise werden wir drei Tabellen für Aufgaben haben - Task_statuses, Task_Priorities und Aufgaben:
Task_statuss
| AUSWEIS | Status |
|---|---|
| 1 | Todo |
| 2 | im Gange |
| 3 | Erledigt |
Task_priorities
| AUSWEIS | Priorität |
|---|---|
| 1 | Wichtig und dringend |
| 2 | wichtig, aber nicht dringend |
| 3 | nicht wichtig, aber dringend |
| 4 | nicht wichtig und nicht dringend |
Aufgaben
| Aufgaben -ID | Konto -ID | Details | Erstellt at | Frist | Zuletzt aktualisiert | Status -ID | Priority ID |
|---|---|---|---|---|---|---|---|
| 1 | 2 | Stifte kaufen. | 2019-05-06 17:40:03 | 2019-05-07 17:40:03 | 2 | 1 | |
| 2 | 3 | Bücher kaufen. | 2019-05-07 7:40:03 | 2019-05-07 17:40:03 | 2019-05-07 23:40:03 | 2 | 1 |
Schließlich haben wir auch eine weitere Voraussetzung, um Konto -Sitzungsdaten zu speichern. Wir werden es wie in der folgenden Tabelle gezeigt aufbewahren:
Account_Sessions
| Sitzungs -ID | Konto -ID | Sitzung erstellt | Sitzungsende |
|---|---|---|---|
| ASD1GH | 1 | 2019-05-06 17:40:03 | 2019-05-06 18:00:03 |
Normalerweise werden in Enterprise -Anwendungen IDs nicht als Ganzzahlen gespeichert. Weil es für jemanden einfacher sein wird, andere Informationen abzufragen, indem sie nur eine Ganzzahl verwenden! In realen Anwendungen sind IDs nicht numerisch, sondern alphanumerisch mit bis zu 100 Zeichen. Machen Sie es also jemandem unmöglich, einen anderen Ausweis zu erraten!
Wir werden unsere Datenbank in MySQL als "Todo" anrufen. Und hier ist das Datenmodell, das auf den oben genannten Informationen basiert:

Wir werden diese Anwendung nach dem berühmten und weit verbreiteten MVC 2 -Desgin -Muster entwickeln. Die folgende Abbildung zeigt, wie wir MVC für unsere App implementieren werden: 
Unsere Anwendung wird Aktion basieren. Wenn ein Benutzer eine HTTP -Anfrage an unsere Anwendung sendet, übersetzen wir sie in die entsprechende Aktion in unserer Anwendung. Die Aktionen, die wir unterstützen, sind Erstellen, Lesen und Update (CRU). Unsere Anwendung ist im Wesentlichen ein datengesteuerter. Es erleichtert Aktionen in der Datenbank. Es hilft Benutzern, ihre Daten mit Hilfe von Authentifizierungs- und Autorisierungsmechanismen sicher und sicher in einer Remote -Datenbank zu speichern und zu verwalten. Es fungiert als HTML- und HTTP -basierte Schnittstelle zur Datenbank.
Wenn ein Benutzer eine HTTP -Anfrage an unsere Anwendung stellt, senden wir angeforderte Daten in Form von HTML zurück. HTML unterstützt Links und Formulare, um Benutzern dabei zu helfen, mit Webanwendungen zu interagieren. Links werden zum Abrufen/GET -Informationen (HTTP -GET) verwendet, während Formulare zum Posten von Daten (HTTP -Post) für die Webanwendung verwendet werden.
So werden wir HTTP -Anfragen in Aktionen übersetzen:
| HTML -Element | HTTP -Methode | Bewerbungsaktion |
|---|---|---|
| Hyperlink | Http bekommen | Details lesen |
| Bilden | Http Post | Erstellen oder aktualisieren |
HTTP GET sendet die Daten als Abfrageparameter an die URL. Während der HTTP -Post die Daten in der HTTP -Anforderungsbehörde sendet. HTTP -Post enthüllt die Daten nicht über die URL, während HTTP GET TOT. HTTP GET ist also nicht zum Senden von Anmeldeinformationen geeignet. Niemand möchte seinen Benutzernamen und sein Passwort an die HTTP -Anfrage -URL angehängt sehen! Wir werden den HTTP -Post verwenden, um die Anmeldeinformationen des Benutzers beim Anmelden zu senden.
Also haben wir uns weit entschieden, wie wir HTTP, HTML und eine Datenbank verwenden werden. Es gibt ein weiteres Konzept von HTTP, das für uns wichtig ist, die Architektur unserer HTTP -basierten Anwendung zu entscheiden. Das ist URL - einheitlicher Ressourcen -Locator. Hier ist eine Beispiel -URL einer Webanwendung mit dem Namen "WebApp" auf dem Beispiel für Beispiel.com:
http://www.example.com/webapp/details?id=12
In der obigen Beispiel -URL ist 'HTTP' das Protokoll, www.example.com der Domänenname oder Servername, 'WebApp' ist der auf dem Server bereitgestellte Anwendungskontext und 'Details' ist die Anwendung, für die wir unsere HTTP -Anfrage senden. 'ID' ist der Abfrageparameter, den wir mit einem Wert von '12' an die 'Details' übergeben. Abfrageparameter bieten uns einen Mechanismus, um die Parameter an die Webanwendung zu übergeben und verwandte Inhalte als Antwort aus der Webanwendung zurück zu empfangen. Stellen Sie sich beispielsweise eine Wetteranwendung vor, die auf einem Webserver ausgeführt wird. Anstatt uns die Liste der Wetterberichte aller Standorte zur Verfügung zu stellen, können wir unsere Wahl für den Standort als Abfrageparameter an die Webanwendung senden. Die Bewerbung würde dann als Antwort die Wetterdetails unserer Standortauswahl senden.
Eine Webanwendung wird auf dem Webserver ausgeführt, im Gegensatz zu Anwendungen, die auf unseren PCs ausgeführt werden. Eine Java -Anwendung, die auf einem Webserver ausgeführt wird, wird als Servlet aufgerufen. Servlets emulieren die Webanwendungen. Sie laufen in einem Behälter. Apache Tomcat ist ein beliebtes Beispiel eines solchen Containers. Die Containersoftware übersetzt die RAW -HTTP -Anforderungen und -Tonantionen in Java -Objekte und bietet sie für Servlets. Eine statische Website bedient den gleichen Inhalt für jede HTTP -Anfrage. Ein Servlet kann jedoch dynamische Inhalte erzeugen, die für jede HTTP -Anforderung unterschiedlich sind.
Die TODO -Web -App, die wir erstellen, enthält mehrere Teile - Servlets, Filter, JSP -Dateien, Datenbankklassen, Pojos usw. Wir werden sie alle zusammen (wie Bündeln) unter einen Anwendungskontext (oder die Anwendungsumgebung) auf den Container (Tomcat) zusammenstellen. Wir werden diesen Anwendungskontext als "todo" bezeichnen. Wenn wir also Tomcat auf unserem PC in Port 8080 ausführen, kann über die URL auf unseren Anwendungskontext 'Todo' zugegriffen werden:
http://localhost:8080/todo/
Unsere Datenschicht besteht aus einer Implementierung von DAO -Muster und Fabrikmuster auf der JDBC -Datenquelle. Wir wählen JDBC DataSource anstelle von DriverManager, da wir die Vorteile des Verbindungspoolings nutzen möchten.
Wir haben nur einen Servlet, der als Controller als "Main" dient. Die HTTP -Anfrage eines Benutzers ist eine Aktion für uns. Der Zweck unseres Controller -Servlets besteht also darin, nur eine geeignete Aktion für die HTTP -Anfrage auszuwählen. Der Controller Servlet wählt einen Aktionshandler aus und übergibt ihn über die vom Benutzer gestellte Anfrage. Wir schreiben die Aktionsausführungsschritte nicht in unserem Controller. Wir halten es sauber und schlank. Sein Ziel ist es, einen Action -Handler zu wählen. Die Aktion nicht selbst ausführen. Nachdem der Aktionshandler die angeforderte Aktion ausgeführt hat, erhält der Controller den "nächsten Schritt", der als Antwort aus dem Aktionshandler ausgeführt werden soll. Die Aufgabe von Controller besteht darin, einfach die Ressource auszuwählen, die die angeforderte Antwort ausführt. Abschließend halten wir unseren Controller von der gesamten Geschäftslogik fern.
Wir werden unseren Controller -Servlet dem URI -Muster /app/* zuordnen. Unser Controller -Servlet leitet also jede URI ab, die dem Muster /app/ folgt.
Eine von einem Benutzer angeforderte Aktion ist die Geschäftslogik für unsere Anwendung. Aktionshandler sind das Modell in unserer MVC -Implementierung. Jede Aktion muss die Aktionsschnittstelle implementieren:
public interface Action {
/*
An action is supposed to execute and return results. ActionResponse represents the response.
*/
public abstract ActionResponse execute ( HttpServletRequest request , HttpServletResponse response )
throws Exception ;
}Eine Aktion soll Ergebnisse ausführen und zurückgeben. Wir erstellen eine spezielle Klasse für ein solches Ergebnis - ActionResponse. Ein Action -Handler kann wählen, sich zu „vorantreiben“ oder „umleiten“.
public class ActionResponse {
private String method ;
private String viewPath ;
public ActionResponse () {
this . method = "" ;
this . viewPath = "" ;
}
public void setMethod ( String method ) {
this . method = method ;
}
public String getMethod () {
return this . method ;
}
public void setViewPath ( String viewPath ) {
this . viewPath = viewPath ;
}
public String getViewPath () {
return this . viewPath ;
}
@ Override
public String toString () {
return this . getClass (). getName ()+ "[" + this . method + ":" + this . viewPath + "]" ;
}
}Wir implementieren das Fabrikdesignmuster. Wir erstellen eine Fabrikklasse - actionFactory -, um uns die von uns benötigte Aktionshandlerklasse zu geben:
public class ActionFactory {
private static Map < String , Action > actions = new HashMap < String , Action >() {
{
put ( new String ( "POST/login" ), new LoginAction ());
put ( new String ( "GET/login" ), new LoginAction ());
put ( new String ( "GET/logout" ), new LogoutAction ());
put ( new String ( "GET/admin/accounts/dashboard" ), new AdminAccountsDashboardAction ());
put ( new String ( "GET/admin/accounts/new" ), new AdminNewAccountFormAction ());
put ( new String ( "POST/admin/accounts/create" ), new AdminCreateAccountAction ());
put ( new String ( "GET/admin/accounts/details" ), new AdminReadAccountDetailsAction ());
put ( new String ( "POST/admin/accounts/update" ), new AdminUpdateAccountAction ());
put ( new String ( "GET/tasks/dashboard" ), new UserTasksDashboardAction ());
put ( new String ( "GET/tasks/new" ), new UserNewTaskFormAction ());
put ( new String ( "GET/tasks/details" ), new UserReadTaskDetailsAction ());
put ( new String ( "POST/tasks/create" ), new UserCreateTaskAction ());
put ( new String ( "POST/tasks/update" ), new UserUpdateTaskAction ());
put ( new String ( "GET/users/profile" ), new UserReadProfileAction ());
put ( new String ( "POST/users/update" ), new UserUpdateProfileAction ());
}
;
};
public static Action getAction ( HttpServletRequest request ) {
Action action = actions . get ( request . getMethod () + request . getPathInfo ());
if ( action == null ) {
return new UnknownAction ();
} else {
return action ;
}
}
}Der Zweck unseres Controller -Servlets ist:
protected void processRequest ( HttpServletRequest request , HttpServletResponse response )
throws ServletException , IOException {
Action action = ActionFactory . getAction ( request );
try {
ActionResponse actionResponse = action . execute ( request , response );
if ( actionResponse . getMethod (). equalsIgnoreCase ( "forward" )) {
System . out . println ( this . getClass (). getCanonicalName () + ":forward:" + actionResponse );
this . getServletContext (). getRequestDispatcher ( actionResponse . getViewPath ()). forward ( request , response );
} else if ( actionResponse . getMethod (). equalsIgnoreCase ( "redirect" )) {
System . out . println ( this . getClass (). getCanonicalName () + ":redirect:" + actionResponse );
if ( actionResponse . getViewPath (). equals ( request . getContextPath ())) {
response . setHeader ( "Cache-Control" , "no-cache, no-store, must-revalidate" );
response . setHeader ( "Pragma" , "no-cache" );
response . setDateHeader ( "Expires" , 0 );
}
response . sendRedirect ( actionResponse . getViewPath ());
} else if ( actionResponse . getMethod (). equalsIgnoreCase ( "error" )) {
System . out . println ( this . getClass (). getCanonicalName () + ":error:" + actionResponse );
response . sendError ( 401 );
} else {
System . out . println ( this . getClass (). getCanonicalName () + ":" + actionResponse );
response . sendRedirect ( request . getContextPath ());
}
} catch ( Exception e ) {
e . printStackTrace ();
}
} Die folgende Tabelle zeigt die Liste der HTTP -Anfragen, auf die unsere Bewerbung und deren zugehörigen Aktionshandler antwortet:
| Benutzerin vorgesehene Aktion | HTTP -Anfrage URI | Action -Handler |
|---|---|---|
| Senden Sie leere Login -Anmeldeinformationen | GET /app/login | Anmeldung |
| Anmeldeinformationen einreichen | POST /app/login | Anmeldung |
| Richten Sie Account -Dashboard | GET /app/admin/accounts/dashboard | AdminAcountSdashboardAction |
| Holen Sie sich eine neue Kontoform | GET /app/admin/accounts/new | AdminNewAccountFormAction |
| Senden Sie neue Kontodetails | POST /app/admin/accounts/create | AdmincreateAccountaction |
| Holen Sie sich Details zu einem Konto | GET /app/admin/accounts/details?id=xx | AdminreadAccountDetailsaction |
| Aktualisieren Sie die Details eines Kontos | POST /app/admin/accounts/update | AdminUpdateAccountaction |
| Holen Sie sich das Dashboard von Aufgaben | GET /app/tasks/dashboard | UserTasKsDashboardaction |
| Holen Sie sich neues Aufgabenformular | GET /app/tasks/new | Benutzernewtaskformaction |
| Senden Sie neue Aufgabendetails | POST /app/tasks/create | UserCreateTaskaction |
| Holen Sie sich Details einer Aufgabe | GET /app/tasks/details?id=xx | UserReReadTaskDetailsaction |
| Aktualisieren Sie Details einer Aufgabe | POST /app/tasks/update | UserUpdatetaskaction |
| Holen Sie sich Details zu meinem Profil | GET /app/users/profile | UserReadProfilaction |
| Aktualisieren Sie meine Profildetails | POST /app/users/update | UserUpdateProfileaction |
| Abmelden | GET /app/logout | Abmeldung |
Die Aufgabe eines Aktionshandlers besteht darin, die Geschäftslogik auszuführen und eine geeignete Ansichtskomponente als Antwort auf die Anforderung eines Benutzers auszuwählen. Die folgende Tabelle zeigt alle Action -Handler und ihre Ansichtskomponenten:
| Action -Handler | Komponente anzeigen |
|---|---|
| Anmeldung | /WEB-INF/pages/admin/accounts/dashboard.jsp/WEB-INF/pages/tasks/dashboard.jsp |
| AdminAcountSdashboardAction | /WEB-INF/pages/admin/accounts/dashboard.jsp |
| AdminNewAccountFormAction | /WEB-INF/pages/admin/accounts/newAccount.jsp |
| AdmincreateAccountaction | /WEB-INF/pages/admin/accounts/createAccountResult.jsp |
| AdminreadAccountDetailsaction | /WEB-INF/pages/admin/accounts/accountDetails.jsp |
| AdminUpdateAccountaction | /WEB-INF/pages/admin/accounts/updateAccountResult.jsp |
| UserTasKsDashboardaction | /WEB-INF/pages/tasks/dashboard.jsp |
| Benutzernewtaskformaction | /WEB-INF/pages/tasks/newTask.jsp |
| UserCreateTaskaction | /WEB-INF/pages/tasks/createTaskResult.jsp |
| UserReReadTaskDetailsaction | /WEB-INF/pages/tasks/taskDetails.jsp |
| UserUpdatetaskaction | /WEB-INF/pages/tasks/updateTaskResult.jsp |
| UserReadProfilaction | /WEB-INF/pages/users/viewProfile.jsp |
| UserUpdateProfileaction | /WEB-INF/pages/users/updateProfileResult.jsp |
| Unbekannte | /WEB-INF/pages/users/unknownAction.jsp |
Die Ansichtskomponente erstellt die erforderliche HTML -Antwort, die an den Benutzer gesendet wird. Die Komponente anzeigen liest die vom Action -Handler festgelegten Nachrichten und zeigt es dem Benutzer an.
Wir verwenden Filter, um eingehende HTTP -Anforderungen abzufangen. Alle Filter werden verwendet, bevor die Anfrage an den Controller Servlet weitergegeben wird. Jede eingehende HTTP -Anfrage wird mit dem Authentifizierungsfilter aus erster Handhabung behandelt. Über diesen Filter überprüfen wir, ob der Benutzer bereits angemeldet ist oder nicht. Wenn nicht angemeldet, leiten wir den Benutzer zur Anmeldeseite um. Nach erfolgreichem Durchgang des Authentifizierungsfilters wird die HTTP -Anfrage von zwei weiteren Filtern abgefangen. In diesen Filtern überprüfen wir den URI -Pfad und der Benutzer "Admin" oder normaler Benutzer. Wenn ein normaler Benutzer versucht, auf "Admin' -URI -Pfade" zugreifen zu können, verhindern wir einen solchen Zugriff. Wenn der Benutzer des Administrators versucht, auf Aufgaben zugegründete URI -Pfade zugreifen zu können, verhindern wir einen solchen Zugriff.
Nur 'Admin' kann auf die URIs zugreifen, beginnend mit /app/admin/* und nur normaler Benutzer kann auf die URIs zugreifen, beginnend mit /app/tasks/* . Andere URIS /app/login , /app/logout , /app/users/* kann von beiden zugegriffen werden.
Wir nehmen keine Antworten ab, die wir senden.
So sieht unsere Bewerbung aus. Ich habe die Benutzeroberfläche zum Einfachheit halber einfach gehalten. Es gibt kein CSS oder JavaScript.










