Статьи

Spring MVC: REST-приложение с CNVR vol.

В предыдущем посте я сделал краткий обзор настройки среды для проекта Spring MVC REST с CNVR. В этой части я могу сосредоточиться непосредственно на контроллере и демонстрации службы REST. Как обычно, я собираюсь сделать краткое введение, и после этого я рассмотрю методы контроллера и объясню все важные моменты.

Поскольку в дальнейшем я расскажу о службе REST, мне нужно сказать несколько предложений об основных понятиях REST. Вы, наверное, слышали раньше о сайтах, которые предоставляют API для использования их функциональности. Это становится возможным с помощью REST или SOAP, но в этой статье я расскажу о REST.

Например, вы хотите разработать приложение для университетской библиотеки, которое будет работать со студентами и книгами. Вы можете реализовать все контроллеры, используя REST. Это решение сделает ваше приложение открытым для совместной работы с другими приложениями, которые могут использовать API приложения. Для получения дополнительной информации о функциях REST вам необходимо посетить специальные сайты .

Spring MVC REST контроллер

Приложение для смартфона ориентировано на HTTP-клиентов, таких как браузеры и JSON-клиенты. Формат JSON может использоваться различными типами клиентов, но теперь это не имеет значения.

Давайте рассмотрим весь код контроллера:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
@Controller
@RequestMapping(value="/smartphones")
public class SmartphoneController {
 
    @Autowired
    private SmartphoneService smartphoneService;
 
    @RequestMapping(value="/create", method=RequestMethod.GET)
    public ModelAndView createSmartphonePage() {
        ModelAndView mav = new ModelAndView("phones/new-phone");
        mav.addObject("sPhone", new Smartphone());
        return mav;
    }
 
    @RequestMapping(value="/create", method=RequestMethod.POST)
    public ModelAndView createSmartphone(@ModelAttribute Smartphone smartphone,
            final RedirectAttributes attributes) {
        ModelAndView mav = new ModelAndView("redirect:/index.html");
        createSmartphone(smartphone);
        attributes.addFlashAttribute("msg", "New Smartphone "+smartphone+" was successfully created.");
        return mav;
    }
 
