SpringMVC, где разместить общий код между методами контроллера - PullRequest
0 голосов
/ 28 января 2019

Я работаю над существующей кодовой базой и вижу этот шаблон во всех методах контроллера.В начале объявляются одни и те же переменные, и код помещается в блок try catch, который также одинаков для всех методов.Мне было интересно, есть ли способ протолкнуть общий код между методами внутри BaseController.Так что мне не нужно объявлять общие переменные внутри каждого метода, а функциональность блока try catch также делегируется в другое место.

Сначала я создал класс BaseController, аннотировал его аннотацией @Controller ирасширил мой контроллер, чтобы стать его подклассом.Затем я переместил все общие переменные в BaseController.Проблема в том, что, как только я изменяю эти переменные внутри метода контроллера, они сохраняют свои значения даже в следующем запросе, что проблематично.

@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public ResponseEntity delete(@PathVariable("id") Integer id)
{
    HashMap response = new HashMap();
    boolean success = false;
    List errors = new ArrayList();
    HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
    String message = "";
    try
    {
        purchaseInvoiceService.delete(id);
        success = true;
        message = "Purchase Invoice Deleted";
        httpStatus = HttpStatus.OK;

    } catch (Exception e)
    {
        errors.add(new ErrorMessage("error", e.getMessage()));
        e.printStackTrace();
    }

    response.put("success", success);
    response.put("errors", errors);
    response.put("message", message);
    return new ResponseEntity(response, httpStatus);
}

Я хочу реорганизовать этот шаблон так, чтобы в каждом методе я просто имелсодержать только вызов службы и условно устанавливать переменную success и httpstatus (присутствующую в BaseController), а затем возвращая ответ, используя метод response (), присутствующий в BaseController, который добавляет переменную данных, а тип ее возврата - ResponseEntity.

Редактировать 1: эта конечная точка возвращает список всех счетов на покупку, в настоящее время она просто возвращает HashMap, который преобразуется в JSON.Я пытаюсь подчеркнуть, что эти ответы, успехи, ошибки, переменные httpStatus и часть, где все эти переменные помещаются в ответ HashMap (), являются частью каждого метода внутри каждого контроллера.Я хотел бы изменить их на что-то похожее на ResponseFactory.Поэтому я думаю передать список в ResponseFactory, который затем структурирует все ответы и возвращает их в форме ResponseEntity.Просто хочу знать, правильно ли я это делаю.

@RequestMapping(method = RequestMethod.GET)
    public ResponseEntity getAll() {
        HashMap response = new HashMap();
        boolean success = false;
        List errors = new ArrayList();
        HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
        String message = "";
        Map data = new HashMap();

        try {
            List<PurchaseInvoice> purchaseInvoices = purchaseInvoiceService.getAll();
            data.put("purchaseInvoices", purchaseInvoices);
            success = true;
            message = "Purchase Invoice List";
            httpStatus = httpStatus.OK;
        } catch (Exception e) {
            errors.add(new ErrorMessage("error", e.getMessage()));
            e.printStackTrace();
        }

        response.put("success", success);
        response.put("errors", errors);
        response.put("message", message);
        response.put("data", data);
        return new ResponseEntity(response, httpStatus);
    }

1 Ответ

0 голосов
/ 28 января 2019

Ваша фраза: "Тогда я переместил все общие переменные в BaseController" звучит сбивающим с толку.

Контроллер весной - это всего лишь Singleton с дополнительной «способностью», предоставляемой пружиной: это то, что отображается как веб-конечная точка (менее актуально для вашего конкретного вопроса).

Быть одиночным означает, что в ApplicationContext есть один экземпляр.

Так что, если переменные были перемещены какthis:

 class BaseController {
       protected Field1 field1;
       protected Field2 field2;
        ....
 }

Тогда, безусловно, существует проблема, вы фактически ввели состояние для контроллера, и это состояние является общим для всех запросов.

Короче говоря, не создавайте контроллеры с состоянием

Сказав, что идея рефакторинга хороша.Просто способ рефакторинга, вероятно, неправильный:

Вместо этого я предлагаю рассмотреть следующий рефакторинг:

Создать класс responseFactory с некоторыми статическими методами:

class ResponseFactory {
     public static ResponseEntity success(String message) {
         here prepare the map with boolean success and everything
     }
}

Теперьконтроллер становится:

class Controller {

    public ResponseEntity delete(@PathVariable("id") Integer id) {
           purchaseInvoiceService.delete(id); // I'll talk about exceptions later
           return ResponseEntityFactory.success("Purchase Invoice Deleted");
    }
}

Теперь, что касается исключений - это несколько сбивает с толку - код в основном говорит, что ответ будет успешным несмотря на ошибок.Поэтому, если вам нужно оставить это так, ResponseEntityFactory должен будет также получить список ошибок или что-то в этом роде, но в целом Spring имеет довольно мощный механизм обработки исключений для сопоставления исключений, генерируемых в бэкэнде (сервис, DAO,что угодно) к значимому ответу, не относящемуся к 200.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...