目标
1. 使用SpringBoot集成Mybatis对数据库中数据实现CURD
2. 学会Post方式请求测试
3. 学会使用Swagger2来生成API文档
咱们了解完Spring Boot的Restful服务,咱们继续用Spring Boot操作数据库,SpringBoot能操作很多数据库,MySQL、Oracle、SQL Server、MongoDB、Redis等等。我们使用多种方式操作MySQL即可。多种方式分别为:
此方式不讲
pom.xml中添加如下MySQL依赖,既然要操作数据库,肯定需要Mysql的依赖。
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.38version>
dependency>
-- 创建数据库
create database if not exists test;
-- ----------------------------
-- Table structure for `test`.`stu`
-- ----------------------------
DROP TABLE IF EXISTS `test`.`stu`;
CREATE TABLE `test`.`stu` (
`stu_id` bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT 'stu id',
`stu_name` varchar(30) DEFAULT NULL COMMENT 'stu name',
`stu_sex` char(1) DEFAULT '0' COMMENT 'stu sex 0:unknown 1:male 2:female',
`stu_age` smallint(6) DEFAULT '0' COMMENT 'stu age',
PRIMARY KEY (`stu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of stu
-- ----------------------------
com/qianfeng/entry包下创建Stu类即可。
package com.qianfeng.entry;
/**
* stu的实体类
*/
public class Stu {
private long stu_id;
private String stu_name;
private char stu_sex;
private int stu_age;
//快捷键生产getter和setter方法即可
}
spring:
datasource:
url: jdbc:mysql://hadoop01:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
#注意
1、yml文件配置格式需要严格注意,每一个值的前面是一定有一个空格的。格式也是严格缩进。
2、springboot可以自动通过url识别数据库类型,所以可以不用显示写driver-class-name.
大家在学习MySQL的时候学习过JDBC,这儿的JDBCTemplate跟MySQL的JDBC差不多一样。是SpringBoot操作MySQL的一种方式。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
package com.qianfeng.service;
import com.qianfeng.entry.Stu;
import java.util.List;
import java.util.Map;
/**
* stu接口类
*/
public interface StuService {
/**
* 增加一个学生
* @param stu
* @return
*/
int addStu(Stu stu);
/**
* 修改学生信息
* @param stu
* @return
*/
int updateStu(Stu stu);
/**
* 获取单个学生信息
* @param stu_id
* @return
*/
Stu getStu(long stu_id);
/**
* 获取全部学生信息
* @return
*/
List<Map<String, Object>> ListAllStu();
/**
* 根据stu_id删除学生
* @param stu_id
* @return
*/
int deleteStu(long stu_id);
}
package com.qianfeng.service.impl;
import com.qianfeng.entry.Stu;
import com.qianfeng.service.StuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
/**
* stu服务实现
* 1、需要注解为Service
* 2、类中需要注解JdbcTemplate
*/
@Service
public class StuServiceImpl implements StuService {
//注解jdbc的模板
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int addStu(Stu stu) {
String sql = "insert into stu(stu_id,stu_name,stu_sex,stu_age) values(null,?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder(); //自动生成主键
//int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
//第一个参数psc:创建ps语句的一个接口 第二个参数generatedKeyHolder:生成的主键
int resRow = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(sql,new String[]{"stu_id"});
ps.setString(1,stu.getStu_name());
ps.setInt(2,stu.getStu_sex());
ps.setInt(3,stu.getStu_age());
return ps;
}
},keyHolder);
System.out.println("操作记录值:"+resRow+" 主键值:"+keyHolder.getKey());
return Integer.parseInt(keyHolder.getKey().toString());
}
@Override
public int updateStu(Stu stu) {
String sql = "update stu set stu_name=?,stu_sex=?,stu_age=? where stu_id=?";
int res = jdbcTemplate.update(sql, new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1,stu.getStu_name());
preparedStatement.setInt(2,stu.getStu_sex());
preparedStatement.setInt(3,stu.getStu_age());
preparedStatement.setLong(4,stu.getStu_id());
}
});
return res;
}
@Override
public Stu getStu(long stu_id) {
String sql = "select * from student where stu_id = ? ";
//也可以使用别的方法实现
List<Stu> stus = jdbcTemplate.query(sql,new Object[]{stu_id}, new StudentRowMapper());
Stu stu = null;
if(!stus.isEmpty()){
stu = stus.get(0);
}
return stu;
}
@Override
public List<Map<String, Object>> ListAllStu() {
String sql = "select * from stu";
List<Map<String, Object>> listStus = jdbcTemplate.queryForList(sql);
return listStus;
}
@Override
public int deleteStu(long stu_id) {
String sql = "delete from stu where stu_id = ?";
return jdbcTemplate.update(sql,stu_id);
}
}
/**
* stu行映射。(将rs转换成Stu对象)
*/
class StudentRowMapper implements RowMapper<Stu> {
@Override
public Stu mapRow(ResultSet resultSet, int i) throws SQLException{
Stu stu = new Stu();
stu.setStu_id(resultSet.getInt("stu_id"));
stu.setStu_name(resultSet.getString("stu_name"));
stu.setStu_sex(resultSet.getInt("stu_sex"));
stu.setStu_age(resultSet.getInt("stu_age"));
return stu;
}
}
package com.qianfeng.controller;
import com.qianfeng.entry.Stu;
import com.qianfeng.service.StuService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
*stu学生控制器
*/
@RestController
@RequestMapping("/stu")
public class StuController {
//注解stu服务
@Autowired
private StuService stuService;
//http://localhost:8080/stu/
@RequestMapping(value = "/", method = RequestMethod.POST)
public int addStu(Stu stu){
System.out.println(stu.getStu_name());
int res = stuService.addStu(stu);
return res;
}
@RequestMapping(value = "/", method = RequestMethod.PUT)
public int updateStu(Stu stu){
System.out.println(stu.getStu_id());
int isHas = stuService.isHasStu(stu.getStu_id());
int res = 0;
if (isHas==1){
res = stuService.updateStu(stu);
}
return res;
}
@RequestMapping(value = "/{stu_id}", method = RequestMethod.GET)
public Stu getStuById(@PathVariable int stu_id){
Stu stu = stuService.getStu(stu_id);
return stu;
}
@RequestMapping(value = "/", method = RequestMethod.GET)
public List<Map<String, Object>> listAllStu(){
List<Map<String, Object>> list = stuService.ListAllStu();
return list;
}
@RequestMapping(value = "/{stu_id}", method = RequestMethod.DELETE)
public int deleteStu(@PathVariable int stu_id){
System.out.println(stu_id);
int res = stuService.deleteStu(stu_id);
return res;
}
}
启动应用主类,即可测试。因为有以一些是post和delete请求,所以建议postman工具进行测试。
添加学生
点击开postman—>new—>request 或者点击 + —>新建连接即可。注意下面的红框中的内容
更新学生
更新是一个put请求,注意,没有填写字段将会是默认值。
获取学生
查询学生是get请求,可以放到普通浏览器测试都可以。
获取所有学生
先添加学生名字、性别、年龄信息:haoge 1 20。然后再查询所有学生。
删除学生
删除是delete请求。
咱们的API编写出来后,那很多的API怎么管理呢?采用execle、word和其他的共享文档等方式来管理都有一定的局限,此时,Swagger就是一个比较合适的在线API生成与管理插件。
Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。简单来说,Swagger是一个功能强大的接口管理工具,并且提供了多种编程语言的前后端分离解决方案。
Swagger目前有33个存储仓库,主要包含了以下三个子项目:
注意:
- RestAPI格式是根据请求的方式决定本次请求操作的类型,如:get–>读,post–>写(增、删、改),put–>修改,delete–>删除
- OpenAPI与语言无关,只是一种规范,可以使用yaml和json格式进行编写,这样更利于开发者们阅读与使用。
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.2.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.2.2version>
dependency>
在controller层(包下)新建MySwagger2.java
或者 在项目根目录下新建 com/qianfeng/config 包并添加一个 SwaggerConfig.java
配置类。代码如下:
package com.qianfeng.controller;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* api文档生成类
* 注意:如果我们application.yml中配置context-path: /qf,则访问地址也需要加根目录。则swagger访问地址为:
* http://localhost:8080/qf/swagger-ui.html
*/
@Configuration
@EnableSwagger2
public class MySwagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.qianfeng")) //扫描api的根目录
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("JdbcTemplate-增删改查-API")
.description("第一个Spring Boot JdbcTemplate 增删改查 API文档列表")
.termsOfServiceUrl("http://www.baidu.com/")
.contact("qianfeng")
.version("1.0")
.build();
}
}
在StuController.java中的每个服务上添加注解@ApiOperation(value=“”, notes=“”) value的值为api文档中名称,notets值为说明。
启动服务,访问swagger页面:http://localhost:8080/swagger-ui.html
添加学生测试
点击POST /stu/ 添加学生
—> Try it out
—> 按下图填写参数
—>Execute
—>验证结果。
文档生成器测试完毕。
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射
。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。MyBatis是一款半ORM框架,相对于Hibernate这样的完全ORM框架,MyBatis显得更加灵活,因为可以直接控制SQL语句,所以使用MyBatis可以非常方便的实现各种复杂的查询需求。当然了,有利必有弊,也正因为太过自由,所以多复杂的SQL都得自己写。
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.3.1version>
dependency>
现在项目的根目录中创建mapper包,并在该包下创建StuMapper.java类。实体Bean我们任然用Stu。
package com.qianfeng.mapper;
import com.qianfeng.entry.Stu;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* Stu接口及实现;;
* 采用直接方式实现;;也可以采用xml配置实现。本次采用注解方式实现。
* 常用注解 :
* @Select
* @Insert
* @Update
* @Delete
*/
@Mapper
public interface StuMapper {
/**
* 参数时和stu绑定,所以#{对象属性} ;一定是对象属性,否则取不出来值。
* @param stu
* @return
*/
@Insert("INSERT INTO stu(stu_name, stu_sex, stu_age) VALUES(#{stu_name}, #{stu_sex}, #{stu_age})")
int addStu(Stu stu);
@Select("SELECT * FROM stu WHERE stu_id = #{stuid}")
Stu findStuById(@Param("stuid") int stuid);
@Select("SELECT * FROM stu")
List<Stu> findAllStu();
@Delete("delete from stu where stu_id=#{stuid}")
int deleteStu(int stuid);
}
为清晰明了,所以单独写一个控制器,在controller包中创建一个控制器MybatisStuController.java
.
package com.qianfeng.controller;
import com.qianfeng.entry.Stu;
import com.qianfeng.mapper.StuMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*mybatis整合springboot的控制器
*/
@RestController
@RequestMapping(value = "/mbstu")
public class MybatisStuController {
//注解接口到控制器
@Autowired
StuMapper stuMapper;
/**
* Post请求也可以直接与对象类绑定。遵守如下规则:
* 1、但需要参数名一致;
* 2、不支持json格式;
* 3、只支持form-data和x-www.form-urlencoded格式;
* @param stu
* @return
*/
@RequestMapping(value = "/add",method = RequestMethod.POST)
public int addStu(Stu stu){
return stuMapper.addStu(stu);
}
/**
* PathVariable注解
* 1、需要在url中加{参数名}。如: /{stuid}/{stuname},使用PathVariable注解几个加几个
* 2、使用PathVariable注解的,不能使用defaultValue属性设置参数默认值。
* 3、用PathVariable注解的,只能是Get请求
* @param stuid
* @return
*/
@RequestMapping(value = "/{stuid}",method = RequestMethod.GET)
public Stu findStuById(@PathVariable(value = "stuid",required = true) int stuid){
return stuMapper.findStuById(stuid);
}
/**
* 查询所有学生
* @return
*/
@RequestMapping(value = "/",method = RequestMethod.GET)
public List<Stu> findAllStu(){
return stuMapper.findAllStu();
}
/**
* 查询所有学生
* @return
*/
@RequestMapping(value = "/delete/",method = RequestMethod.DELETE)
public int deleteStu(@RequestParam(value = "stuid",required = false,defaultValue = "0") int stuid){
return stuMapper.deleteStu(stuid);
}
}
启动服务测试。访问swagger页面即可。
查询所有学生
查找单个学生
增加学生
删除学生
到此为止,Spring Boot、Mybatis和Swagger2整合完毕。