一文詳解springboot平臺上的scala語言與實現微信公衆號推送功能

1什麼是springboot框架?

springboot是目前最流行的開箱即用的框架,該框架的目的是爲了幫助開發人員減化配置,提高開發人員的速度等等。具體自行百度,今天的主角可不是它,今天寫這遍文章的目的是整合scala語言在springboot當中。

2 什麼是scala語言?

相信從java8開始,大家就注意到了java的開發風格已經越來越接近scala這門語言,那麼scala編程語言究竟有怎樣的魅力?通過scala語言官網我們可以知道這是一門與java相同運行在jvm上的高級語言。
官方介紹:

Scala combines object-oriented and functional programming in one
concise, high-level language. Scala’s static types help avoid bugs in
complex applications, and its JVM and JavaScript runtimes let you
build high-performance systems with easy access to huge ecosystems of
libraries.

通過這個介紹我們大概就可以知道scala是一門函數式編程語言,相信接觸過java8開發的同學都知道函數式編程的巧妙之處了。scala具體有多牛逼就自行百度啦。

3 how to do 怎麼去使用它?

扯了這麼多終於奔入主題啦
首先和java相同導入maven依賴

maven依賴:(注意安裝依賴環境之前請確保已經安裝了idea plugins支持scala 的插件)

<modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <!--定義項目相關的版本號-->
    <properties>
        <java.version>1.8</java.version>
		<lombok.version>1.18.6</lombok.version>
		<scala.version>2.12.4</scala.version>
        <scala.maven.version>3.3.1</scala.maven.version>
        <scala.complie.version>0.9.0</scala.complie.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <!-- Need this to compile JSP -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <!--spring-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
		<!-- lombok-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>${lombok.version}</version>
			<scope>provided</scope>
		</dependency>
		<!-- scala -->
		<dependency>
			<groupId>org.scala-lang</groupId>
			<artifactId>scala-library</artifactId>
			<version>${scala.version}</version>
		</dependency>
		<!--scala.complie-->
		<dependency>
			<groupId>org.scala-lang.modules</groupId>
			<artifactId>scala-java8-compat_2.12</artifactId>
			<version>${scala.complie.version}</version>
		</dependency>
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>${scala.maven.version}</version>
                <executions>
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <scalaVersion>${scala.version}</scalaVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>aliyun</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>aliyun</id>
            <name>aliyun</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <layout>default</layout>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

4.編寫一個簡單的hello wolrd網頁?

application文件的配置:

server.port=8888

同java相似 我們也創建相應的controller來測試一下吧
創建IndexController.scala文件 注意是scala文件不要創建成java了

編寫代碼:(注意scala的requestMapping只接受Array())

package com.example.demo.controller

import org.springframework.web.bind.annotation.{RequestMapping, RestController}

@RestController
@RequestMapping(Array("/"))
class IndexController {
  @RequestMapping(Array("/welcome"))
  def welcome() = {
    "hello scala!!!"
  }
}

5 簡單測試一下?

在這裏插入圖片描述
測試沒問題啦。

6 如何注入service 層?

service層代碼:(需要導入springboot-web模塊)

@Service
class UserService {
  def query(): Array[Int] = {
    val array = Array[Int](3, 4, 5)
    array
  }
}

controller層代碼

  @ResponseBody
  @RequestMapping(Array("/userList"))
  def userList() = {
    val list = userService.query()
    for (ele <- list) println(ele)
    "userList"
  }

7 什麼這些還不夠? 從項目的角度開發?

從零到一開發一個微信公衆號推送demo?
導入項目相關的maven 這裏推薦使用(com.github.binarywang)這個開源項目進行公衆號開發

 <dependency>
        <groupId>com.github.binarywang</groupId>
        <artifactId>weixin-java-mp</artifactId>
        <version>${weixin-java-mp.version}</version>
    </dependency>
    <!--fashjson工具類-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>${fastjson.version}</version>
    </dependency>

實體類:

AccessToken
package com.example.demo.pojo

case class AccessToken(access_token:String,expires_in:String){

}

service 類:

package com.example.demo.service

import java.io.IOException
import java.net.{MalformedURLException, URL, URLConnection}
import java.security.{MessageDigest, NoSuchAlgorithmException}
import java.util.Optional
import com.alibaba.fastjson.JSON
import com.example.demo.CommonUtils
import com.example.demo.pojo.AccessToken
import lombok.extern.slf4j.Slf4j
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.{Component, Service}

@Slf4j
@Service
@Component
class WxServiceScala {
  var GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"
  var TOKEN: String = _
  var APPID: String = _
  var APPSECRET: String = _
  var APPKEY: String = _
  var ac: AccessToken = _
  /**
   * 未來的過期時間
   */
  var futureExpireTime: Optional[Long] = _;

  @Value(value = "${wx.token}") def setTOKEN(token: String): Unit = {
    TOKEN = token
  }

  @Value(value = "${wx.appId}") def setAPPID(appId: String): Unit = {
    APPID = appId
  }

