SpringBoot+MyBatis搭建迷你小程序

开发环境

  1. jdk:java version “1.8.0_152”
  2. Itell IDEA
    IDEA官网 (可凭学生邮箱注册免费使用)
  3. maven3.3.9
    Maven安装配置
  4. mysql-community-5.7.21
    MySQL下载地址
    MySQL安装教程
  5. sqlyog
    sqlyog注册码

步骤

1.项目新建及配置

JDK之类的配置就不多说了,新建项目;
New Project
对了,当时不记得了,别勾选Android相关配置,不然后面会出问题的。
选中【Spring Initializr】,设置好【Project SDK】;
New Project
New Project
勾选Web下的web和SQL下的MyBatis,然后Next……Finish。

这里写图片描述
设置好Maven的目录;(矮油,顺便换了个皮肤,不要在意这些细节啦~)
注释
因为之前手动勾选设好了Maybatis的配置了,所以现在可以把pom.xml配置文件里的这段注释掉;

  <dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>1.3.1</version>
	</dependency>

然后记得点击右下角重新导入Maven依赖。
导入Maven

测试SpringBoot在Web端运行(只是测试,可跳过此步)

新建Hello类
Hello类
代码如下:

package cn.yimispace.demo;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Hello {
    @RequestMapping(value="/hello", method = RequestMethod.GET)
    public String hello(){
        return "Hello SpringBoot!";
    }
}

然后点击运行,在浏览器url处输入:

http://localhost:8080/

即可运行。
如果想换端口或者添加根路径也可在application.properties文件自己配置:
application.properties
然后运行,Web显示如下:
Web显示

项目后台开发

1. 使用SQLyog创建数据库及表

数据库名:Yimi
表名:plan
使用SQLyog创建数据库及表

CREATE DATABASE Yimi;
USE Yimi;

CREATE TABLE `plan`(
`id` INT(2) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(200) NOT NULL,
`priority` INT(2) NOT NULL DEFAULT '0',
`content` VARCHAR(500),
`create_time` DATETIME DEFAULT NULL,
`last_edit_time` DATETIME DEFAULT NULL,
PRIMARY KEY(`id`),
UNIQUE KEY `UK_PLAN`(`name`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

SELECT * FROM `plan`;

2. 修改pom.xml文件

打开IDEA的项目,修改pom.xml文件。
修改pom.xml文件
添加的代码如下:

		<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.新建entity包,在此包内新建Plan类

表中字段与此类一一对应,并添加相应getter,setter方法。

package cn.yimispace.demo.entity;

import java.util.Date;

public class Plan {
    private Integer id;         //计划ID
    private String name;        //计划名称
    private Integer priority;   //权重,越大越靠前显示
    private String content;     //内容
    private Date createTime;    //创建时间
    private Date lastEditTime;  //更新时间

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

   //......

4.配置mybatis-config.xml

<?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的GeneratedKeys获取数据库自增主键值 -->
        <setting name="useGeneratedKeys" value="true" />
        <!-- 使用列标签替换列别名 默认:true -->
        <setting name="useColumnLabel"  value="true" />
        <!-- 开启驼峰命名转换:Table{create_time} -> Entity{createTime} -->
        <setting name="mapUnderscoreToCamelCase" value="true" />
    </settings>
</configuration>

5.配置application.properties

用于连接数据库及地址映射相关操作。

server.port=8081
server.context-path=/demo

#DataSourceConfiguration
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/yimi?useUnicode=true&useSSL=false
jdbc.username=root
jdbc.password=wanxinyan

#SessionFactoryConfiguration
mybatis_config_file=mybatis-config.xml
mapper_path=/mapper/**.xml
entity_package=cn.yimispace.demo.entity

6.DataSource配置

新建cn.yimispace.demo.config包,在此包下新建类DataSourceConfiguration,代码如下:

package cn.yimispace.demo.config;

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 java.beans.PropertyVetoException;

/**
 * @Configuration 告诉Spring容器调用此类注入
 * @MapperScan 配置mybatis mapper的扫描路径
 */
@Configuration
@MapperScan("cn.yimispace.demo.dao")
public class DataSourceConfiguration {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 设置连接池
     * @return
     */
    @Bean(name="dataSource")
    public ComboPooledDataSource createDataSource() throws PropertyVetoException {
        //普通java项目里不能导入安卓的包,否则会报Runningtime错及找不到PropertyVetoException
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);
        //关闭连接后不自动提交
        dataSource.setAutoCommitOnClose(false);
        return dataSource;
    }
}

7.SessionFactory配置

在cn.yimispace.demo.config包下新建SessionFactoryConfiguration类,代码如下:

package cn.yimispace.demo.config;

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;

@Configuration
public class SessionFactoryConfiguration {
    @Value("${mybatis_config_file}")
    private String mybatisConfigFilePath;
    @Value("${mapper_path}")
    private String mapperPath;
    @Value("${entity_package}")
    private String entityPackage;

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

    @Bean(name="sqlSessionFactory")
    public SqlSessionFactoryBean createSqlSessionFactoryBean() throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setConfigLocation(new ClassPathResource(mybatisConfigFilePath));
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        String packageSearchPath = PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + mapperPath;
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(packageSearchPath));
        sqlSessionFactoryBean.setDataSource(dateSource);
        sqlSessionFactoryBean.setTypeAliasesPackage(entityPackage);
        return sqlSessionFactoryBean;
    }
}

