Статьи

Scala Spring 4 MVC без конфигурации Web.XML со статической обработкой ресурсов

Этот пост полностью посвящен Scala и его использованию для разработки приложений JavaEE на основе Spring 4. Я изменю пример приложения, которое я использовал в своих сообщениях в блоге, ранее опубликованных в моем  личном блоге   (« Spring4Netty без конфигурации Web.XML на Java 8 ..  »).    

Spring Framework очень популярен в Java-земле, но использование Scala может дать ему крылья и перевести его на новый уровень опыта разработчиков. 

В примере приложения я использовал популярный AngularJS Framework для внешнего интерфейса. Мой личный опыт использования AngularJS для событийно-ориентированного приложения в Scala действительно положительный. Я считаю, что это намного «проще» (все еще много работы 🙂 и удобно понимать функциональность бэкэнда и интерфейса. 

Для создания нового примера приложения Spring 4 Scala я использовал следующие инструменты:

  • SBT  % 0,13,0
  • Весна4  % 4.0.6. РЕЛИЗ
  • Скала  % 2.10.3
  • Причал  % 9.1.0
  • Сервер Jetty можно легко заменить на Tomcat 7.

    Весь пример приложения был разработан в  IntelliJ IDEA 13.x  IDE. 

    После того, как мы создали проект SBT под IntelliJ, нам нужно импортировать некоторые плагины.

    Чтобы импортировать их, мы изменим настройку плагина sbt, изменив файл следующим образом. 

    addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "1.0.0-M4")
    
    addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")

    W е теперь добавлены два плагина:  xsbt-веб-плагин  и  SBT-идея Xsbt-веб-плагин  используется для создания веб — приложений предприятия. Оба они являются дополнением к инструменту построения SBT.

    Следующим шагом является добавление необходимых библиотечных зависимостей в   файл build.sbt . Поскольку мы также хотим связать статические ресурсы для фронт-энда, количество необходимых библиотек будет больше. 

    Build.sbt  файл будет выглядеть после нашей модификации в следующем примере.

    name := "miko-spring-scala"
    
    version := "1.0"
    
    scalaVersion := "2.11.2"
    
    libraryDependencies ++= Seq(
      "org.springframework" % "spring-webmvc" % "4.0.6.RELEASE",
      "org.springframework" % "spring-context" % "4.0.6.RELEASE",
      "org.springframework" % "spring-context-support" % "4.0.6.RELEASE",
      "javax.servlet" % "javax.servlet-api" % "3.0.1" % "provided",
      "javax.servlet" % "jstl" % "1.2" % "compile",
      "org.eclipse.jetty" % "jetty-webapp" % "9.1.0.v20131115" % "container, compile",
      "org.eclipse.jetty" % "jetty-jsp" % "9.1.0.v20131115" % "container"
    )
    jetty(port = 9090) 

    Когда приложение SBT будет готово, мы будем использовать команды для его запуска / остановки.

    //SBT console ...
    container:start
    container:stop
    //END SBT console

    Все библиотеки и плагины готовы, и мы можем приступить к созданию Spring4 Scala-приложения без использования  Web.XML  и со связанными статическими ресурсами для следующей внешней разработки.  Файл Web.xml будет выглядеть почти пустым в контрактах с конфигурацией XML.

    Структура пакета приложения очень похожа на предыдущие. Я хочу сохранить последовательность и получить возможность иметь ссылки на реализацию Java в случае возможного сравнения.

     

    Теперь я просто превращаю Java в Scala в несколько шагов
    1. Scala  WebConfig  будет выглядеть так:

    @Configuration
    @ComponentScan(basePackages = Array("miko.scala.helloexample"))
    @EnableWebMvc
    class WebConfig extends WebMvcConfigurerAdapter{
    
      override def addResourceHandlers(registry: ResourceHandlerRegistry) = {
        registry.addResourceHandler("/app/**").addResourceLocations("/app/").setCachePeriod(31550522)
      }
    
      override def configureDefaultServletHandling(configurer: DefaultServletHandlerConfigurer) = {
        configurer.enable()
      }
    
      @Bean
      def viewResolver = {
        val viewResolver = new InternalResourceViewResolver
        viewResolver.setViewClass(classOf[JstlView])
        viewResolver.setPrefix("/WEB-INF/pages/")
        viewResolver.setSuffix(".jsp")
        viewResolver
      }
    }

    2. Scala  WebInitializer поможет нам настроить ServletContext при запуске.

    class WebInitializer extends WebApplicationInitializer{
    
      override def onStartup(servletContext: ServletContext) = {
        val ctx = new AnnotationConfigWebApplicationContext
        ctx.register(classOf[WebConfig])
    
        ctx.setConfigLocation("META-INF/spring/app-spring-scala.xml")
    
        val servlet: Dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx))
        servlet.addMapping("/")
        servlet.setLoadOnStartup(1)
      }
    }

    3. Класс Scala  HelloExampleController,  аннотированный  @Contoller . Аннотация заботится о HttpServletRequest  и  Ответах . В этом примере контроллера также показано, как службы  @Autowired  при использовании языка Scala.

    @Controller
    @RequestMapping(Array("/"))
    class HelloExampleController @Autowired() (exampleService: ExampleService, exampleImportService: ExampleImportService){
    
      @RequestMapping(method =  Array(RequestMethod.GET))
      def hello( model: Model) = {
        model.addAttribute("message", "Here is Scala with ServiceName = " + exampleService.serviceName)
        model.addAttribute("importMessage", "Here is Scala with ServiceImportName = " + exampleImportService.name)
        "hello"
      }
    }

    4.  Пример Scala … Службы,  используемые  HelloExampleController  , выполняются поверх довольно мощной   реализации Traits . Черты очень похожи на Java Interfaces, но они допускают частичную реализацию, что делает их намного более мощными (вне области блога;). 

    trait ExampleImportService {
      def name: String
    }
    -----
    class ExampleImportServiceImpl extends ExampleImportService{
      override def name: String = "Imported service over XML"
    }

    После всех этих шагов у нас есть приложение Scala Spring 4 для тестирования. Кроме того, у нас также есть исходный код для сравнения с предыдущей реализацией Java 8.

    Scala делает большую работу, потому что мышление в функциях и намерениях обратного вызова делает всю разработку более простой. 
    Наслаждайтесь примером приложения!