    @RequestMapping(value="/create", method=RequestMethod.POST,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public Smartphone createSmartphone(@RequestBody Smartphone smartphone) {
        return smartphoneService.create(smartphone);
    }
 
    @RequestMapping(value="/edit/{id}", method=RequestMethod.GET)
    public ModelAndView editSmartphonePage(@PathVariable int id) {
        ModelAndView mav = new ModelAndView("phones/edit-phone");
        Smartphone smartphone = smartphoneService.get(id);
        mav.addObject("sPhone", smartphone);
        return mav;
    }
 
    @RequestMapping(value="/edit/{id}", method=RequestMethod.PUT,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public Smartphone editSmartphone(@PathVariable int id,
            @RequestBody Smartphone smartphone) {
        smartphone.setId(id);
        return smartphoneService.update(smartphone);
    }
 
    @RequestMapping(value="/edit/{id}", method=RequestMethod.PUT)
    public ModelAndView editSmartphone(@PathVariable int id,
            @ModelAttribute Smartphone smartphone,
            final RedirectAttributes attributes) {
        ModelAndView mav = new ModelAndView("redirect:/index.html");
        editSmartphone(id, smartphone);
        attributes.addFlashAttribute("msg", "The Smartphone "+smartphone+" was successfully updated.");
        return mav;
    }
 
    @RequestMapping(value="/delete/{id}", method=RequestMethod.DELETE,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public Smartphone deleteSmartphone(@PathVariable int id) {
        return smartphoneService.delete(id);
    }
 
    @RequestMapping(value="/delete/{id}", method=RequestMethod.GET)
    public ModelAndView deleteSmartphone(@PathVariable int id,
            final RedirectAttributes attributes) {
        ModelAndView mav = new ModelAndView("redirect:/index.html");
        Smartphone deletedSphone = deleteSmartphone(id);
        attributes.addFlashAttribute("msg", "The Smartphone "+deletedSphone+" was successfully deleted.");
        return mav;
    }
 
    @RequestMapping(value="", method=RequestMethod.GET,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public List< Smartphone > allPhones() {
        return smartphoneService.getAll();
    }
 
    @RequestMapping(value="", method=RequestMethod.GET)
    public ModelAndView allPhonesPage() {
        ModelAndView mav = new ModelAndView("phones/all-phones");
        List< Smartphone > smartphones = new ArrayList< Smartphone >();
        smartphones.addAll(allPhones());
        mav.addObject("smartphones", smartphones);
        return mav;
    }
 
}

Контроллер смартфона действительно многословен и имеет множество методов. В пуске контроллера вы можете увидеть автосервисный смартфон- сервис. В свою очередь, смартфон-сервис имеет пять способов:

  • создание общедоступного смартфона (Smartphone sp);
  • общедоступный смартфон get (Integer id);
  • общедоступный список <Smartphone> getAll ();
  • общедоступное обновление смартфона (Smartphone sp) выдает SmartphoneNotFoundException;
  • общедоступное удаление смартфона (целочисленный идентификатор) создает исключение SmartphoneNotFoundException;

Каждый метод в контроллере соответствует определенному методу службы. Итак, давайте рассмотрим это соответствие в следующих разделах.

ОТДЫХ: СОЗДАТЬ

Следующий фрагмент кода отвечает за создание новой сущности смартфона:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
...
    @RequestMapping(value="/create", method=RequestMethod.POST)
    public ModelAndView createSmartphone(@ModelAttribute Smartphone smartphone,
            final RedirectAttributes attributes) {
        ModelAndView mav = new ModelAndView("redirect:/index.html");
        createSmartphone(smartphone);
        attributes.addFlashAttribute("msg", "New Smartphone "+smartphone+" was successfully created.");
        return mav;
    }
 
    @RequestMapping(value="/create", method=RequestMethod.POST,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public Smartphone createSmartphone(@RequestBody Smartphone smartphone) {
        return smartphoneService.create(smartphone);
    }
...

Первый способ — это простой контроллер Spring MVC. В предыдущих постах я несколько раз объяснял, как работать с контроллерами Spring MVC. Но вы можете заметить, что метод необычен, потому что он содержит вызов второго метода. Второй метод — это метод REST со стандартными аннотациями REST: @ResponseBody и @RequestBody .

Когда вы отправляете форму с данными о новом смартфоне на «../smartphones/create.html» для обработки, распознаватель просмотра согласования содержимого определяет, что вам нужно получить HTML-страницу. В случае, если вы позвоните по URL «../smartphones/create.json», вы получите обратно документ JSON. Потому что я указал в WebAppConfig, что CNVR нужно принимать решение на основе URL-суффикса.

Вы можете спросить: Так в чем же причина использования CNVR, если нам все еще нужно создать несколько методов для одной и той же операции? Предположим, что приложение для смартфона должно поддерживать 2 дополнительных типа контента: XML и PDF. В этом случае CNVR сделает нашу жизнь проще, и мы не будем разрабатывать дополнительные методы, просто добавим соответствующие средства разрешения представления в WebAppConfig . Ситуация станет идеальной, если мы начнем использовать AJAX в приложении. Это означает, что мы можем исключить методы, которые возвращают объекты ModelAndView .

ОТДЫХ: ПОЛУЧИТЬ ВСЕ ЗАПИСИ

В предыдущем параграфе я сделал подробный обзор принципов CNVR на практике. Поэтому сейчас я просто опубликую конкретные фрагменты кода, которые соответствуют соответствующей операции.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
...
    @RequestMapping(value="", method=RequestMethod.GET,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public List< Smartphone > allPhones() {
        return smartphoneService.getAll();
    }
 
    @RequestMapping(value="", method=RequestMethod.GET)
    public ModelAndView allPhonesPage() {
        ModelAndView mav = new ModelAndView("phones/all-phones");
        List< Smartphone > smartphones = new ArrayList< Smartphone >();
        smartphones.addAll(allPhones());
        mav.addObject("smartphones", smartphones);
        return mav;
    }
...

Эти методы отвечают за получение списка смартфонов.

ОТДЫХ: ОБНОВЛЕНИЕ

Вот методы, которые выполняют обновление существующего смартфона.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
...
    @RequestMapping(value="/edit/{id}", method=RequestMethod.PUT,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public Smartphone editSmartphone(@PathVariable int id,
            @RequestBody Smartphone smartphone) {
        smartphone.setId(id);
        return smartphoneService.update(smartphone);
    }
 
    @RequestMapping(value="/edit/{id}", method=RequestMethod.PUT)
    public ModelAndView editSmartphone(@PathVariable int id,
            @ModelAttribute Smartphone smartphone,
            final RedirectAttributes attributes) {
        ModelAndView mav = new ModelAndView("redirect:/index.html");
        editSmartphone(id, smartphone);
        attributes.addFlashAttribute("msg", "The Smartphone "+smartphone+" was successfully updated.");
        return mav;
    }
...

ОТДЫХ: УДАЛИТЬ

Вот методы, которые выполняют удаление существующего смартфона.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
...
    @RequestMapping(value="/delete/{id}", method=RequestMethod.DELETE,
            produces = "application/json", consumes = "application/json")
    @ResponseBody
    public Smartphone deleteSmartphone(@PathVariable int id) {
        return smartphoneService.delete(id);
    }
 
    @RequestMapping(value="/delete/{id}", method=RequestMethod.GET)
    public ModelAndView deleteSmartphone(@PathVariable int id,
            final RedirectAttributes attributes) {
        ModelAndView mav = new ModelAndView("redirect:/index.html");
        Smartphone deletedSphone = deleteSmartphone(id);
        attributes.addFlashAttribute("msg", "The Smartphone "+deletedSphone+" was successfully deleted.");
        return mav;
    }
...

Резюме

Я надеюсь, что эта часть была ясна для вас. Определенно, вам нужно иметь базовые знания о Spring и REST, чтобы полностью понять эту статью. Не игнорируйте ссылки, которые я поместил в статье для получения дополнительной информации. В третьей части я собираюсь продемонстрировать, как работает это приложение.

Ссылка: Spring MVC: приложение REST с CNVR vol. 2 от нашего партнера JCG Алексея Зволинского в блоге заметок Фрузенштейна .