来一个springboot+mybatis+mysql+swagger3的示例

一、介绍

  上2篇分别写了Springboot入门以及给Springboot加swagger,本篇将在此基础上进行DB操作
  本文为整合springboot+mybatis+mysql+swagger3的示例,完整写了一个关于用户增删改查的demo 整个示例采用rest api详细完成了一个关于用户的基本增(post)、删(delete)、改(put)、查(get)过程 另外其中详细写了采用mybatis进行相关db处理
  本文代码git地址:https://gitee.com/jimmyTown_admin_admin/springboot-mybatis-mysql-demo.git

二、软件架构

 1. 本demo使用时下最流程的rest架构向外提供服务,采用GET/POST/PUT/DELETE来完成demo的增删改查 
 2. 采用2.5.5版本的sprintboot大大简化开发过程 
 3. 本文内部有关于springboot结合swagger3的整体使用,除ui controller层有注释外,同时将dto、entity等也加上对应注释,便于理解 
 4. 本文结果sprintboot及mybatis完整demo演示 
 5. 本文中加入对应的lombok组件,简化了大量的get/set操作

三、准确工作及说明

  1. 准确数据库脚本
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
 `id` int(0) NOT NULL AUTO_INCREMENT,
 `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
 `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
 `age` int(0) NULL DEFAULT NULL,
 `sex` varchar(8) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
 PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (3, 'bob', '333666', 32, ' 男');
INSERT INTO `t_user` VALUES (4, 'ruby', '333333', 25, ' 女');
INSERT INTO `t_user` VALUES (5, 'test', '11', 11, '11');
INSERT INTO `t_user` VALUES (6, 'jimmy', '000000', 33, '男');

SET FOREIGN_KEY_CHECKS = 1;
  1. 大概运行的示例图
    image.png
  2. Swagger运行结果
    image.png
  3. 项目代码结构
    image.png

四、整体代码详细说明

  1. 本文是采用springboot+mybatis+mysql+swagger3来做的,故第一步在建springboot项目时,需要添加相关spring web、Thymeleaf、Mybatis Framework、MySQL Driver,另外为了文件也添加了Lombok,故最终pom中依赖代码如下:
<dependencies>
        <!--springboot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--加入thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--加入mybatis支持-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!--加入mysql数据库依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--加入lombok支持-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--加入swagger3支持-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
    </dependencies>

相关依赖添加ok后,采用mvn reimport使依赖包正常拉取并编译成功

  1. 按项目代码结构中,我们依次讲解相关代码
    • controller层
      该处用于向外提供接口服务,此处添加UserController的api接口,实现增删改查,相关注解详细请参看上2篇说明,此处先贴入代码
     /**
* 在接口类上添加@Api(tags = "操作接口"),tags的值是该类的作用,在文档页面会显示,value不会显示
* 在需要生成文档的接口上添加注解@ApiOperation
* 对请求参数添加@ApiParam
*/
@Api(tags = "用户控制器")
@RestController
@RequestMapping("user")
public class UserController {
   // 接口服务注入
   @Autowired
   private UserService userService;

   @ApiOperation("查找所有用户列表")
   @GetMapping(value = {"/getUserList"})
   public List<User> getUserList() {
       return userService.getUserList();
   }

   @ApiOperation("通过用户Id查找用户信息")
   @GetMapping(value = {"/getUser"})
   public User getUser(@ApiParam(name = "id", value = "用户Id") int id) {
       return userService.getUser(id);
   }

   @ApiOperation("通过用户姓名查询用户列表")
   @GetMapping("/getUserByUserName")
   public List<User> getUserByUserName(@ApiParam(name = "userName", value = "用户姓名") String userName) {
       return userService.getUserByUserName(userName);
   }

   @ApiOperation("添加用户信息")
   @PostMapping("/addUser")
   public String Add(@ApiParam(name = "user", value = "用户信息") UserRequestDto user) throws Exception {
       try {
           // 先判断用户名存在不存在如果存在,则报错,否则添加
           if (null == user || "".equals(user.getUsername())) {
               return "用户或用户信息不得为空";
           }
           List<User> users = userService.getUserByUserName(user.getUsername());
           if (null != users && users.size() > 0) {
               return "用户名已存在";
           }
           User userItem = new User();
           userItem.setUsername(user.getUsername());
           userItem.setPassword(user.getPassword());
           userItem.setAge(user.getAge());
           userItem.setSex(user.getSex());
           userService.addUser(userItem);
           return "用户" + user.getUsername() + "添加成功";
       } catch (Exception ex) {
           return "异常信息:" + ex.getMessage();
       }
   }

