1. 程式人生 > >SpringBoot迷你微信小程式

SpringBoot迷你微信小程式

SpringBoot+MyBatis搭一個簡單的後臺API介面給前臺微信小程式使用

假定一個簡單的CRUD業務:管理一個區域列表,對其增刪該查。
效果:
這裡寫圖片描述

專案取名為:demo_springboot

初始化專案結構:

這裡寫圖片描述
- config :spring java config配置
- dao:資料庫訪問介面
- entity:資料庫物件實體
- handler:異常處理等。。
- service:業務層
- web:檢視控制層
DemoSpringbootApplication:SpringBoot啟動類

後臺介面

mysql資料庫表:簡單點,就一個,語句如下:

CREATE TABLE `tb_area` (
  `area_id` int(2) NOT NULL AUTO_INCREMENT,
  `area_name` varchar(255) NOT NULL COMMENT '區域名',
  `priority` int(11) NOT NULL DEFAULT '0' COMMENT '優先順序',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
  `update_time` timestamp NOT NULL DEFAULT
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間', PRIMARY KEY (`area_id`), UNIQUE KEY `UK_AREA` (`area_name`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

dao、mapper檔案以及entity實體,使用mybatis generator逆向工程生成,就簡單的增刪查改,不再囉嗦。
只在dao裡增加一個列表查詢介面:

 List<TbArea> queryArea();

對於xml的sql:

<select id="queryArea" resultType="com.kay.entity.TbArea">
    SELECT <include refid="Base_Column_List" />
    FROM tb_area
    ORDER BY priority
  </select>

簡單的pom.xml 依賴,這裡就用c3p0連線池好了:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.kay</groupId>
    <artifactId>demo_springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>demo_springboot</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>

        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Spring配置,為了複習一下基礎,這裡就不簡化配置了,直接寫在java config裡面:

手擼 datasource

package com.kay.config.dao;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * Created by kay on 2018/3/16.
 */
@Configuration
@MapperScan("com.kay.dao")
public class DataSourceConfiguration {

    @Value("${jdbc.driver}")
    private String jdbcDriverClass;

    @Value("${jdbc.url}")
    private String jdbcUrl;

    @Value("${jdbc.user}")
    private String jdbcUser;

    @Value("${jdbc.password}")
    private String jdbcPwd;

    @Bean(name="dataSource")
    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(jdbcDriverClass);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setUser(jdbcUser);
        dataSource.setPassword(jdbcPwd);
        dataSource.setAutoCommitOnClose(false);
        return dataSource;
    }

}
package com.kay.config.dao;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * Created by kay on 2018/3/16.
 */
@Configuration
public class SqlSessionFacoryConfiguration {

    @Value("${mybatis_config_file}")
    private String mybatisConfigPath;

    @Value("${mapper_path}")
    private String mapperPath;

    @Value("${entity_package}")
    private String entityPackage;

    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;

    @Bean("sqlSessionFactory")
    public SqlSessionFactoryBean creatSqlSessionFactory() throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigPath));
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        String packSearchPath = PathMatchingResourcePatternResolver.CLASSPATH_URL_PREFIX;
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(packSearchPath+mapperPath));
        sqlSessionFactoryBean.setTypeAliasesPackage(entityPackage);
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }
}

Service也沒什麼好說了的,就是CRUD,直接貼Controller的介面吧:

package com.kay.web;

import com.kay.entity.TbArea;
import com.kay.service.AreaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by kay on 2018/3/16.
 */
@RestController
@RequestMapping("/superadmin")
public class AreaController {

    @Autowired
    private AreaService areaService;

    /**
     * 列表查詢
     * @return
     */
    @RequestMapping(value = "/listarea",method = RequestMethod.GET)
    private Map<String, Object> listArea() {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        List<TbArea> areas = areaService.queryArea();
        modelMap.put("areaList", areas);
        return modelMap;
    }

    /**
     * areaid 查詢
     * @param areaId
     * @return
     */
    @RequestMapping(value = "/getareabyid",method = RequestMethod.GET)
    private Map<String, Object> getAreaById(Integer areaId) {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        TbArea area = areaService.selectByPrimaryKey(areaId);
        modelMap.put("area", area);
        return modelMap;
    }

