在Java專案中整合Scala
Scala是一個執行在Java JVM上的面向物件的語言。它支援函式程式設計,在語法上比Java更加靈活,同時通過Akka庫,Scala支援強大的基於Actor的多執行緒程式設計。具有這些優勢,使得我最近很想在一個新的專案中使用Scala,但是在新專案中,拋棄我們常用的Java和C#,而直接使用一門新的語言是很困難的。這不僅包括學習新語言這個過程,未來,更為專案的長期發展和日後的開發和支援增加了很多變數。畢竟一門新的語言是不可能在很短的時間內在行業中達到Java和C#的流行度的。
那麼,我們就不能在新專案中應用和實踐Scala麼?通過我的實踐,我發現其實我們可以通過簡單的Maven配置把Scala整合到我們現有的Java專案中。這樣我們可以很簡單得在Java專案中整合和使用Scala。在這篇blog裡,我給出一個用Scala實現的Hello World Servlet。專案的程式碼可以在
在開發之前,我們首先要配置Scala環境。我在Java開發中使用IntelliJ,首先,在IntelliJ中安裝Scala外掛。外掛安裝好後,我們重啟IntelliJ,這樣我們的執行環境就配置好了。
我們用IntelliJ新建一個Maven專案,新增如下Maven Dependency:
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId >scala-library</artifactId>
<version>2.10.1</version>
</dependency>
同時新增如下plugin:
[html]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8.1</version>
<configuration>
<includes>
<include>**/*.java</include>
<include>**/*.scala</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
這樣就完成了對我們的Java專案新增Scala的步驟。
在下面的Scala程式碼中,我們實現了一個簡單的Servlet返回Hello World:
package weblog.examples.scala
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.{RequestMapping, RequestMethod}
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
import java.io.OutputStream
import org.apache.log4j.Logger
import org.apache.commons.io.IOUtils
import HelloWorldServlet._
@Controller
class HelloWorldServlet {
@RequestMapping(value = Array("/"), method = Array(RequestMethod.GET))
def helloworld(request: HttpServletRequest, response: HttpServletResponse, outputStream: OutputStream) {
log.info("helloworld is called")
response.setStatus(HttpServletResponse.SC_OK)
IOUtils.write("HELLO WORLD!", outputStream)
outputStream.flush
outputStream.close
}
}
object HelloWorldServlet {
private var log: Logger = Logger.getLogger(classOf[HelloWorldServlet])
}
當這段程式碼通過編譯之後,就會生成和Java一樣的class檔案。我們可以看到,用Scala編寫的Servlet程式碼更加簡潔,這可以大大提高我們的程式設計效率。
由於Scala語言普及度的侷限,在專案中普及使用還是很有風險的。但是,在我們編寫Unit Test的過程中,我們可以很好的使用Scala來提高我們的程式設計效率。下面是一個用Scala寫的對我們的HelloWorldServlet進行測試的單元測試的例子:
```
package weblog.examples.scala
import org.springframework.web.servlet.DispatcherServlet
import org.springframework.mock.web.{MockServletConfig, MockHttpServletResponse, MockHttpServletRequest}
import org.junit.{Assert, Test, After, Before}
class HelloWorldServletTest {
private var dispatcherServlet : DispatcherServlet = _
private var httpRequest : MockHttpServletRequest = _
private var httpResponse : MockHttpServletResponse = _
@Before
def before() {
val config = new MockServletConfig
config.addInitParameter("contextConfigLocation", "classpath:servlet-context.xml")
dispatcherServlet = new DispatcherServlet
dispatcherServlet.init(config)
httpRequest = new MockHttpServletRequest
httpResponse = new MockHttpServletResponse
}
@After
def after() {
dispatcherServlet = null
httpRequest = null
httpResponse = null
}
@Test
def testHelloWord() {
httpRequest.setMethod("GET")
httpRequest.setRequestURI("/")
dispatcherServlet.service(httpRequest, httpResponse)
val response = httpResponse.getContentAsString
Assert.assertEquals("HELLO WORLD!", response)
}
}
這段程式碼,與Java相比較要簡潔很多,這可以大大提高我們的程式設計效率。
與完全基於Scala開發相比,這種Java與Scala的混合開發方式有以下幾個優勢:
專案本身還是基於Java的,可以很好的使用現有的Java工具,包括CI繼承,等
混合了Java和Scala,可以使程式設計師根據自己的需要在不同的情況下選擇更合適的語言
在專案未來的持續維護上,我們不需要使用Scala的專門程式設計師,即使是完全沒有Scala經驗的Java程式設計師,也可以進行程式碼維護
同時我們還可以用這種混合開發方式,對現有的Java專案進行修改,而不是完全的重寫。希望這種混合開發方式可以幫助希望使用Scala而又在工作中沒有機會的朋友。