Spring MVC: как вернуть другой тип в тело ResponseEntity

В моем обработчике запросов я хочу сделать некоторую проверку и на основании результатов проверки проверки вернусь к другому ответу (успех/ошибка). Поэтому я создаю абстрактный класс для объекта ответа и делаю 2 подкласса для случая отказа и успешного случая. Код выглядит примерно так, но он не компилируется, жалуясь, что errorResponse и successResponse не могут быть преобразованы в AbstractResponse.

Я новичок в Java Generic и Spring MVC, поэтому я не знаю простого способа решить эту проблему.

@ResponseBody ResponseEntity<AbstractResponse> createUser(@RequestBody String requestBody) {
    if(!valid(requestBody) {
        ErrorResponse errResponse = new ErrorResponse();
        //populate with error information
        return new ResponseEntity<> (errResponse, HTTPStatus.BAD_REQUEST);
    }
    createUser();
    CreateUserSuccessResponse successResponse = new CreateUserSuccessResponse();
    // populate with more info
    return new ResponseEntity<> (successResponse, HTTPSatus.OK);
}

Ответ 1

Здесь есть две проблемы:

  • ваш тип возврата должен быть изменен в соответствии с двумя подклассами ответа ResponseEntity<? extends AbstractResponse>
  • когда вы создаете экземпляр ResponseEntity, вы не можете использовать упрощенный синтаксис < > , который вы должны указать, какой класс ответа вы собираетесь использовать new ResponseEntity<ErrorResponse> (errResponse, HTTPStatus.BAD_REQUEST);

    @ResponseBody ResponseEntity<? extends AbstractResponse> createUser(@RequestBody String requestBody) {
        if(!valid(requestBody) {
            ErrorResponse errResponse = new ErrorResponse();
            //populate with error information
            return new ResponseEntity<ErrorResponse> (errResponse, HTTPStatus.BAD_REQUEST);
        }
        createUser();
        CreateUserSuccessResponse successResponse = new CreateUserSuccessResponse();
        // populate with more info
        return new ResponseEntity<CreateUserSuccessResponse> (successResponse, HTTPSatus.OK);
    }
    

Ответ 2

Другим подходом будет использование обработчиков ошибок

@ResponseBody ResponseEntity<CreateUserSuccessResponse> createUser(@RequestBody String requestBody) throws UserCreationException {
    if(!valid(requestBody) {
        throw new UserCreationException(/* ... */)
    }
    createUser();
    CreateUserSuccessResponse successResponse = new CreateUserSuccessResponse();
    // populate with more info
    return new ResponseEntity<CreateUserSuccessResponse> (successResponse, HTTPSatus.OK);
}

public static class UserCreationException extends Exception {
    // define error information here
}

@ExceptionHandler(UserCreationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorResponse handle(UserCreationException e) {
    ErrorResponse errResponse = new ErrorResponse();
    //populate with error information from the exception
    return errResponse;
}

Этот подход позволяет возвращать какой-либо объект, поэтому абстрактный суперкласс для случая успеха и случая ошибки (или даже случаев) больше не нужен.