    /**
     * 新增area
     * @param area
     * @return
     */
    @RequestMapping(value = "/addarea",method = RequestMethod.POST)
    private Map<String, Object> addArea(@RequestBody TbArea area) {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        boolean isSuccess = areaService.insert(area);
        modelMap.put("success", isSuccess);
        return modelMap;
    }

    /**
     * 修改
     * @param area
     * @return
     */
    @RequestMapping(value = "/modifyarea",method = RequestMethod.POST)
    private Map<String, Object> modifyArea(@RequestBody TbArea area) {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        boolean b = areaService.updateByPrimaryKeySelective(area);
        modelMap.put("success", b);
        return modelMap;
    }

    /**
     * 刪除area
     * @param areaId
     * @return
     */
    @RequestMapping(value = "/removearea",method = RequestMethod.GET)
    private Map<String, Object> removeArea(Integer areaId) {
        Map<String, Object> modelMap = new HashMap<String, Object>();
        boolean isSuccess = areaService.deleteByPrimaryKey(areaId);
        modelMap.put("success", isSuccess);
        return modelMap;
    }
}

好的,現在我們所有介面都有了,用 postman測試一下通過後,開始來寫小程式。

迷你小程式

下載好微信開發者工具,掃碼進入:
小程式的開發語法非常類似於 Vue,所以開發起來也很直觀。
結構:
這裡寫圖片描述
新建的2個page就是我們主要開發的地方(右鍵pages選擇新建page,類似於建了一個元件)
- list:列表頁
- operation:操作,新增、編輯、刪除

list.js頁面展示回撥函式裡面,呼叫我們剛才寫好的後臺列表介面:

/**
   * 生命週期函式--監聽頁面顯示
   */
  onShow: function () {
    var that=this;
    wx.request({
      url: 'http://127.0.0.1:8081/superadmin/listarea',
      method:'GET',
      data:{},
      success:function(res){
        var list=res.data.areaList;
        if(list==null){
          var toastText='獲取資料失敗'+res.data.errMsg;
          wx.showToast({
            title: toastText,
            icon:'',
            duration:2000 //彈出時間
          })
        }else{
          that.setData({
            list:list
          })
        }
      }
    })
  }

list.wxml 其實就是html,有一些小程式自己標籤,具體看開發文件:

<!--pages/list/list.wxml-->
<view class="container">
  <view class='widget'>
    <text class='column'>編號</text>
    <text class='column'>校區名</text>
    <text class='column'>排名</text>
    <text class='link-column'>操作</text>
  </view>
  <scroll-view scroll-y="true">
    <view>
      <block wx:for='{{list}}'>
      <view class='widget'> 
        <text class='column'>{{item.areaId}}</text>
        <text class='column'>{{item.areaName}}</text>
        <text class='column'>{{item.priority}}</text>
        <view class='link-column'>
          <navigator class='link' url='../operation/operation?areaId={{item.areaId}}'>編輯</navigator> |
          <text class='link' bindtap='deleteArea' data-areaid='{{item.areaId}}' data-areaname='{{item.areaName}}' data-index='{{index}}'>刪除</text>  
        </view>
        </view>      
      </block>
    </view>
  </scroll-view>
  <button type='primary' bindtap='addArea'>新增區域資訊</button>
</view>

同理,list.wxss 就是css:

/* pages/list/list.wxss */
.container{
  height: 100%;
  display: table;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  padding-top: 10rpx;
  padding-bottom: 10rpx;
  text-align: center;
}

.widget{
  position: relative;
  margin-top: 5rpx;
  margin-bottom: 5rpx;
  padding-top: 10rpx;
  padding-bottom: 10rpx;
  padding-left: 40rpx;
  padding-right: 40rpx;
  border: #ddd 1px solid;
}

.column{
  width: 4rem;
  display: table-cell;
}

.link-column{
  width: 6rem;
  display: table-cell;
}

.link{
  color: blue;
  display: inline-table;

}

於是我們就有了這樣一個頁面,雖然簡陋,但是好歹是從後臺查到資料了啊(記得要先啟動後臺專案):
這裡寫圖片描述