8.DAO层

新建cn.yimispace.demo.dao包,在此包下新建接口PlanDao,代码如下:

package cn.yimispace.demo.dao;

import cn.yimispace.demo.entity.Plan;

import java.util.List;

public interface PlanDao {  //alt+enter键create test可创建测试单元
    /**
     * 列出计划列表
     * @return  planList
     */
    List<Plan> queryPlan();

    /**
     * 根据ID列出具体计划
     * @param id
     * @return plan
     */
    Plan queryPlanById(int id);

    /**
     * 插入计划信息
     * @param plan
     * @return
     */
    int insertPlan(Plan plan);

    /**
     * 更新计划信息
     * @param plan
     * @return
     */
    int updatePlan(Plan plan);

    /**
     * 删除计划信息
     * @param id
     * @return
     */
    int deletePlan(int id);
}

要想DAO层能访问数据库内容,需要做映射,在resources目录下新建mapper文件夹,内新建PlanDao.xml,用于设置SQL代码,其中标签内配置的id等信息与类内方法一一对应,内容如下:

<?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="cn.yimispace.demo.dao.PlanDao">
    <select id="queryPlan" resultType="cn.yimispace.demo.entity.Plan">
        SELECT id,name,priority,content,create_time,last_edit_time
        FROM plan
        ORDER BY priority
        DESC
    </select>
    <select id="queryPlanById" resultType="cn.yimispace.demo.entity.Plan">
        SELECT id,name,priority,content,create_time,last_edit_time
        FROM plan
        WHERE
        id=#{id}
    </select>
    <insert id="insertPlan" useGeneratedKeys="true" keyProperty="id"
            keyColumn="id" parameterType="cn.yimispace.demo.entity.Plan">
        INSERT INTO
        PLAN(name,priority,content,create_time,last_edit_time)
        VALUES
        (#{name},#{priority},#{content},#{createTime},#{lastEditTime})
    </insert>
    <update id="updatePlan" parameterType="cn.yimispace.demo.entity.Plan">
        UPDATE plan
        <set>
            <if test="name!=null">name=#{name},</if>
            <if test="priority!=null">priority=#{priority},</if>
            <if test="content!=null">content=#{content},</if>
            <if test="lastEditTime!=null">last_edit_time=#{lastEditTime},</if>
        </set>
        WHERE id=#{id}
    </update>
    <delete id="deletePlan">
        DELETE FROM
        plan
        WHERE
        id=#{id}
    </delete>
</mapper>

接下来,可以对所写的DAO层方法进行测试,回到接口PlanDao的名字处使用alt+enter键create test可创建测试单元,在test文件夹下会自动生成cn.yimispace.demo.dao.PlanDaoTest类,然后对每个方法进行单元测试,暂时不测试的类可先写上@Ignore,形如以下代码:

package cn.yimispace.demo.dao;

import cn.yimispace.demo.entity.Plan;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;
import java.util.List;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class PlanDaoTest {
    @Autowired   //Spring通过Autowire用于动态注入
    private PlanDao planDao;

    @Test@Ignore
    public void queryPlan() {
        List<Plan> planList = planDao.queryPlan();
        //expected:2表示期望返回的结果条数
        assertEquals(2, planList.size());
    }

    @Test@Ignore
    public void queryPlanById() {
        Plan plan = planDao.queryPlanById(2);
        assertEquals("生活计划", plan.getName());
    }

    @Test@Ignore
    public void insertPlan() {
        Plan plan = new Plan();
        plan.setName("运动计划");
        plan.setPriority(1);
        plan.setContent("跑一次全程马拉松");
        int effectedNum = planDao.insertPlan(plan);
        assertEquals(1, effectedNum);
    }

    @Test@Ignore
    public void updatePlan() {
        Plan plan = new Plan();
        plan.setContent("周游世界");
        plan.setId(3);
        plan.setLastEditTime(new Date());
        int effectedNum = planDao.updatePlan(plan);
        assertEquals(1,effectedNum);
    }

    @Test
    public void deletePlan() {
        int effectedNum = planDao.deletePlan(3);
        assertEquals(1,effectedNum);
    }

}

进行单元测试

9.Service层

新建cn.yimispace.demo.service.PlanService接口:

package cn.yimispace.demo.service;

import cn.yimispace.demo.entity.Plan;

import java.util.List;

public interface PlanService {
    /**
     * 列出计划列表
     * @return  planList
     */
    List<Plan> getPlanList();

    /**
     * 根据ID列出具体计划
     * @param id
     * @return plan
     */
    Plan queryPlanById(int id);

    /**
     * 添加计划信息
     * @param plan
     * @return
     */
    boolean addPlan(Plan plan);

    /**
     * 修改计划信息
     * @param plan
     * @return
     */
    boolean modifyPlan(Plan plan);

    /**
     * 删除计划信息
     * @param id
     * @return
     */
    boolean deletePlan(int id);
}

新建cn.yimispace.demo.service.impl.PlanServiceImpl类实现接口:

package cn.yimispace.demo.service.impl;

import cn.yimispace.demo.dao.PlanDao;
import cn.yimispace.demo.entity.Plan;
import cn.yimispace.demo.service.PlanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
public class PlanServiceImpl implements PlanService {
    @Autowired
    private PlanDao planDao;

    /**
     * 列出计划列表
     *
     * @return planList
     */
    @Override
    public List<Plan> getPlanList() {
        return planDao.queryPlan();
    }

    /**
     * 根据ID列出具体计划
     *
     * @param id
     * @return plan
     */
    @Override
    public Plan queryPlanById(int id) {
        return planDao.queryPlanById(id);
    }

    /**
     * 添加计划信息
     *@Transactional
     * 默认回滚RuntimeException类型的异常,
     * 若想回滚所有Exception异常可改为@Transactional(rollbackFor = Exception.class)
     * @param plan
     * @return
     */
    @Transactional
    @Override
    public boolean addPlan(Plan plan) {
        if(plan.getName() != null && !"".equals(plan.getName())){
            plan.setCreateTime(new Date());
            plan.setLastEditTime(new Date());
            try{
                int effectedNum = planDao.insertPlan(plan);
                if(effectedNum > 0){
                    return true;
                }else{
                    throw  new RuntimeException("插入计划信息失败!");
                }
            }catch(Exception e){
                throw new RuntimeException("插入计划信息失败:" + e.getMessage());
            }
        }else{
            throw  new RuntimeException("计划信息不能为空!");
        }
    }

    /**
     * 修改计划信息
     *
     * @param plan
     * @return
     */
    @Override
    public boolean modifyPlan(Plan plan) {
        if(plan.getId() != null && plan.getId() > 0){
            plan.setLastEditTime(new Date());
            try{
                int effectedNum = planDao.updatePlan(plan);
                if(effectedNum > 0){
                    return true;
                }else{
                    throw  new RuntimeException("更新计划信息失败!");
                }
            }catch(Exception e){
                throw new RuntimeException("更新计划信息失败:" + e.toString());
            }
        }else{
            throw  new RuntimeException("计划信息不能为空!");
        }
    }

    /**
     * 删除计划信息
     *
     * @param id
     * @return
     */
    @Override
    public boolean deletePlan(int id) {
        if(id > 0){
            try{
                int effectedNum = planDao.deletePlan(id);
                if(effectedNum > 0){
                    return true;
                }else{
                    throw  new RuntimeException("删除计划信息失败!");
                }
            }catch(Exception e){
                throw new RuntimeException("删除计划信息失败:" + e.toString());
            }
        }else{
            throw  new RuntimeException("计划id不能为空!");
        }
    }
}

当然,写好后也可以仿照之前介绍的方法进行单元测试,效果如图:
进行单元测试2

10.业务Controller方法实现

新建cn.yimispace.demo.web.PlanController类:

package cn.yimispace.demo.web;

import cn.yimispace.demo.entity.Plan;
import cn.yimispace.demo.service.PlanService;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
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.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @RestController
 * 即@ResponseBody与@Controller的组合
 * 因为返回的不是页面,而是body值
 * @RequestMapping("/superadmin")
 * 设置根路由(最好小写)
 */
@RestController
@RequestMapping("/superadmin")
public class PlanController {
    @Autowired
    private PlanService planService;

    /**
     * 启动DemoApplication在浏览器访问
     * http://localhost:8081/demo/superadmin/listplan
     * 即可查到返回的内容
     * @return
     */
    @RequestMapping(value = "/listplan", method = RequestMethod.GET)
    private Map<String, Object> listPlan(){
        Map<String, Object>modelMap = new HashMap<String, Object>();
        List<Plan> list = planService.getPlanList();
        modelMap.put("planList", list);
        return modelMap;
    }
    @RequestMapping(value="/getplanbyid", method = RequestMethod.GET)
    private Map<String, Object>getPlanById(Integer id){
        Map<String, Object>modelMap = new HashMap<String, Object>();
        Plan plan = planService.queryPlanById(id);
        modelMap.put("plan", plan);
        return modelMap;
    }

    /**
     * @RequestBody 使前端传参以对象方式获取plan到后台
     * @param plan
     * @return
     */
    @RequestMapping(value="/addplan", method = RequestMethod.POST)
    private Map<String, Object>addPlan(@RequestBody Plan plan){
        Map<String, Object>modelMap = new HashMap<String, Object>();
        modelMap.put("success", planService.addPlan(plan));
        return modelMap;
    }
    @RequestMapping(value="/modifyplan", method = RequestMethod.POST)
    private Map<String, Object>modifyPlan(@RequestBody Plan plan){
        Map<String, Object>modelMap = new HashMap<String, Object>();
        modelMap.put("success", planService.modifyPlan(plan));
        return modelMap;
    }
    @RequestMapping(value="/removeplan", method = RequestMethod.GET)
    private Map<String, Object>removePlan(@RequestBody Integer id){
        Map<String, Object>modelMap = new HashMap<String, Object>();
        modelMap.put("success", planService.deletePlan(id));
        return modelMap;
    }
}

11.异常处理类

新建cn.yimispace.demo.handle.GlobalExceptionHandle用于处理DAO,Service,Controller等抛出的异常。

package cn.yimispace.demo.handle;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 异常处理类:
 * 用于处理DAO,Service,Controller等抛出的异常
 */
@ControllerAdvice
public class GlobalExceptionHandle {
    /**
     * @ExceptionHandler(value=Exception.class)
     * 也可自定义错误类,抛出异常时new处自定义的错误类进行处理
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value=Exception.class)
    @ResponseBody
    private Map<String, Object>exceptionHandler(HttpServletRequest req, Exception e){
        Map<String, Object> modelMap = new HashMap<String, Object>();
        modelMap.put("success", false);
        modelMap.put("errMsg", e.getMessage());
        return modelMap;
    }
}

若抛出了异常可根据Json键值对"success"为false及"errorMsg"显示错误信息,可以测试一下此类是否生效。例如:可在PlanController类的listPlan()方法中写int x = 1/0;运行DemoApplication,则Web端显示Json报错信息。
报错情况:
报错情况
正常情况:
正常情况

项目前端开发

1.工具准备及项目新建

微信小程序使用微信提供的开发工具,具体介绍可参见小程序文档
下载微信开发者工具
用自己的微信扫码登录,在一个空文件夹里新建快速启动项目,打开效果如下:
微信开发者工具

2.前端代码编写

在pages下新建list目录,在此目录下新建名为list的Page,微信开发者工具会自动生成相应的js,json,wxml,wxss文件,修改list.json文件用于改变计划列表页面标题栏:

{
  "navigationBarTitleText": "计划信息列表"
}

报错修改

使用IDEA写Autowired报错时,可做如下操作来解除报错
解除Autowired报错

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值