Zwei Mal dieselbe Anwendung in 2 verschiedenen Browsern starten

Anfaengerin

Aktives Mitglied
Hallo,

ich habe eine SpringBoot-Anwendung, einen Rechner, den man auf localhost:8080 erreichen kann. Wenn man aber diese Adresse mit zwei verschiedenen Browsern aufruft, kommen die sich "in die Quere", d.h. eine 4, die ich in einem Browser eingegeben habe, erscheint auch im zweiten. Wie kann ich das umgehen?
 

KonradN

Super-Moderator
Mitarbeiter
Kannst Du das einmal im Detail ausführen? Wenn Du zwei unterschiedliche Browser hast (also z.B. Edge und Firefox), dann hast Du auf jeden Fall zwei unterschiedliche Sessions.

Wenn Du nur einen Browser verwendest, aber mehrere Tabs oder Fenster öffnest, dann hast Du nur eine Session. Dies kannst Du vermeiden, in dem Du unterschiedliche Profile verwendest. Dies kann z.B. über die Verwendung von InPrivate Fenstern erfolgen.

Generell ist aber auch die Frage, was Du genau machst. Was genau machst Du in der Spring Boot Anwendung? Was ist im Browser? Wenn Du im Browser eine 4 eingibst: Was machst Du damit genau? Evtl. kannst Du hier einmal mehr Details geben. Hier kommt dann vermutlich der Scope ins Spiel: Wenn Du in Spring Boot einen @Controller hast, dann ist das ein Bean mit Scope Singleton. Das bedeutet, es gibt genau eine Instanz eines solchen Controllers. Wenn Du also eine 4, die von einem Client gekommen ist, in dem Controller speicherst, dann wäre das geteilt zwischen allen Clients (Unabhängig von Browsern, Sessions, Systemen, ....)

Daher wäre meine Bitte, doch einmal mehr Details zu nennen, was Du genau machst und dann können wir die Details erläutern.
 

Anfaengerin

Aktives Mitglied
Kannst Du das einmal im Detail ausführen? Wenn Du zwei unterschiedliche Browser hast (also z.B. Edge und Firefox), dann hast Du auf jeden Fall zwei unterschiedliche Sessions.

Wenn Du nur einen Browser verwendest, aber mehrere Tabs oder Fenster öffnest, dann hast Du nur eine Session. Dies kannst Du vermeiden, in dem Du unterschiedliche Profile verwendest. Dies kann z.B. über die Verwendung von InPrivate Fenstern erfolgen.

Generell ist aber auch die Frage, was Du genau machst. Was genau machst Du in der Spring Boot Anwendung? Was ist im Browser? Wenn Du im Browser eine 4 eingibst: Was machst Du damit genau? Evtl. kannst Du hier einmal mehr Details geben. Hier kommt dann vermutlich der Scope ins Spiel: Wenn Du in Spring Boot einen @Controller hast, dann ist das ein Bean mit Scope Singleton. Das bedeutet, es gibt genau eine Instanz eines solchen Controllers. Wenn Du also eine 4, die von einem Client gekommen ist, in dem Controller speicherst, dann wäre das geteilt zwischen allen Clients (Unabhängig von Browsern, Sessions, Systemen, ....)

Daher wäre meine Bitte, doch einmal mehr Details zu nennen, was Du genau machst und dann können wir die Details erläutern.
Klar. Also es ist ein Webtaschenrechner, ich hab genau einen Controller und wenn ich mit dem Button "4" (0-9 sind möglich) klicke, erscheint im oberen Textfeld eine 4. Dann der Operator und dann die zweite Zahl, ganz simpel gehalten. Für das Ergebnis muss man "=" drücken und das erscheint dann im zweiten Textfeld.
 

Anfaengerin

Aktives Mitglied
Java:
package org.example.taschenrechner;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import static java.lang.Integer.parseInt;

@Controller
public class Controller1 {

    private String anzeige1 = "";
    private String anzeige = "";
    private String aktuelleZahl = "";
    private String operator = "";
    private String vorherigeZahl = "";
    long ergebnisAlsLong;

    @GetMapping("/")
    public String zeigeFormular() {
        return "index";
    }