繼續實現前臺的新增,編輯,刪除功能:
類似於vue元件的開發,貼上程式碼:(operation.js)

// pages/operation/operation.js
Page({

  /**
   * 頁面的初始資料
   */
  data: {
    areaId:null,
    areaName:'',
    priority:'',
    addUrl:'http://127.0.0.1:8081/superadmin/addarea',
    modifyUrl:'http://127.0.0.1:8081/superadmin/modifyarea'
  },

  /**
   * 生命週期函式--監聽頁面載入
   */
  onLoad: function (options) {
    var that=this;
    if(options.areaId==undefined){
      return;
    }
    that.setData({
      areaId: options.areaId,
    });
    wx.request({
      url: 'http://127.0.0.1:8081/superadmin/getareabyid',
      data:{"areaId":options.areaId},
      method:'GET',
      success:function(res){
        var area=res.data.area;
        if(area==undefined){
          var text='獲取資料失敗'+res.data.errMsg;
          wx.showToast({
            title: text,
            icon:'',
            duration:2000
          });
        }else{
          that.setData({
            areaName:area.areaName,
            priority:area.priority
          })
        }
      }
    })
  },

  /**
   * 生命週期函式--監聽頁面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命週期函式--監聽頁面顯示
   */
  onShow: function () {

  },

  /**
   * 生命週期函式--監聽頁面隱藏
   */
  onHide: function () {

  },

  /**
   * 生命週期函式--監聽頁面解除安裝
   */
  onUnload: function () {

  },

  /**
   * 頁面相關事件處理函式--監聽使用者下拉動作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 頁面上拉觸底事件的處理函式
   */
  onReachBottom: function () {

  },

  /**
   * 使用者點選右上角分享
   */
  onShareAppMessage: function () {

  },

/**
 *  表單功能
 */
  formSubmit:function(e){
    var that=this;
    var formData=e.detail.value; //獲取表資料
    var url=that.data.addUrl;  //預設url
    if(that.data.areaId!=undefined){
      formData.areaId=that.data.areaId;
      url = that.data.modifyUrl;
    }
    wx.request({
      url: url,
      data:JSON.stringify(formData),
      method:'POST',
      header:{
        'Content-Type':'application/json'
      },
      success:function(res){
        var result=res.data.success;
        var toastText="操作成功";
        if(result!=true){
          toastText="操作失敗!"+res.data.errMsg;
        }
        wx.showToast({
          title: toastText,
          icon:'',
          duration:3000
        });

        wx.redirectTo({
          url: '../list/list',
        })
        // if(that.data.areaId=undefined){
        //   wx.redirectTo({
        //     url: '../list/list',
        //   })
        // }
      }
    })
  }
})

頁面:

<!--pages/operation/operation.wxml-->
<view class='container'>
  <form bindsubmit='formSubmit' bindreset='formReset'>
    <view class='row'>
      <text>校區名:</text>
      <input type='text' name='areaName' placeholder='請輸入校區名稱' value='{{areaName}}'></input>
    </view>
    <view class='row'>
      <text>排名:</text>
      <input type='text' name='priority' placeholder='請輸入排名' value='{{priority}}'></input>
    </view>
    <view class='row'>
      <button type='primary' form-type='submit'>提交</button>
      <button type='primary' form-type='reset'>重置</button>
    </view>
  </form>
</view>

樣式:

/* pages/operation/operation.wxss */
.container {
  padding: 1rem;
  font-size: 0.9rem;
  line-height: 1.5rem;
}
.row {
  display: flex;
  align-items: center;
  margin-bottom: 0.8rem;
}
.row text {
  flex-grow: 1;
  text-align: right;
}
.row input {
  font-size: 0.7rem;
  flex-grow: 3;
  border: ipx solid #09c;
  display: inline-block;
  border-radius: 0.3rem;
  box-shadow: 0 0 0.15rem #aaa;
  padding: 0.3rem;
}
.row button {
  padding: 0.2rem;
  margin: 3rem 1rem;
}

迷你小程式開發完畢。

2018.9.5更新:
慕課網視訊學習地址:
《SpringBoot+MyBatis搭建迷你小程式》:https://www.imooc.com/learn/945