3

Spring MVC、Jersey、JAXBを使用してRESTアプリケーションを実装しました。

クライアントServiceRequestは、要求に関する情報を含むオブジェクトを送信しServiceResponse、応答に関する情報を含むオブジェクトを受信します。

サービス要求

@XmlRootElement(name = "servicerequest")
public class ServiceRequest{

    String serviceName = "AddUser"

    public String getServiceName() {
        return serviceName;
    }

    @XmlElement
    public void setServiceName(String serviceName) {
        this.serviceName = name;
    }   
}

ServiceResponse

@XmlRootElement(name = "serviceresponse")
public class ServiceResponse {

    String responseCode; 

    public String getResponseCode() {
        return responseCode;
    }

    @XmlElement
    public void setResponseCode(String code) {
        this.responseCode = name;
    }   
}

クライアントはJerseyを使用してサービスに電話をかけます

ServiceClient

ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource service = client.resource(RESOURCE_URL);

ServiceRequest request = new ServiceRequest();
ServiceResponse response = service.path("addUser").type(MediaType.APPLICATION_XML)
.accept(MediaType.APPLICATION_XML).entity(request).post(ServiceRequest.class);

サーバー側では、サービスはリクエストを取得して処理し、オブジェクトを返しServiceResponseます。

@RequestMapping(method = RequestMethod.POST, 
            value = "/addUser",headers="Accept=application/xml")
    @ResponseStatus(HttpStatus.OK)  
public @ResponseBody ServiceResponse addUser(@RequestBody ServiceRequest request) {

        ServiceResponse response = new ServiceResponse();

        //Handle request
        //service.addUser();

        response.setCode("200");
        return response; 
}

上記のコントローラークラスは、別のサービスクラスを呼び出して、要求を処理します(service.addUser())。このサービスクラスは、いくつかの例外を発生させる可能性があります。

私がよくわからないのは、それらをどのように処理するのが最善かということです。グーグルした後、次のようにExceptionHandlerを使用できることがわかりました。

@ExceptionHandler(NullPointerException.class)
@ResponseBody
public String handleException1(NullPointerException ex)
{
    return ex.getMessage();
}

例外ハンドラーを持つ基本クラスをコントローラーに拡張させることができます。

上記のアプローチに関するいくつかの質問:

  • 例外タイプごとに1つのハンドラーを作成する必要がありますか?処理する必要のある例外が非常に多いので、すべての例外に対して汎用ハンドラーを使用することはできませんか?
  • 私のコントローラーはタイプのオブジェクトを返すのでServiceResponse、例外が発生したときに返されるオブジェクトタイプは何でしょうか?
  • ServiceResponseクライアントは、タイプのオブジェクトを取得することを期待しています。応答が例外タイプの場合、どのように機能しますか?

そして最後に、ExceptionHanlderは次のいずれかの戻り型しか持てないことに気づきました。

ModelAndView
Model
Map
View
String – interpreted as a view name
void, but only if the method writes directly to the response object

ServiceResponseでオブジェクトを作成しExceptionHandler、適切なコードを設定してオブジェクトを返すことができると思いましたServiceResponseServiceResponseただし、例外ハンドラーで型を返すことができない場合、これは不可能です。

編集

以下に示すように、ジェネリック例外クラスを使用してExceptionHandlerを使用してみました

@ExceptionHandler(ServiceException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
    public @ResponseBody resolveServiceValidationException(ServiceException ex) {       

        System.out.println("In resolveServiceError");

        ServiceResponse = new ServiceResponse();
        response.setResponseException(ex.getMessage());
        return response;        
    } 

例外はキャッチされていますが、ServiceResponseオブジェクトは常にnullです。私が得るのは次のメッセージだけです:

GET http://localhost:8080/myService/services/pingError returned a response status of 400 Bad Request

例外が返されたときに応答オブジェクトにアクセスするにはどうすればよいですか?

ありがとう

4

1 に答える 1

4
  1. @ExceptionHandlerアノテーションはクラスの配列をパラメーターとして受け取ることができるため、複数の例外に対して1つ(または複数)のハンドラーのみを作成できます。メソッドのシグネチャを変更して、処理されたすべての例外クラスの共通の祖先をパラメータとして取得します。線に沿った何か:

    @ExceptionHandler(value = {NullPointerException.class, AnotherException.class})
    @ResponseBody
    public String handleException1(Exception ex) {
        return ex.getMessage();
    }
    
  2. あなたの場合はString、で注釈を付けているので、になりますが@ResponseBody、返されたhttpコードをエラーコードに変更したい場合があります。あなたは追加することによってそれを行うことができます

    @ResponseStatus(value = HttpStatus.WHATEVER_CODE_YOU_WANT, reason = "Your message")` 
    

    例外ハンドラへの注釈。

  3. 呼び出しによって返されるhttpコードが、以上の場合300、ジャージクライアントはをスローしUniformInterfaceExceptionます。あなたはそれを捕まえて扱うことができます。この場合、変換の前に例外がスローされるため、応答タイプは重要ではありません。

アップデート

UniformInterfaceExceptionサーバーで例外ハンドラーを取得して変更し、応答本文として返されるようにしたらServiceResponse、次を使用して応答を取得できます。

ServiceResponse response = uniformInterfaceException.getResponse().getEntity(ServiceResponse.class);
于 2012-12-29T16:40:19.403 に答える