   @ApiOperation("更新用户信息")
   @PutMapping("/updateUser")
   public String Update(@ApiParam(name = "user", value = "用户信息") User user) throws Exception {
       try {
           if (null == user || "".equals(user.getUsername()) || 0 == user.getId()) {
               return "用户或用户信息不得为空";
           }
           if ("".equals(user.getPassword()) || user.getPassword().length() < 5) {
               return "用户密码至少为5位";
           }
           User userItem = userService.getUser(user.getId());
           if (null == userItem) {
               return "用户不存在,无法更新,请先添加";
           }

           userService.updateUser(user);
           return "用户" + user.getUsername() + "信息更新成功";
       } catch (Exception ex) {
           return "异常信息:" + ex.getMessage();
       }
   }

   @ApiOperation("删除用户信息")
   @DeleteMapping("/delete")
   public ApiResult delete(@ApiParam(name = "id", value = "用户Id") @RequestParam(value = "id") int id) {
       ApiResult result = new ApiResult();
       if (id <= 0) {
           result.setCode("-1");
           result.setMessage("非法id");
           return result;
       }
       return userService.delete(id);
   }
}
  • service
    service层一般包括接口服务,接口服务实现类,一般主要用于业务服务实现,这里service层包括服务实现类UserServiceImpl以及接口UserService,代码分别如下:
    • UserService代码
public interface UserService {
    /**
     * 通过所有用户列表
     *
     * @return
     */
    List<User> getUserList();

    /**
     * 通过用户id查询用户信息
     *
     * @param id
     * @return
     */
    User getUser(int id);

    /**
     * 通过用户姓名查询用户信息
     *
     * @param userName
     * @return
     */
    List<User> getUserByUserName(String userName);

    /**
     * 添加新用户
     *
     * @param user
     */
    void addUser(User user);

    /**
     * 更新用户信息
     *
     * @param user
     */
    void updateUser(User user) throws Exception;

    /**
     * 删除用户信息
     *
     * @param id
     * @return
     */
    ApiResult delete(int id);
}

UserService代码

// 加入service,将实现交给spring来管理
@Service
public class UserServiceImpl implements UserService {
    // 加入dao的注入
    @Autowired
    private UserDao userDao;

    /**
     * 获取所有用户列表
     *
     * @return
     */
    @Override
    public List<User> getUserList() {
        return userDao.getUserList();
    }

    /**
     * 通过用户id查询用户信息
     *
     * @param id
     * @return
     */
    @Override
    public User getUser(int id) {
        return userDao.getUserById(id);
    }

    /**
     * 通过用户姓名查询用户信息
     *
     * @param userName
     * @return
     */
    @Override
    public List<User> getUserByUserName(String userName) {
        return userDao.getUserByUserName(userName);
    }

    /**
     * 添加新用户
     *
     * @param user
     */
    @Override
    public void addUser(User user) {
        userDao.addUser(user);
    }

    /**
     * 添加新用户
     *
     * @param user
     */
    @Override
    public void updateUser(User user) throws Exception {
        if (null == user || "".equals(user.getUsername())) throw new Exception("用户信息不得为空");

        User userOriginal = userDao.getUserById(user.getId());
        if (null == userOriginal) throw new Exception("当前用户不存在");

        userOriginal.setAge(user.getAge());
        userOriginal.setSex(user.getSex());
        userOriginal.setUsername(user.getUsername());
        userOriginal.setPassword(user.getPassword());

        userDao.updateUser(userOriginal);
    }

    @Override
    public ApiResult delete(int id) {
        userDao.delete(id);

        ApiResult apiResult = new ApiResult();
        apiResult.setSuccess(true);
        apiResult.setCode("200");

        return apiResult;
    }
}
  • dao
    dao层为数据访问层,主要是用于与数据库交互的,类似于仓储层,这里UserDao主要是处理对应的数据库与用户信息的交互,具体代码如下:
/**
 * 用户映射接口(@Repository注解是把这个接口的一个实现类交给spring管理)
 */
@Repository
public interface UserDao {
    /**
     * 查找所有用户列表
     *
     * @return
     */
    List<User> getUserList();

    /**
     * 通过id查找用户
     *
     * @param id
     * @return
     */
    User getUserById(int id);

    /**
     * 通过用户名查询用户列表
     *
     * @param userName
     * @return
     */
    List<User> getUserByUserName(String userName);

