SpringBoot整合Mybatis实现简单的CRUD

继上篇文章:Spring-Boot入门之环境搭建。这次我们整合SpringBoot-Mybatis实现简单的CRUD业务。

需求:

  • 详解SpringBoot工程的构建、与SSM项目在工程搭建上的不同。
  • 实现SpringBoot-Mybatis整合征服数据库。
  • 解决页面跳转,详解与SSM阶段的不同。
  • 实现分页查询,使用PaheHelper插件和ElementUI分页控件。
  • 实现文件上传。
  • 使用Spring AOP切面编程实现简易的实现登录拦截工程。

项目源码请看我的Github仓库:教你优雅的入门Spring Boot框架

如果觉得不错就点击右上角star鼓励一下笔者吧(#.#)

教你优雅的入门Spring Boot框架

技术栈

  • 后端: SpringBoot + Mybatis
  • 前端: Vue.JS + ElementUI

测试环境

  • IDEA + SpringBoot-2.0.5

项目设计

.
├── db  -- sql文件
├── mvnw 
├── mvnw.cmd
├── pom.xml  -- 项目依赖
└── src
    ├── main
    │   ├── java
    │   │   └── cn
    │   │       └── tycoding
    │   │           ├── SpringbootApplication.java  -- Spring Boot启动类
    │   │           ├── controller  -- MVC-WEB层
    │   │           ├── entity  -- 实体类
    │   │           ├── interceptor  -- 自定义拦截器
    │   │           ├── mapper  -- mybatis-Mapper层接口
    │   │           └── service  -- service业务层
    │   └── resources  -- Spring Boot资源文件 
    │       ├── application.yml  -- Spring Boot核心配置文件
    │       ├── mapper  -- Mybatis Mapper层配置文件
    │       ├── static  -- 前端静态文件
    │       └── templates  -- Thymeleaf模板引擎识别的HTML页面目录
    └── test  -- 测试文件

文档

更多文档将在我的公众号 程序员涂陌 中陆续发布,请持续关注!

程序员涂陌
qrcode_for_gh

捐赠

Alipay WechatPay
alipay_258px
wechat_258px

准备

开始实战Spring Boot项目,首先,你需要将Spring Boot工程搭建出来。

Spring Boot工程搭建请看我的博客:Spring Boot入门之工程搭建

Spring Boot应用启动器

Spring Boot提供了很多应用启动器,分别用来支持不同的功能,说白了就是pom.xml中的依赖配置,因为Spring Boot的自动化配置特性,我们并不需再考虑项目依赖版本问题,使用Spring Boot的应用启动器,它能自动帮我们将相关的依赖全部导入到项目中。

我们这里介绍几个常见的应用启动器:

  • spring-boot-starter: Spring Boot的核心启动器,包含了自动配置、日志和YAML
  • spring-boot-starter-aop: 支持AOP面向切面编程的功能,包括spring-aop和AspecJ
  • spring-boot-starter-cache: 支持Spring的Cache抽象
  • spring-boot-starter-artermis: 通过Apache Artemis支持JMS(Java Message Service)的API
  • spring-boot-starter-data-jpa: 支持JPA
  • spring-boot-starter-data-solr: 支持Apache Solr搜索平台,包括spring-data-solr
  • spring-boot-starter-freemarker: 支持FreeMarker模板引擎
  • spring-boot-starter-jdbc: 支持JDBC数据库
  • spring-boot-starter-Redis: 支持Redis键值储存数据库,包括spring-redis
  • spring-boot-starter-security: 支持spring-security
  • spring-boot-starter-thymeleaf: 支持Thymeleaf模板引擎,包括与Spring的集成
  • spring-boot-starter-web: 支持全栈式web开发,包括tomcat和Spring-WebMVC
  • spring-boot-starter-log4j: 支持Log4J日志框架
  • spring-boot-starter-logging: 引入Spring Boot默认的日志框架Logback

Spring Boot项目结构设计

Spring Boot项目(即Maven项目),当然拥有最基础的Maven项目结构。除此之外:

  1. Spring Boot项目中不包含webapp(webroot)目录。

  2. Spring Boot默认提供的静态资源目录需要置于classpath下,且其下的目录名称要符合一定规定。

  3. Spring Boot默认不提倡用XML配置文件,主张使用YML作为配置文件格式,YML有更简洁的语法。当然也可以使用.properties作为配置文件格式。

  4. Spring Boot官方推荐使用Thymeleaf作为前端模板引擎,并且Thymeleaf默认将templates作为静态页面的存放目录(由配置文件指定)。

  5. Spring Boot默认将resources作为静态资源的存放目录,存放前端静态文件、项目配置文件。

  6. Spring Boot规定resources下的子级目录名要符合一定规则,一般我们设置resources/static为前端静态(JS,CSS)的存放目录;设置resources/templates作为HTML页面的存放目录。

  7. Spring Boot指定的Thymeleaf模板引擎文件目录/resources/templates是受保护的目录,想当与之前的WEB-INF文件夹,里面的静态资源不能直接访问,一般我们通过Controller映射访问。

  8. 建议将Mybatis-Mapper的XML映射文件放于resources/目录下,我这里设为resources/mapper目录,且src/main/java/Mapper下的Mapper层接口要使用@Mapper注解标识,不然mybatis找不到接口对应的XML映射文件。

  9. SpringBootApplication.java为项目的启动器类,项目不需要部署到Tomcat上,由SpringBoot提供的服务器部署项目(运行启动器类即可);且SpringBoot会自动扫描该启动器同级和子级下用注解标识的Bean。

  10. Spring Boot不建议使用JSP页面,如果想使用,请自行百度解决办法。

  11. 上面说了Spring Boot提供的存放HTML静态页面的目录resources/templates是受保护的目录,访问其中的HTML页面要通过Controller映射,这就间接规定了你需要配置Spring的视图解析器,且Controller类不能使用@RestController标识。

起步

首先: 我想特殊强调的是:SpringBoot不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式。一定要切记这一点。

学习SpringBoot框架,只是为了更简便的使用Spring框架,我们在SSM阶段学习的知识现在放在Spring Boot框架上开发是完全适用的,我们学习的大多数是SpringBoot的自动化配置方式。

因为Spring Boot框架的一大优势就是自动化配置,从pom.xml的配置中就能明显感受到。

所以这里推荐一下我之前的SSM阶段整合项目: SSM详细入门整合案例 SSM+Redis+Shiro+Solr+Vue.js整合项目

项目依赖

本项目的依赖文件请看Github仓库:spring-boot/pom.xml

初始化数据库

本项目数据库表设计请看GitHub仓库:spring-boot/db/

请运行项目前,先把数据库表结构建好

SpringBoot整合Mybatis

之前已经说过:SpringBoot框架不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式

所以说,SpringBoot整合Mybatis的思想和Spring整合Mybatis的思想基本相同,不同之处有两点:

  • 1.Mapper接口的XML配置文件变化。之前我们使用Mybatis接口代理开发,规定Mapper映射文件要和接口在一个目录下;而这里Mapper映射文件置于resources/mapper/下,且置于src/main/java/下的Mapper接口需要用@Mapper注解标识,不然映射文件与接口无法匹配。

  • 2.SpringBoot建议使用YAML作为配置文件,它有更简便的配置方式。所以整合Mybatis在配置文件上有一定的区别,但最终都是那几个参数的配置。

关于YAML的语法请自行百度,我这里也仅仅是满足基本的配置需求,不涉及那种不易理解的语法。

整合配置文件

本例详细代码请看GitHub仓库:spring-boot/resources/application.yml

在Spring阶段用XML配置mybatis无非就是配置:1.连接池;2.数据库url连接;3.mysql驱动;4.其他初始化配置

spring:
  datasource:
    name: springboot
    type: com.alibaba.druid.pool.DruidDataSource
    #druid相关配置
    druid:
      #监控统计拦截的filters
      filter: stat
      #mysql驱动
      driver-class-name: com.mysql.jdbc.Driver
      #基本属性
      url: jdbc:mysql://127.0.0.1:3306/springboot?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
      username: root
      password: root
      #配置初始化大小/最小/最大
      initial-size: 1
      min-idle: 1
      max-active: 20
      #获取连接等待超时时间
      max-wait: 60000
      #间隔多久进行一次检测,检测需要关闭的空闲连接
      time-between-eviction-runs-millis: 60000

  #mybatis配置
  mybatis:
    mapper-locations: classpath:mapper/*.xml
    type-aliases-package: cn.tycoding.entity

注意:空格代表节点层次;注释部分用#标记

解释

  1. 我们实现的是spring-mybatis的整合,包含mybatis的配置以及datasource数据源的配置当然属于spring配置中的一部分,所以需要在spring:下。

  2. mapper-locations相当于XML中的<property name="mapperLocations">用来扫描Mapper层的配置文件,由于我们的配置文件在resources下,所以需要指定classpath:

  3. type-aliases-package相当与XML中<property name="typeAliasesPackase">别名配置,一般取其下实体类类名作为别名。

  4. datasource数据源的配置,name表示当前数据源的名称,类似于之前的<bean id="dataSource">id属性,这里可以任意指定,因为我们无需关注Spring是怎么注入这个Bean对象的。

  5. druid代表本项目中使用了阿里的druid连接池,driver-class-name:相当于XML中的<property name="driverClassName">url代表XML中的<property name="url">username代表XML中的<property name="username">password代表XML中的<property name="password">;其他druid的私有属性配置不再解释。这里注意druid连接池和c3p0连接池在XML的<property>的name中就不同,在此处SpringBoot的配置中当然名称也不同。

如果Spring整合Mybtis的配置你已经很熟悉了,那么这个配置你肯定也很眼熟,从英文名称上就很容易区分出来。这里需要注意的就是YAML语法规定不同行空格代表了不同的层级结构。

既然完成了SpringBoot-Mybatis基本配置下面我们实战讲解如何实现基本的CRUD。

实现查询

1.在src/main/java/cn/tycoding/entity/下新建User.java实体类

public class User implements Serializable {
    private Long id; //编号
    private String username; //用户名
    private String password; //密码
    //getter/setter
}

2.在src/main/java/cn/tycoding/service/下创建BaseService.java通用接口,目的是简化service层接口基本CRUD方法的编写。

public interface BaseService<T> {

    // 查询所有
    List<T> findAll();

    //根据ID查询
    List<T> findById(Long id);

    //添加
    void create(T t);

    //删除(批量)
    void delete(Long... ids);

    //修改
    void update(T t);
}

以上就是我对Service层基本CRUD接口的简易封装,使用了泛型类,其继承接口指定了什么泛型,T就代表什么类。

3.在src/main/java/cn/tycoding/service/下创建UserService.java接口:

public interface UserService extends BaseService<User> {}

4.在src/main/java/cn/tycoding/service/impl/下创建UserServiceImpl.java实现类:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }
  
    //其他方法省略
}

5.在src/main/java/cn/tycoding/mapper/下创建UserMapper.javaMapper接口类:

@Mapper
public interface UserMapper {
    List<User> findAll();
}

如上,我们一定要使用@Mapper接口标识这个接口,不然Mybatis找不到其对应的XML映射文件。

6.在src/main/resources/mapper/下创建UserMapper.xml映射文件:

<?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.tycoding.mapper.UserMapper">

    <!-- 查询所有 -->
    <select id="findAll" resultType="cn.tycoding.entity.User">
        SELECT * FROM tb_user
    </select>
</mapper>

7.在src/main/java/cn/tycoding/controller/admin/下创建UserController.java

@RestController
public class UserController {
    @Autowired
    private UserService userService;
    
    @RequestMapping("/findAll")
    public List<User> findAll() {
        return userService.findAll();
    }
}

8.运行src/main/java/cn/tycoding/SpringbootApplication.java的main方法,启动springboot

在浏览器上访问localhost:8080/findAll即可得到一串JSON数据。

思考

看了上面一步步的讲解。你应该明白了,其实和SSM阶段的CRUD基本相同,这里我就不再举例其他方法。

下面我们讲解一下不同的地方:

实现页面跳转

因为Thymeleaf指定的目录src/main/resources/templates/是受保护的目录,其下的资源不能直接通过浏览器访问,可以使用Controller映射的方式访问,怎么映射呢?

1.在application.yml中添加配置

spring:
  thymeleaf:
    prefix: classpath:/templates/
    check-template-location: true
    suffix: .html
    encoding: UTF-8
    mode: LEGACYHTML5
    cache: false

指定Thymeleaf模板引擎扫描resources下的templates文件夹中已.html结尾的文件。这样就实现了MVC中关于视图解析器的配置:

    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

是不是感觉方便很多呢?但这里需要注意的是:classpath:后的目录地址一定要先加/,比如目前的classpath:/templates/

2.在Controller添加映射方法

    @GetMapping(value = {"/", "/index"})
    public String index() {
        return "home/index";
    }

这样,访问localhost:8080/index将直接跳转到resources/templates/home/index.html页面。

实现分页查询

首先我们需要在application.yml中配置pageHelper插件

pagehelper:
  pagehelperDialect: mysql
  reasonable: true
  support-methods-arguments: true

我这里使用了Mybatis的PageHelper分页插件,前端使用了ElementUI自带的分页插件:具体的教程请查看我的博客:SpringMVC+ElementUI实现分页查询

核心配置:

UserServiceImp.java

    public PageBean findByPage(Goods goods, int pageCode, int pageSize) {
        //使用Mybatis分页插件
        PageHelper.startPage(pageCode, pageSize);

        //调用分页查询方法,其实就是查询所有数据,mybatis自动帮我们进行分页计算
        Page<Goods> page = goodsMapper.findByPage(goods);

        return new PageBean(page.getTotal(), page.getResult());
    }

实现文件上传

这里涉及的无非就是SpringMVC的文件上传,详细的教程请参看我的博客:SpringMVC实现文件上传和下载

因为本项目中前端使用了ElementUI+Vue.JS技术,所以前端的文件上传和回显教程请看我的博客:SpringMVC+ElementUI实现图片上传和回显

除了代码的编写,这里还要在application.yml中进行配置:

spring:
  servlet:
    multipart:
      max-file-size: 10Mb
      max-request-size: 100Mb

这就相当于SpringMVC的XML配置:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="500000"/>
</bean>

使用Spring AOP切面编程实现简单的登录拦截器

本项目,我们先不整合Shiro和Spring Security这些安全框架,使用Spring AOP切面编程思想实现简单的登录拦截:

@Component
@Aspect
public class MyInterceptor {

    @Pointcut("within (cn.tycoding.controller..*) && !within(cn.tycoding.controller.admin.LoginController)")
    public void pointCut() {
    }
    @Around("pointCut()")
    public Object trackInfo(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        User user = (User) request.getSession().getAttribute("user");
        if (user == null) {
            attributes.getResponse().sendRedirect("/login"); //手动转发到/login映射路径
        }
        return joinPoint.proceed();
    }
}

解释

关于Spring AOP的切面编程请自行百度,或者你也可以看我的博客:Spring AOP思想。我们需要注意以下几点

  1. 一定要熟悉AspectJ的切点表达式,在这里:..*表示其目录下的所有方法和子目录方法。

  2. 如果进行了登录拦截,即在session中没有获取到用户的登录信息,我们可能需要手动转发到login页面,这里访问的是login映射。

  3. 基于2,一定要指定Object返回值,若AOP拦截的Controller return了一个视图地址,那么本来Controller应该跳转到这个视图地址的,但是被AOP拦截了,那么原来Controller仍会执行return,但是视图地址却找不到404了。

  4. 切记一定要调用proceed()方法,proceed():执行被通知的方法,如不调用将会阻止被通知的方法的调用,也就导致Controller中的return会404。

Preview

image
image
image
image


交流

如果大家有兴趣,欢迎大家加入我的Java交流技术群:671017003 ,一起交流学习Java技术。博主目前一直在自学JAVA中,技术有限,如果可以,会尽力给大家提供一些帮助,或是一些学习方法,当然群里的大佬都会积极给新手答疑的。所以,别犹豫,快来加入我们吧!


联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,812评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,626评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,144评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,052评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,925评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,035评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,461评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,150评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,413评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,501评论 2 307
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,277评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,159评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,528评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,868评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,143评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,407评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,615评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,485评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,676评论 6 342
  • 前言:学习SpringBoot不应该直接就是开始使用SpringBoot,如果直接拿来用肯定会有很多人不是很明白特...
    CoderZS阅读 74,734评论 10 217
  • 个人专题目录[https://www.jianshu.com/u/2a55010e3a04] 一、Spring B...
    Java及SpringBoot阅读 2,818评论 1 25
  • 你的眼 是世间最赫耀的星辰 星光照入凡尘 我只是个凡人 我当仰望你呀 若是白昼降临 你会遁去踪形 我当铭记你呀 若...
    吕风风快回家阅读 199评论 0 1