  @Value(value = "${wx.appSecret}") def setAPPSECRET(appsecret: String): Unit = {
    APPSECRET = appsecret
  }

  def checkSign(timestamp: String, nonce: String, echostr: String, signature: String): Boolean = {
    val array = Array[String](TOKEN, timestamp, nonce)
    val str = new StringBuilder
    for (elem <- array.sorted) {
      elem -> {}
      str.append(elem);
    }
    sha1(str.toString()).eq(signature);
  }

  /**
   * 獲取token值
   */
  def getToken(): Unit = {
    println("===APPID===" + APPID + "======APPSECRET===" + APPSECRET + "========")
    val url = GET_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET)
    val str = get(url)
    println("str" + str)
    val accessToken = JSON.parseObject(str, classOf[AccessToken])
    futureExpireTime = Optional.of(System.currentTimeMillis + accessToken.expires_in.toInt * 1000)
    ac = accessToken
    println(ac.toString)
    println("======futureExpireTime=====未來過期時間==" + futureExpireTime)
  }

  /**
   * 判斷當前時間過期了嗎
   *
   * @return
   */
  def isExpired: Boolean = System.currentTimeMillis > futureExpireTime.orElse(0L)

  /**
   * 獲取token值 有效期目前爲2個小時
   *
   * @return
   */
  def getAccessToken: String = {
    if (ac == null || isExpired) getToken()
    ac.access_token
  }

  def sha1(src: String): String = {
    try {
      val md = MessageDigest.getInstance("sha1")
      val digest = md.digest(src.getBytes)
      val chars = Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')
      val sb = new StringBuilder
      for (b <- digest) {
        sb.append(chars((b >> 4) & 15))
        sb.append(chars(b & 15))
      }
      return sb.toString
    } catch {
      case e: NoSuchAlgorithmException =>
        e.printStackTrace()
    }
    null
  }

  /**
   * @param url
   * @return
   */
  def get(url: String): String = {
    try {
      val urlObj = new URL(url)
      val connection = urlObj.openConnection
      val is = connection.getInputStream
      val b = new Array[Byte](1024)
      var len = 0
      val sb = new StringBuilder
      while ( {
        (len = is.read(b)) != -1
      }) sb.append(new String(b, 0, len))
      return sb.toString
    } catch {
      case e: MalformedURLException =>
        e.printStackTrace()
      case e: IOException =>
        e.printStackTrace()
    }
    null
  }
}

用於認證測試的controller類

package com.example.demo.controller

import com.example.demo.service.WxServiceScala
import javax.servlet.http.HttpServletRequest
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.{GetMapping, PostMapping, RequestMapping, RestController}

@RestController
@RequestMapping(Array("/wechat/scala"))
class WeChatAuthController @Autowired()(wxService: WxServiceScala) {
  @GetMapping(Array(""))
  def auth(signature: String, timestamp: String, nonce: String, echostr: String): String = {
    println("======signature=======" + signature)
    println("======timestamp=======" + timestamp)
    println("======nonce=======" + nonce)
    println("======echostr=======" + echostr)
    if (wxService.checkSign(timestamp, nonce, echostr, signature)) {
      return echostr
    }
    "error"
  }
  @PostMapping(Array(""))
  def getMessage(req: HttpServletRequest): Unit ={
    req.setCharacterEncoding("UTF-8")
    println("response post")
  }
}

yml文件 填上自己的微信公衆號配置

server:
  port: 8888
wx.token:

wx.appId:

wx.appSecret:

如何調用模版接口?(以java爲案例,後續會附上scala版的)
注意:微信公衆號測試模版接口需要在測試頁面申請模版Id
在這裏插入圖片描述

在這裏插入圖片描述

        WxMpDefaultConfigImpl wxStorage = new WxMpDefaultConfigImpl();
        wxStorage.setAccessToken(wxService.getAccessToken());
        wxStorage.setAppId(WxService.APPID);
        wxStorage.setAesKey(WxService.APPKEY);
        wxStorage.setSecret(WxService.APPSECRET);
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxStorage);
   WxMpTemplateMessage templateMessage = WxMpTemplateMessage
                                .builder()
                                // 接收者openid
                                .toUser(wechatId)
                                // 模板id
                                .templateId(Constants.WECHAT_TEMPLATE_ID)
                                .miniProgram(new WxMpTemplateMessage.MiniProgram())
                                // 模板跳轉鏈接 跳轉到微信小程序
                                .build();
                        // 添加模板數據
                        templateMessage.addData(new WxMpTemplateData("first", "", "#000000"))
                                .addData(new WxMpTemplateData("keyword1", “”, "#000000"))
                                .addData(new WxMpTemplateData("keyword2", “").format(new Date()), "#000000"))
                                .addData(new WxMpTemplateData("remark", “”, "#ff0000"));
                            String result = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);

在這裏插入圖片描述

代碼在哪?(地址附上):https://github.com/RAOE/scalaDemo.git
由於本文作者水平有限,筆誤之處歡迎指正。謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章