Некоторое время назад я опробовал небольшой пример на основе Spring Boot с Scala в качестве языка и обнаружил, что комбинация работает довольно хорошо — никаких больших сюрпризов на самом деле нет, так как программы Scala в конечном итоге выполняются в JVM. Теперь я обновил образец последней версией Spring Boot и некоторыми из вспомогательных библиотек.
Чтобы очень быстро вернуться к примеру, это очень простое веб-приложение с пользовательским интерфейсом для управления доменным объектом «Отель», управляемым через JPA, представленным в scala следующим образом:
|
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
|
import javax.persistence.Idimport javax.persistence.GeneratedValueimport java.lang.Longimport javax.persistence.Entityimport scala.beans.BeanPropertyimport org.hibernate.validator.constraints.NotEmpty@Entityclass Hotel { @Id @GeneratedValue @BeanProperty var id: Long = _ @BeanProperty @NotEmpty var name: String = _ @BeanProperty @NotEmpty var address: String = _ @BeanProperty @NotEmpty var zip: String = _} |
JPA-аннотации переносятся довольно хорошо, одна морщина может быть дополнительной аннотацией @BeanProperty, хотя это требуется для реализаций JPA, поскольку это заставляет компилятор scala генерировать обычные геттеры и установщики типа Java Beans вместо геттеров и сеттеров по умолчанию для scala, которые не ‘ следовать соглашениям Java Bean.
Spring Data делает смехотворно простым управление этим типом домена, все что ему требуется — это интерфейс маркера, который генерирует реализацию во время выполнения:
|
1
2
3
4
5
|
import org.springframework.data.repository.CrudRepositoryimport mvctest.domain.Hotelimport java.lang.Longtrait HotelRepository extends CrudRepository[Hotel, Long] |
Теперь у меня есть набор инструментов для управления доменом отеля:
|
01
02
03
04
05
06
07
08
09
10
11
|
//save or update a hotelhotelRepository.save(hotel)//find one hotelhotelRepository.findOne(id)//find all hotelsval hotels = hotelRepository.findAll()//delete a hotelhotelRepository.delete(id) |
И, наконец, контроллер для управления потоком пользовательского интерфейса с этим хранилищем:
|
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
|
@Controller@RequestMapping(Array("/hotels"))class HotelController @Autowired()(private val hotelRepository: HotelRepository) { @RequestMapping(method = Array(RequestMethod.GET)) def list(model: Model) = { val hotels = hotelRepository.findAll() model.addAttribute("hotels", hotels) "hotels/list" } @RequestMapping(Array("/edit/{id}")) def edit(@PathVariable("id") id: Long, model: Model) = { model.addAttribute("hotel", hotelRepository.findOne(id)) "hotels/edit" } @RequestMapping(method = Array(RequestMethod.GET), params = Array("form")) def createForm(model: Model) = { model.addAttribute("hotel", new Hotel()) "hotels/create" } @RequestMapping(method = Array(RequestMethod.POST)) def create(@Valid hotel: Hotel, bindingResult: BindingResult) = { if (bindingResult.hasErrors()) { "hotels/create" } else { hotelRepository.save(hotel) "redirect:/hotels" } } @RequestMapping(value = Array("/update"), method = Array(RequestMethod.POST)) def update(@Valid hotel: Hotel, bindingResult: BindingResult) = { if (bindingResult.hasErrors()) { "hotels/edit" } else { hotelRepository.save(hotel) "redirect:/hotels" } } @RequestMapping(value = Array("/delete/{id}")) def delete(@PathVariable("id") id: Long) = { hotelRepository.delete(id) "redirect:/hotels" }} |
Здесь также есть некоторые недостатки, но в основном они должны иметь смысл: способ автоматического подключения хранилища немного неинтуитивен, и способ предоставления явного типа Array для путей и методов отображения запросов может сбивать с толку.
Помимо этих небольших проблем, код просто работает, играйте с ним, я хотел бы получить любые отзывы о способах улучшения этого образца. Вот расположение git этого образца .
| Ссылка: | Spring Boot со Scala от нашего партнера JCG Биджу Кунджуммен в блоге « Все и вся» . |