    /**
     * 添加新用户
     *
     * @param user
     */
    void addUser(User user);

    /**
     * 更新用户信息
     *
     * @param user
     */
    void updateUser(User user);

    /**
     * 删除用户信息
     * @param id
     */
    void delete(int id);
}
  • mapper
    mapper主要是添加相关映射关系,来实现数据库的增删改查功能,采用mybatis的mapper文件配置方式,不使用dao接口注解方式,此处的UserMapper.xml,在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="com.jimmy.springbootmybatismysqldemo.dao.UserDao">
    <select id="getUserList" resultType="com.jimmy.springbootmybatismysqldemo.entity.User">
        SELECT * FROM t_user
    </select>

    <select id="getUserById" parameterType="Integer" resultType="com.jimmy.springbootmybatismysqldemo.entity.User">
        SELECT * FROM t_user WHERE id = #{id}
    </select>

    <select id="getUserByUserName" parameterType="String" resultType="com.jimmy.springbootmybatismysqldemo.entity.User">
        SELECT * FROM t_user WHERE userName = #{userName}
    </select>

    <insert id="addUser" parameterType="User" useGeneratedKeys="true" keyColumn="id">
       insert into t_user(username, password,age, sex) values(#{username},#{password}, #{age}, #{sex})
    </insert>

    <update id="updateUser" parameterType="User">
       update t_user set username=#{username}, password=#{password}, age=#{age}, sex=#{sex} where id=#{id}
    </update>

    <delete id="delete" parameterType="Integer">
       delete from t_user where id=#{id}
    </delete>
</mapper>
  • entity
    entity层一般用来存放实体,该部分一般即是用来完成数据库对象与实体对象转换的桥梁,这里实体User,为了方便以及考虑后面Swagger中注释的显示问题,需引入lombok及swagger相关包,可以详细看代码,不赘述,实体代码如下:
@Data
@ApiModel(value = "User", description = "用户信息")
public class User {
    /**
     * 用户id
     */
    @ApiModelProperty("用户id")
    private int id;
    /**
     * 用户姓名
     */
    @ApiModelProperty("用户姓名")
    private String username;
    /**
     * 用户密码
     */
    @ApiModelProperty("用户密码")
    private String password;
    /**
     * 年龄
     */
    @ApiModelProperty("年龄")
    private int age;
    /**
     * 性别
     */
    @ApiModelProperty("性别")
    private String sex;
}
  • utils
    utils中一般用于处理通用功能、帮助类等的,此处我们只是添加swagger3,代码上期说过,这里就直接贴代码
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        //swagger设置,基本信息,要解析的接口及路径等
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                //设置通过什么方式定位需要自动生成文档的接口,这里定位方法上的@ApiOperation注解
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                //接口URI路径设置,any是全路径,也可以通过PathSelectors.regex()正则匹配
                .paths(PathSelectors.any())
                .build();
    }

    //生成接口信息,包括标题、联系人,联系方式等
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Swagger3接口文档")
                .description("如有疑问,请联系开发工程师")
                .contact(new Contact("jimmy", "https://www.jianshu.com/u/6800502d6a89", "52247053@qq.com"))
                .version("1.0")
                .build();
    }
}
  • dto
    dto层一般存储的为接口交互的数据传输对象,用来方便输入输出对象封装等,这里主要有2个,一个用户的dto:UserRequestDto,一个接口服务返回的结果:ApiResult,具体代码如下:
@Data
@ApiModel(value = "User", description = "用户信息")
public class UserRequestDto {
    /**
     * 用户姓名
     */
    @ApiModelProperty("用户姓名")
    private String username;
    /**
     * 用户密码
     */
    @ApiModelProperty("用户密码")
    private String password;
    /**
     * 年龄
     */
    @ApiModelProperty("年龄")
    private int age;
    /**
     * 性别
     */
    @ApiModelProperty("性别")
    private String sex;
}
@Data
@ApiModel(value = "服务执行结果", description = "服务执行结果")
public class ApiResult {
    @ApiModelProperty("是否执行成功")
    private boolean isSuccess;
    @ApiModelProperty("执行结果编码")
    private String code;
    @ApiModelProperty("错误信息")
    private String message;
}

五、具体代码已上传git

git地址:https://gitee.com/jimmyTown_admin_admin/springboot-mybatis-mysql-demo

六、文章参考文献地址:

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

推荐阅读更多精彩内容