Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
de:modul:ffit:3-jahr:java:learningunits:lu10:a [2025/11/09 23:15] apeterde:modul:ffit:3-jahr:java:learningunits:lu10:a [2025/11/10 00:02] (aktuell) apeter
Zeile 1: Zeile 1:
 ====== LU10a - Umgang mit Exceptions ====== ====== LU10a - Umgang mit Exceptions ======
 +
 +==== Spring ResponseStatusException ====
 +
 +Allgemein gilt, dass Exceptions in Bezug auf die Performanz schlechter abschneiden als die entsprechenden Checks. Daher sollte man Exceptions nie in "Schönwetter"-Fällen benutzen, sondern höchstens in unerwarteten Situationen. Ein ungültiger API-Aufruf ist in unserem Fall aber unerwartet und kann mittels einer Exception gelöst werden. Werden aber viele ungültige API-Aufrufe erwartet, sollte man eine Exception-freie Alternative in Erwägung ziehen.
 +
 +Spring bietet eine sehr einfache Version, um Fehlerfälle mittels Exceptions abzuhandeln. Dabei wird direkt automatisch eine Antwort mit dem entsprechenden HTTP-Statuscode erstellt und zurückgeschickt.
 +
 +Im nachfolgenden Beispiel wird jeweils ein Project-Objekt geladen und falls kein Objekt in der Datenbank vorhanden ist, wird der Statuscode 404 zurückgegeben. 
 +
 +^ Lange Variante ^ Verkürzte Variante ^ Variante mit Exception ^
 +| <WRAP>
 +<code java>
 +Optional<Project> optionalProject = projectRepository.findById(projectName);
 +if(optionalProject.isEmpty()){
 +    return ResponseEntity.notFound().build();
 +}
 +Project project = optionalProject.get();
 +</code> 
 +</WRAP> | <WRAP>
 +<code java>
 +Project project = projectRepository.findById(projectName).orElse(null);
 +if(null == project){
 +    return ResponseEntity.notFound().build();
 +}
 +</code> 
 +</WRAP> | <WRAP>
 +<code java>
 +Project project = projectRepository.findById(projectName).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Project not found"));
 +</code>
 +</WRAP> |
 +
 +Ein sehr grosser Vorteil der dritten Variante ist die Wiederverwendbarkeit: Ein ResponseEntity-Objekt kann nur in der API-Methode zurückgegeben werden. Eine ResponseStatusException kann aber auch in einer verschachtelten Methode geworfen werden. Das erlaubt, dass man Methoden, die man zum Beispiel bei mehreren API-Methoden benötigt, bequem auslagern kann.
  
 ==== Validierung des JWT ==== ==== Validierung des JWT ====
Zeile 18: Zeile 50:
 <WRAP center round info 60%> <WRAP center round info 60%>
 **Kleine Wiederholung** **Kleine Wiederholung**
 +
 Setzt man Exceptions ein, sollte man diese auch loggen oder weiterschicken (gegebenenfalls sogar ans Frontend). Ein "catch" ohne Verwendung der gefangenen Exception, wie im Beispiel, ist zu vermeiden. Setzt man Exceptions ein, sollte man diese auch loggen oder weiterschicken (gegebenenfalls sogar ans Frontend). Ein "catch" ohne Verwendung der gefangenen Exception, wie im Beispiel, ist zu vermeiden.
 </WRAP> </WRAP>
  
- +Wenn nun zudem Informationen wie das "Subject" aus dem JWT herausgelesen werden müssenergibt es keinen Sinn, eine separate "Exception"-basierte Validierung zu machenMan kann die Validierung und das Auslesen direkt kombinierenNutzt man zudem die ResponseStatusExceptionhat man eine Methode, die man in mehreren API-Methoden einsetzen kann.
- +
-Hierbei ist anzumerkendass Exceptions in aller Regel in Bezug auf die Performanz schlechter abschneiden als die entsprechenden Checks. Daher sollte man Exceptions nie in "Schönwetter"-Fällen benutzen, sondern höchstens in unerwarteten SituationenEin invalides Token, bzw. allgemein ein ungültiger API-Aufruf, ist in unserem Fall unerwartet und kann mittels Exceptions gelöst werdenWerden aber viele ungültige API-Aufrufe erwartetsollte man eine Exception-freie Alternative in Erwägung ziehen. +
- +
-Wenn zudem  +
- +
  
 <code java> <code java>
-import org.slf4j.Logger+public String verifyTokenAndExtractSubject() { 
-import org.slf4j.LoggerFactory;+    try{ 
 +        String token = extractTokenFromHeader()
 +        return extractSubject(token); 
 +    } catch (Exception e) { 
 +        // Exception mitschicken 
 +        // throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid token", e);
  
-public class DemoController { +        // Exception loggen 
-    private static final Logger log = LoggerFactory.getLogger(DemoController.class); +        log.warn("Invalid token", e); 
-    ... +        throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid token"); 
-        log.error("Error during execution of...:", e); +    } 
-</code>+}
  
-Neu ist, dass wir die dazugehörigen Einstellungen einfach in unser ''application.properties'' schreiben können.+private String extractSubject(String token) { 
 +    return Jwts.parserBuilder() 
 +            .setSigningKey(key) 
 +            .build() 
 +            .parseClaimsJws(token) 
 +            .getBody() 
 +            .getSubject(); 
 +}
  
-<code application.properties> +private String extractTokenFromHeader() { 
-logging.level.root=INFO +    ServletRequestAttributes attributes (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 
-logging.level.ch.bzz=DEBUG +    if (attributes == null){ 
-logging.file.name=app.log +        return null; 
-</code> +    } 
-  +    String authHeader = attributes.getRequest().getHeader("Authorization")
- +    if (authHeader == null || !authHeader.startsWith("Bearer ")) { 
-Project Lombok hilft uns auch hier die Erstellung des Logger-Objektes zu vereinfachen +        return null; 
- +    } 
-<code java> +    return authHeader.substring(7); 
-import lombok.extern.slf4j.Slf4j+}
- +
-@Slf4j +
-public class DemoController { +
-    ... +
-        log.error("Error during execution of...:", e);+
 </code> </code>
  
  • de/modul/ffit/3-jahr/java/learningunits/lu10/a.1762726558.txt.gz
  • Zuletzt geändert: 2025/11/09 23:15
  • von apeter