springboot 入门教程(1 )-helloword前端
springboot 入门教程-Thymeleaf(2)java
springboot 入门教程(3)-运行原理、关键注解和配置mysql
springboot 入门教程(4)--web开发(spring mvc和Thymeleaf模板,带源码)jquery
若是没看前面例子的同窗建议先看下,咱们这篇直接基于前面搭建的开发框架进行扩展。web
准备工做或知识储备:maven、spring、spring mvc 、mybatis,jquery、Bootstrap、sql,druid链接池spring
上一篇咱们已经完成了基于Thymeleaf模板的整合,为了下降门槛,咱们这个ssm的demo前端使用Bootstrap+jquery+BootStrap Table来实现。(BootStrap Table和VUE.js有点像,理解和学习起来相对容易,从开始接触到使用到实际项目也就半天时间,官方文档和demo都比较完善,虽然是英文,直接照葫芦画瓢就行)sql
后台源码(有小bug):springBoot+mybatis实现CRUD源码 完整源码:springBoot+mybatis实现CRUD源码-完整版 数据库
=========================华丽分割线==============================apache
先说步骤json
注:本篇不对单个框架进行深刻介绍,若是点赞关注多我再补充单个框架更详细的系列教程。
一、引入须要的jar包(mysql驱动、mybatis)
二、建库建表
三、编写实体bean
四、整合spring+mybatis(dao、servcei层)
五、使用spring mvc提供rest服务(controller)
六、前端框架整合调用rest服务
接下来开始撸代码吧
有坑(spring-tx必须引用,要不找不到DaoSurport)
<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.pxk.springboot</groupId> <artifactId>SpringBootDemo</artifactId> <version>0.0.1-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> <relativePath /> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- web容器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>1.5.6.RELEASE</version> </dependency> <!-- 须要单独引用否则会报 java.lang.NoClassDefFoundError: org/springframework/dao/support/DaoSupport --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.10.RELEASE</version> </dependency> <!-- spring jdbc支持, 不引用会报相似,具体类可能不一样NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSour --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.10.RELEASE</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.0</version> </dependency> <!-- mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> <!--日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- druid链接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.18</version> </dependency> </dependencies> </project>
数据使用的是myql5.5,客户端工具是Navicat 8(i表结构会包含在源码中)
一张普通的用户表,id采用数据库自增加,随便补充十条数据
get、set方法就不贴出来了,省得浪费篇幅
有个坑哦(构造函数必须有)
package com.pxk.springboot.domain; import java.util.Date; import com.fasterxml.jackson.annotation.JsonFormat; public class User { private Integer id; private String name; private Integer age; private String passWord; private char gender; //json日期格式化 @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") private Date regestDate; //默认构造函数不能少 ,若是没有会报ibatis.executor.ExecutorException: No constructor found public User() { super(); }
首先介绍下mybatis,用过的同窗应该都知道它是一个半自动的ORM框架,比Hibernate更灵活,可是开发效率没有Hibernate高,不过如今有不少开源的插件封装了crud操做,效率也还能够,目前开源中国比较热的是mybatis-plus,我也用过基本能知足需求,就是源代码没注释,文档少,遇到坑的时候就就比较浪费时间去理源码。
本文主要是在spring+mybatis的基础上使用springboot的整合方式而已,如搭建过常规spring+mybatis框架的就很好理解。
这部分也是本文的核心,首先咱们要编写mapper、而后定义接口,spring会自动调用接口对应的mapper中的方法(实现原理就是使用的反射--框架开发利器)
新建UserMapper接口(若是使用自动扫描接口名必须和xml的mapper文件名对应)
package com.pxk.springboot.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.pxk.springboot.domain.User; public interface UserMapper { List<User> findUserByPage(@Param("startIndex")int startIndex ,@Param("pageSize")int pageSize); User getUserById(int id); int updateUser(User user); int deleteUser(User user); int addUser(User user); }
这部分就是mybatis中的内容了,没有用到什么高级的特性,只是普通的单表操做,sql不严谨没必要纠结哈(动态sql,resultMap关联等都没用)
为了能让spring经过接口调用咱们的mapper中的sql语句,咱们必须让spring将mapper和接口对应上,那咱们在调用接口的时候,spring才知道去找哪一个mapper中的那个sql啊。首先,保证mapper的文件名和接口名要一致,不然是匹配不上的(固然咱们若是采用配置文件的方式是能够配置对应关系的,但这又和咱们使用SpringBoot的零配置思想背离了,因此我仍是认为约定优于配置)。其次,采用java配置,让Spring扫描mapper文件,我知道的至少有三种方式我这里就随便选了一种(注意:直接在springBootApplication上配置mapperScan后期打包部署的时候会有jar包扫描不到的问题,我跳的过坑,建议你们像我同样用别去采坑了,浪费了我一个下午的时间,开发环境能启动,打包后就不行了,这是mybaitis的一个bug,不知道后来修复没有)。我采用的是新建一个configration类的方式进行配置,详见下面代码:MyBatisConfig .java
UserMapper.xml(所在目录SpringBootDemo/src/main/resources/com/pxk/springboot/dao,这目录就是要被扫描的)
<?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.pxk.springboot.dao.UserMapper"> <!-- 使用别名的目的是让查询结果属性名称和实体bean的属性名对应,要不让绑定不上数据。要么就写resultMap这个你们本身搞了 --> <select id="findUserByPage" resultType="User"> select name,age,gender,pass_word passWord,regest_date regestDate from user limit #{startIndex},#{pageSize}; </select> <insert id="addUser" parameterType="User"> insert into User <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null and name!=''"> name, </if> <if test="gender != null and gender!=''"> gender, </if> <if test="password != null and password!=''"> pass_word, </if> <if test="regestDate != null"> regest_date, </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="name != null and name!=''"> #{name,jdbcType=VARCHAR}, </if> <if test="gender != null and gender!=''"> #{gender,jdbcType=CHAR}, </if> <if test="password != null and password''"> #{pass_word,jdbcType=VARCHAR}, </if> <if test="regestDate != null "> #{regest_date,jdbcType=Date}, </if> </trim> </insert> <select id="getUserById" parameterType="int" resultType="User"> select * from user where id=#{id} </select> <delete id="deleteUser" parameterType="User"> delete from user where id=#{id} </delete> </mapper>
MyBatisConfig .java
package com.pxk.springboot.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * mybatis 配置文件 * @author Administrator * */ @Configuration public class MyBatisConfig { @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); //指定扫描的mapper.xml文件所在目录 mapperScannerConfigurer.setBasePackage("com.pxk.springboot.dao"); return mapperScannerConfigurer; } }
为何配置实体类呢,由于spring经过反射调用接口之后要知道你返回的结果是什么类型啊,这些实体也须要托管到spring容器他才会给你封装好啊,因此咱们仍是得像spring+mybatis同样配置TypeAliases,只是配置方式不一样而已。那么采用springBoot集成该怎么作能,只须要在APPlication中覆盖默认配置sqlSessionFactory的方法,指定实体类所在路径便可,springBoot内部也是经过扫描的方式去加载的。具体代码以下:
Application.java
package com.pxk.springboot; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.log4j.lf5.util.Resource; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import com.alibaba.druid.pool.DruidDataSource; @SpringBootApplication //@MapperScan(basePackages = { "com.pxk.springboot.dao" })//这种扫描会有bug哦 public class Application { private final static Logger log=LoggerFactory.getLogger(Application.class); @Bean @ConfigurationProperties(prefix = "spring.datasource") //覆盖默认数据源 使用druid数据源 public DataSource dataSource() { return new DruidDataSource(); } @Bean public SqlSessionFactory sqlSessionFactory() { try { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); //扫描实体类所在包 sessionFactory.setTypeAliasesPackage("com.pxk.springboot.domain"); return sessionFactory.getObject(); } catch (Exception e) { return null; } } public static void main(String[] args) { SpringApplication.run(Application.class, args); log.info("启动成功"); } }
service层比较简单就是依赖注入之后调用没有任何业务逻辑,直接上代码
UserServiceImpl.java
package com.pxk.springboot.serivce.imp; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.pxk.springboot.dao.UserMapper; import com.pxk.springboot.domain.User; import com.pxk.springboot.serivce.UserService; @Service//注入成service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User getUser(String name) { return new User(name); } @Override public List<User> findUserByPage(int pageSize, int pageNum) { return userMapper.findUserByPage((pageNum-1)*pageSize, pageSize); } @Override public User getUserById(int id) { return userMapper.getUserById(id); } @Override public int updateUser(User user) { return userMapper.updateUser(user); } @Override public int deleteUser(User user) { return userMapper.deleteUser(user); } @Override public int addUser(User user) { return userMapper.addUser(user); } }
也没什么特殊的,直接上代码(你们有点spring mvc基础就能看懂的)
UserController.java(代码片断,先作个测试)
@RequestMapping("/findUserByPage") @ResponseBody//返回json格式数据 protected List<User> findUserByPage(int pageSize,int pageNum){ return userService.findUserByPage(pageSize, pageNum); }
运行程序,输入http://localhost:8081/user/findUserByPage?pageSize=5&pageNum=1测试controller的findUserByPage方法,结果以下