945-SpringBoot+MyBatis搭建迷你小程序
https://www.imooc.com/learn/945
简介:用Spring Boot框架大大简化了新Spring应用的初始搭建以及开发过程,在开发人员中越来越受到欢迎。微信小程序作为目前炙手可热的应用,很有可能在未来占据轻应用的市场。本门课程的主要目的是将两者结合起来,同时希望作为入门翔仔之前实战课的一个更低门槛的课程进行讲解。本课分为三大部分:第一部分带领大家明确需求,从零开始进行SpringBoot+MyBatis的框架搭建;第二部分咱们将依据业务模块配合UT实现后端完整的增删改查功能;最后我们将来到微信小程序开发部分,帮大家入门微信小程序开发,并教会大家前后联调。老师相关实战课程:http://coding.imooc.com/class/144.html 老师的面试课程: https://coding.imooc.com/class/303.html
第1章 课程介绍
本章节讲解本门课程的主旨,便于同学掌握课程的来龙去脉。
1-1 课程介绍
学习本门课程的作用:
- 学会从0搭建后端的SpringBoot + MyBatis框架
- 微信小程序入门
- 规范的代码编写
本门课程的框架:
- 从0搭建后端的springboot + mybatis框架
- 实现后端的业务功能
- 实现本地微信小程序的前端开发
- 前端与后端的联调
技术储备要求:
- 基本的Java知识
- 基本的前端开发知识(简单了解HTML,JS等)
- Spring , Mybatis基础知识(不会也没关系)
1-2 最终效果展示
登录、区域信息的增删改查
第2章 项目设计及框架搭建
本章节讲解项目的需求分析、数据库设计以及后端SpringBoot + Mybatis框架的搭建
2-1 SpringBoot的搭建与启动上
server.context-path=/demo //设置上下文路径
server.port=8888 //设置端口号
2-3 功能点的明确
区域信息的增删改查
2-4 表设计与实体类的创建
表设计
CREATE DATABASE IF NOT EXISTS `imooc_945_mini_app`; USE `imooc_945_mini_app`; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for tb_area -- ---------------------------- DROP TABLE IF EXISTS `tb_area`; CREATE TABLE `tb_area` ( `area_id` INT(2) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `area_name` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称', `priority` INT(2) NOT NULL DEFAULT 0 COMMENT '权重,越大越排前显示', `create_time` DATETIME(0) NULL DEFAULT NULL COMMENT '创建时间', `last_edit_time` DATETIME(0) NULL DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`area_id`) USING BTREE, UNIQUE INDEX `UK_AREA`(`area_name`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '区域信息' ROW_FORMAT = DYNAMIC; SET FOREIGN_KEY_CHECKS = 1;
实体类
// 区域信息 public class Area { // 主键ID private Integer areaId; // 名称 private String areaName; // 权重,越大越排前显示 private Integer priority; // 创建时间 private Date createTime; // 更新时间 private Date lastEditTime; }
第3章 项目开发
本章节带领大家从零开始从Dao到Controller开发一个完整的带单元测试增删改查后端。
- 配置
- 接口
- mapper
- ut,即单元测试
3-1 pom的配置
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
3-2 mybatis-config的配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--配置全局属性-->
<settings>
<!--使用JDBC的getGeneratedKeys获取数据库自增主键值-->
<setting name="useGeneratedKeys" value="true"/>
<!--使用列标签替换列别名 默认:true-->
<setting name="useColumnLabel" value="true"/>
<!--开启驼峰命名转换:Table{create_time} -> Entity{createTime}-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
3-3 datasource和sessionfactorybean的配置
配置datasource到ioc容器里面
@Configuration // 配置mybatis mapper的扫描路径 @MapperScan("com.tuyrk.dao") public class DataSourceConfiguration { @Value("${jdbc.driver}") private String jdbcDriver; @Value(("${jdbc.url}")) private String jdbcUrl; @Value("${jdbc.username}") private String jdbcUsername; @Value("${jdbc.password}") private String jdbcPassword; // 生成与spring-dao.xml对应的bean dataSource @Bean(name = "dataSource") public ComboPooledDataSource createDataSource() throws PropertyVetoException { // 生成datasource实例 ComboPooledDataSource dataSource = new ComboPooledDataSource(); // 跟配置文件一样设置以下信息 // 驱动 dataSource.setDriverClass(jdbcDriver); // 数据库连接URL dataSource.setJdbcUrl(jdbcUrl); // 设置用户名 dataSource.setUser(jdbcUsername); // 设置用户密码 dataSource.setPassword(jdbcPassword); // 配置c3p0连接池的私有属性 // 连接池最大线程数 dataSource.setMaxPoolSize(30); // 连接池最小线程数 dataSource.setMinPoolSize(10); //关闭连接后不自动commit dataSource.setAutoCommitOnClose(false); // 连接超时时间 dataSource.setCheckoutTimeout(10000); // 连接失败重试次数 dataSource.setAcquireRetryAttempts(2); return dataSource; } }
创建sqlSessionFactoryBean实例
@Configuration public class SessionFactoryConfiguration { // mybatis-config.xml配置文件的路径 @Value("${mybatis_config_file}") private String mybatisConfigFilePath; // mybatis mapper文件所在的路径 @Value("${mapper_path}") private String mapperPath; // 实体类所在的Package @Value("${entity_package}") private String entityPackage; @Autowired @Qualifier("dataSource") private DataSource dataSource; // 创建sqlSessionFactoryBean实例 并且设置configtion 设置mapper映射路径 设置datasource数据源 @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); // 设置mybatis configuration 扫描路径 sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFilePath)); // 添加mapper 扫描路径 PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); String packageSearchPath = PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath; sqlSessionFactoryBean.setMapperLocations(resolver.getResources(packageSearchPath)); // 设置dataSource sqlSessionFactoryBean.setDataSource(dataSource); // 设置typeAlias 包扫描路径 sqlSessionFactoryBean.setTypeAliasesPackage(entityPackage); return sqlSessionFactoryBean; } }
3-4 dao的创建
public interface AreaDao {
// 列出区域列表
List<Area> queryArea();
// 根据Id列出具体区域
Area queryAreaById(Integer areaId);
// 插入区域信息
Integer insertArea(Area area);
// 更新区域信息
Integer updateArea(Area area);
// 删除区域信息
Integer deleteArea(Integer areaId);
}
3-5 mapper的编写
自动化生成mapper工具:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tuyrk.dao.AreaDao"> <!-- 查询区域信息列表 --> <select id="queryArea" resultType="com.tuyrk.entity.Area"> SELECT area_id, area_name, priority, create_time, last_edit_time FROM tb_area ORDER BY priority DESC; </select> <!-- 根据区域ID,查询区域信息 --> <select id="queryAreaById" resultType="com.tuyrk.entity.Area"> SELECT area_id, area_name, priority, create_time, last_edit_time FROM tb_area WHERE area_id = #{areaId} </select> <!-- 新增区域信息 --> <insert id="insertArea" useGeneratedKeys="true" keyProperty="areaId" keyColumn="area_id" parameterType="com.tuyrk.entity.Area"> INSERT INTO tb_area (area_name, priority, create_time, last_edit_time) VALUES (#{areaName}, #{priority}, #{createTime}, #{lastEditTime}); </insert> <!-- 更新区域信息 --> <update id="updateArea" parameterType="com.tuyrk.entity.Area"> update tb_area <set> <if test="areaName != null">area_name = #{areaName},</if> <if test="priority != null">priority = #{priority},</if> <if test="lastEditTime != null">last_edit_time = #{lastEditTime}</if> </set> where area_id = #{areaId}; </update> <!-- 根据区域ID,删除区域信息 --> <delete id="deleteArea"> DELETE FROM tb_area WHERE area_id = #{areaId}; </delete> </mapper>
3-6 dao层开发
@Autowired private AreaDao areaDao;
areaDao红线报错解决方案:
- 【File】==>【settings】==>【Inspections】==>【Spring】==>【Spring Core】==>【Code】==>【Autowiring for Bean Class】==>【Warning】
UT单元测试:
AreaDaoTest.java的编写
@RunWith(SpringRunner.class) @SpringBootTest public class AreaDaoTest { //通过spring容器注入Dao的实现类 @Autowired private AreaDao areaDao; @Test public void queryArea() { List<Area> areaList = areaDao.queryArea(); // 验证预期值和实际值是否相符 assertEquals(2, areaList.size()); } // ... }
如此繁多的框架应该学习哪一个?
答:Spring。多看Spring源码,学习框架设计。
3-7 service层的实现
配置
对标spring-service里面的transactionManager
继承TransactionManagementConfiguration是因为开启annotation-driven@Configuration // 首先使用注解 @EnableTransactionManagement 开启事务支持后 // 在Service方法上添加注解 @Transactional 便可 @EnableTransactionManagement// 开启事务的管理 public class TransactionManagementConfiguration implements TransactionManagementConfigurer { @Autowired // 注入DataSourceConfiguration里边的DataSource,通过createDataSource()获取 private DataSource dataSource; // 关于事务管理,需要返回PlatformTransactionManager的实现 @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } }
接口
public interface AreaService { // 获取区域列表 List<Area> getAreaList(); // 通过区域Id获取区域信息 Area getAreaById(int areaId); // 增加区域信息 boolean addArea(Area area); // 修改区域信息 boolean modifyArea(Area area); // 删除区域信息 boolean deleteArea(int areaId); }
实现类
3-8 业务controller方法的实现
业务Controller方法的实现
统一异常处理
浏览器JSON格式化查看插件:JsonView
3-9 统一异常处理功能的实现
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Map<String, Object> handlerException(HttpServletRequest request, Exception e) {
Map<String, Object> modelMap = new HashMap<>();
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
return modelMap;
}
}
第4章 微信小程序的入门及前后联调
本章节将带领大家入门微信小程序,并实现本项目的前端功能,同时进行前后端联调。
4-1 微信小程序简介
小程序代码构成:
- JSON配置
- WXML模板
- WXSS样式
- JS逻辑交互
4-2 微信开发者工具简介
下载
模拟器、编辑器、调试器
4-3 创建新的小程序
【项目目录】==>【APPID(测试号)】==>【项目名称】==>【建立普通快速启动模板】
4-4 列表页开发
修改标题:
- 在*.json中添加
"navigationBarTitleText": "区域信息列表"
组件:
- view:类似于html的div
- scroll-view:可滚动试图区域
- text:文本
<!--pages/list/list.wxml-->
<view class='container'>
<!-- 表头 -->
<view class='widget'>
<text class='column'>ID</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>
列表展示
onShow: function() { var that = this; wx.request({ url: 'http://127.0.0.1:8888/demo/superadmin/listarea', data: {}, method: 'GET', success: function(res) { var list = res.data.areaList; console.log(res); if (list == null) { var toastText = '获取数据失败' + res.data.errMsg; wx.showToast({ title: toastText, icon: '', duration: 2000 }) } else { that.setData({ list: list }); } } }) }
删除功能
deleteArea: function(e) { var that = this; // 0. 询问用户是否删除该信息 wx.showModal({ title: '提示', content: '确定要删除[' + e.target.dataset.areaname + ']吗?', success: function(sm) { // 如果点击确认, if (sm.confirm) { // 1. 获取areaId,将其传递给后台做删除操作 wx.request({ url: 'http://127.0.0.1:8888/demo/superadmin/removearea', data: { "areaId": e.target.dataset.areaid }, method: 'GET', success: function(res) { var result = res.data.success; var toastText = "删除成功!"; if (result != true) { toastText = "刪除失敗!"; } else { // 2. 更新list值 that.data.list.splice(e.target.dataset.index, 1); that.setData({ list: that.data.list }) } // 彈出提示 wx.showToast({ title: toastText, icon: '', duration: 2000 }) } }) } } }) }
跳转到添加区域信息
addArea: function() { wx.navigateTo({ url: '../operation/operation' }); }
4-7 列表页前后端联调
4-8 区域信息编辑页的开发
<!--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}}'/>
</view>
<view class='row'>
<text>优先级:</text>
<input type='number' name='priority' placeholder='数值越大越靠前' value='{{priority}}'/>
</view>
<!-- 按钮 -->
<view class='row'>
<button type='primary' form-type='submit'>提交</button>
<button type='primary' form-type='reset'>清空</button>
</view>
</form>
</view>
- 区域信息添加
- 区域信息更新
页面的初始数据
data: { areaId: undefined, areaName: '', priority: '', addUrl: 'http://127.0.0.1:8888/demo/superadmin/addarea', modifyUrl: 'http://127.0.0.1:8888/demo/superadmin/modifyarea' }
编辑页获取区域信息
onLoad: function(options) { var that = this; // 页面初始化 options为页面跳转所带来的参数 this.setData({ areaId: options.areaId }); if (options.areaId == undefined) { return; } // 向后端发送请求,获取areaId的区域信息 wx.request({ url: 'http://127.0.0.1:8888/demo/superadmin/getareabyid', data: { "areaId": options.areaId }, method: 'GET', success: function(res) { var area = res.data.area; if (area == undefined) { var toastText = "获取数据失败" + res.data.errMsg; wx.showToast({ title: toastText, icon: '', duration: 2000 }); } else { that.setData({ areaName: area.areaName, priority: area.priority }); } } }) }
提交区域信息表单
formSubmit: function (e) { var that = this; // 默认为新增操作 var formData = e.detail.value; var url = that.data.addUrl; // 如果areaId不为空,则为更新操作 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: 2000 }); if (that.data.areaId == undefined) { wx.redirectTo({ url: '../list/list' }) } } }); }
4-9 区域信息编辑页的联调
第5章 课程总结与展望
从整体上复习下本门课程的知识点
- HelloWorld Controller
- 表设计和实体类的创建
- dao层配置:mybatis-config,
- service层配置:事务,接口及实现类
- Controller层:增删改查
- 微信小程序,微信开发者工具
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com
文章标题:945-SpringBoot+MyBatis搭建迷你小程序
文章字数:3.6k
本文作者:神秘的小岛岛
发布时间:2019-07-06, 23:20:09
最后更新:2019-11-05, 19:27:12
原始链接:https://www.tuyrk.cn/imooc/945-mini-app/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。