    @PostMapping("/rechnen")
    public String rechnen(@RequestParam(value = "eingabe") String eingabe,
                          Model model) {

        /*if (eingabe.equals("<-")) {removeLastChar();}*/

        if (eingabe.equals("<-")) {
            removeLastChar();

            // Anzeige aktualisieren
            if (!aktuelleZahl.isEmpty()) {
                anzeige1 = aktuelleZahl;
            } else if (!operator.isEmpty()) {
                anzeige1 = vorherigeZahl + " " + operator;
            } else {
                anzeige1 = vorherigeZahl;
            }

            model.addAttribute("anzeige1", anzeige1);
            model.addAttribute("anzeige", anzeige);
            return "index";
        }

        if (eingabe.matches("[0-9]")) {
            aktuelleZahl += eingabe;
        }

        double zahl1 = vorherigeZahl.isEmpty() ? 0 : Double.parseDouble(vorherigeZahl);
        double zahl2 = aktuelleZahl.isEmpty() ? 0 : Double.parseDouble(aktuelleZahl);
        double ergebnis = 0;


        if (!vorherigeZahl.isEmpty() && !operator.isEmpty() && !aktuelleZahl.isEmpty()) {
            anzeige1 = vorherigeZahl + " " + operator + " " + aktuelleZahl;
        } else if (!vorherigeZahl.isEmpty() && !operator.isEmpty()) {
            anzeige1 = vorherigeZahl + " " + operator;
        } else if (!aktuelleZahl.isEmpty()) {
            anzeige1 = aktuelleZahl;
        } else {
            anzeige1 = "";
        }

        model.addAttribute("anzeige1", anzeige1);
        model.addAttribute("anzeige", anzeige);

        switch (eingabe) {
            case "+", "-", "*", "/" -> {
                if (!aktuelleZahl.isEmpty()) {

                    vorherigeZahl = aktuelleZahl;
                    aktuelleZahl = "";
                }
                operator = eingabe;

                anzeige1 = vorherigeZahl + " " + operator;
                model.addAttribute("anzeige1", anzeige1);
            }

            case "=" -> {

                switch (operator) {
                    case "+" -> ergebnis = zahl1 + zahl2;
                    case "-" -> ergebnis = zahl1 - zahl2;
                    case "*" -> ergebnis = zahl1 * zahl2;
                    case "/" -> {
                        if (zahl2 != 0) {
                            ergebnis = zahl1 / zahl2;
                        } else {
                            anzeige = "Fehler: Division durch Null!";
                            model.addAttribute("anzeige", anzeige);
                            vorherigeZahl = "";
                            aktuelleZahl = "";
                            operator = "";
                            return "index";
                        }
                    }
                    default -> {
                        anzeige = "";
                        model.addAttribute("anzeige", anzeige);
                        return "index";
                    }
                }

                anzeige = String.valueOf(ergebnis);
                model.addAttribute("anzeige", anzeige);
                ergebnisAlsLong = Math.round(ergebnis);
                vorherigeZahl = String.valueOf(ergebnisAlsLong);
                aktuelleZahl = "";
                operator = "";
            }
            default -> {
                anzeige = "";
                model.addAttribute("anzeige", anzeige);
            }
        }

        return "index";
    }

    public void removeLastChar() {
        if (!aktuelleZahl.isEmpty()) {
            aktuelleZahl = aktuelleZahl.substring(0, aktuelleZahl.length() - 1);
        } else if (!operator.isEmpty()) {
            operator = "";
        } else if (!vorherigeZahl.isEmpty()) {
            vorherigeZahl = vorherigeZahl.substring(0, vorherigeZahl.length() - 1);
        }
    }
}
 

KonradN

Super-Moderator
Mitarbeiter
Ok, dann ist es, wie schon genau beschrieben. Von der Klasse gibt es genau 1 Instanz. Die Variablen:
Java:
    private String anzeige1 = "";
    private String anzeige = "";
    private String aktuelleZahl = "";
    private String operator = "";
    private String vorherigeZahl = "";
    long ergebnisAlsLong;

gibt es also auch nur genau ein Mal. Alle Clients teilen sich diese.

Um diese Problematik zu lösen, gibt es mehrere Ansätze. Ein Ansatz wäre, den Scope zu ändern:
Die Änderung wäre sehr klein und überschaubar: Zu dem @Controller kommt einfach noch ein @SessionController

Das geht recht gut, so lange es mehrere Session sind. Also zwei unterschiedliche Browser oder so. Die Probleme sind aber wieder da, wenn jemand in zwei Tabs arbeiten würde.

Das ist aber eine Lösung, die so eher unüblich geworden ist. In modernen Anwendungen versucht man, es zu vermeiden, so einen Status zu merken oder zu speichern. Man spricht von Stateless. Damit das funktioniert, gibst Du alle Daten von der Seite als Parameter mit. Neben der Eingabe also auch die Anzeige. Wenn Du irgendwas zwischenspeichern willst, dann kannst Du das über unsichtbare Felder machen. Und im Controller schreibst Du dann auch alles in das model damit es in der Seite gespeichert wird.
So vermeidest Du, dass unnötige Instanzen aufgebaut werden. Du hast auch nicht das Problem, dass Daten verloren gehen, wenn eine Session auf einen Timeout läuft und so eine Controller Instanz aus dem Speicher entfernt wird. Und das Interface ist auch gut testbar.
 
Ähnliche Java Themen

Ähnliche Java Themen


Oben