2016-07-20 4 views
2

ich Anwendung mit vielen Ruhe Dienstleistungen haben, folgt die meisten von ihnen dieses Muster:Wie man innerhalb jeder Methode von try/catch Methode loszuwerden

class RestService{ 

    public Response execute1() { 
     try{ 
     // doLogicThere... 

     return response; 
     } catch() { 
     // handle exception and build Response object.. 

     return response; 
     } 
    } 

    public Response execute2() { 
     try{ 
      // doLogicThere... 

      return response; 
     } catch() { 
      // handle exception and build Response object.. 

      return response; 
     } 
    } 
} 

catch-Klausel ist die gleiche für alle Methoden, so will ich haben Muster wie unten, aber mit Versuch/Fang von woanders angerufen. Ich möchte diese Methoden einpacken.

+0

Sie fangen entweder an dem Punkt, an dem die Ausnahme auftreten soll, oder Sie fangen irgendwo weiter oben im Aufruf-Stack ein. –

+0

Mögliche Duplikate von [Vermeiden Sie leere Catch-Blöcke, wenn Sie eine Ausnahme erwarten] (http://stackoverflow.com/questions/38468125/avoid-empty-catch-blocks-when-expecting-exception) –

+1

Wie Sie mit Feder sind, empfehle ich Ihnen um dies zu betrachten https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc suchst du so etwas? – user902383

Antwort

2

JAX-WS enthält einen Mechanismus, um die richtige Antwort für jede Art von Ausnahme für die Erstellung, die Ihre RESTE Methoden produzieren könnten.

Erstellen Sie für jeden Ausnahmetyp eine Klasse, die ExceptionMapper<E> implementiert, wobei E der Typ der Ausnahme ist. Sie erstellen Ihre Antwort in der toResponse Methode. Sie müssen Ihren Exception-Mapper mit @Provider annotieren, um ihn mit der JAX-RS-Laufzeit zu registrieren.

@Provider 
public class UserNotFoundMapper implements ExceptionMapper<UserNotFoundException> { 
    @Override 
    public Response toResponse(UserNotFoundException e) { 
     return Response.status(404).entity(e.getMessage()).type("text/plain").build(); 
    } 
} 
+0

Das war mein erster Dreh. Leider hatte ich es mit der Registrierung dieses Anbieters zu tun, da ich meinen Custom Web Application Container verwende. In einigen Fällen müssen Sie den Provider manuell registrieren, wie Sie es manchmal für JacksonJsonProvider tun. – MagGGG

2

Sie eine Schnittstelle mit der Methode Sie ausführen müssen, erstellen können. Dann können Sie diese Methode in einer neuen Methode in einen try catch umbrechen. Dies wird die Verwendung vieler wiederholter Versuchsbegrenzungsblöcke vermeiden.

Sie können so etwas tun:

public interface CallableClass { 
    public Response call(); 
} 



... 

class RestService { 
    private Response handleCall(CallableClass myClass) { 
     try { 
      return myClass.call(); 
     } catch (Exception e) { 
      // Handle exception and return a particular response 
      ... 
     } 
    } 

    public Response execute1() { 
     return handleCall(/* put anonymous class of type CallableClass here */); 
    } 

    public Response execute2() { 
     return handleCall(/* put anonymous class of type CallableClass here */); 
    } 

} 

Wenn Sie Java verwenden 8 Sie die anonynous Klasse mit einem eleganteren Lambda-Ausdruck ersetzen können.


Hier ist ein einfaches Beispiel mit Lambda

public Response executeLambda() { 
    return handleCall(() -> { 
     ... // Your code here 
     return response; 
    }); 
} 
+0

Können Sie ein Beispiel mit Lambdas angeben? – jimpudar

+0

@jimpudar Ich habe ein einfaches Beispiel in der Antwort hinzugefügt –

0

Wenn Sie bauen RESTful-Service SPring MVC verwenden, Sie haben eine bessere Möglichkeit, mit folgenden Anmerkung "(CustomExceptionForRestServices.class) @ExceptionHandler" nutzen. Wo Sie Ihre benutzerdefinierte Ausnahme schreiben können oder eine kommagetrennte Liste von Ausnahmeklassen haben, erwarten Sie, dass Ihre Methode ausgelöst wird.

Der @ExceptionHandler-Wert kann auf ein Array von Exception-Typen festgelegt werden. Wenn eine Ausnahme ausgelöst wird, die einem der Typen in der Liste entspricht, wird die mit dem entsprechenden @ExceptionHandler annotierte Methode aufgerufen. Wenn der Anmerkungswert nicht festgelegt ist, werden die als Methodenargumente aufgeführten Ausnahmetypen verwendet.

Ähnlich wie Standard-Controller-Methoden, die mit einer @RequestMapping-Annotation versehen sind, sind die Methodenargumente und Rückgabewerte von @ExceptionHandler-Methoden sehr flexibel.

0

Ich habe ein kleines Beispiel in plain AspectJ erstellt, d. H. Ohne Spring.Ich habe sogar ein Dummy Response Klasse nur um die grundlegenden Mechanismen hinter Aspekte gesteuerte Ausnahmebehandlung zu zeigen:

Dummy Response-Klasse:

package de.scrum_master.app; 

public class Response { 
    private int statusCode; 
    private String message; 

    public Response(int statusCode) { 
     this.statusCode = statusCode; 
     switch (statusCode) { 
     case 200: 
      message = "OK"; 
      break; 
     case 202: 
      message = "Accepted"; 
      break; 
     case 401: 
      message = "Unauthorized"; 
      break; 
     default: 
      message = "Unknown status"; 
     } 
    } 

    public int getStatusCode() { 
     return statusCode; 
    } 

    @Override 
    public String toString() { 
     return "Response(statusCode=" + statusCode + ", message=" + message + ")"; 
    } 
} 

Treiber-Anwendung mit zwei Methoden abgefangen werden:

Wie Sie sehen können, werfen beide Methoden zufällig Ausnahmen, die später von einem Aspekt erfasst werden sollten.

package de.scrum_master.app; 

import java.util.Random; 

public class RestService { 
    private static final Random RANDOM = new Random(); 

    public Response someRequest() { 
     Response response = new Response(RANDOM.nextBoolean() ? 200 : 401); 
     if (response.getStatusCode() != 200) 
      throw new RuntimeException("request failed: " + response); 
     return response; 
    } 

    public Response anotherRequest(String argument) { 
     Response response = new Response(RANDOM.nextBoolean() ? 200 : 401); 
     if (response.getStatusCode() != 200) 
      throw new RuntimeException("request failed: " + response); 
     return response; 
    } 

    public static void main(String[] args) { 
     RestService restService = new RestService(); 
     for (int i = 0; i < 3; i++) { 
      System.out.println(restService.someRequest()); 
      System.out.println(restService.anotherRequest("foo")); 
     } 
    } 
} 

Ausnahmebehandlung Aspekt: ​​

package de.scrum_master.aspect; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 

import de.scrum_master.app.Response; 

@Aspect 
public class ResponseErrorHandler { 
    @Around("execution(de.scrum_master.app.Response *(..))") 
    public Response handleError(ProceedingJoinPoint thisJoinPoint) { 
     System.out.println("\n" + thisJoinPoint); 
     try { 
      return (Response) thisJoinPoint.proceed(); 
     } 
     catch (Exception e) { 
      System.out.println(" Handling exception: " + e.getMessage()); 
      return new Response(202); 
     } 
    } 
} 

Konsolenprotokoll:

execution(Response de.scrum_master.app.RestService.someRequest()) 
Response(statusCode=200, message=OK) 

execution(Response de.scrum_master.app.RestService.anotherRequest(String)) 
Response(statusCode=200, message=OK) 

execution(Response de.scrum_master.app.RestService.someRequest()) 
Response(statusCode=200, message=OK) 

execution(Response de.scrum_master.app.RestService.anotherRequest(String)) 
    Handling exception: request failed: Response(statusCode=401, message=Unauthorized) 
Response(statusCode=202, message=Accepted) 

execution(Response de.scrum_master.app.RestService.someRequest()) 
Response(statusCode=200, message=OK) 

execution(Response de.scrum_master.app.RestService.anotherRequest(String)) 
    Handling exception: request failed: Response(statusCode=401, message=Unauthorized) 
Response(statusCode=202, message=Accepted) 

Fühlen Sie sich frei Follow-up-Fragen zu stellen, wenn Sie die Antwort nicht verstehen.

Verwandte Themen