SpringBoot + Mybatis搭建完整的项目架构

时间:2024-02-01 22:41:03

准备工作:

  • Java开发环境 
  • 已安装 springboot 插件(STS)的 Eclipse
  • MySQL服务

 一、 创建 springboot 项目

1. 打开Eclipse  --> 左上角 File --> New --> Other ,到如下界面

如果没有 Spring Starter Project 这个选项,说明 Eclipse 的 springboot 插件没安装成功。本人win10系统,用 Eclipse 4.10、4.12 版本,

各尝试过在线安装、离线安装,都没有安装成功(有Spring/Spring Boot选项,但是没有Spring Starter Project)。最后使用Eclipse 4.7版

本才成功装上,找遍网上都没发现有人遇到过这个问题,真是服啦。

 2. 选择Spring Starter Project ,点击 Next,进入如下界面

 

3. 填写项目名称--Name选项,我这里改为 SpringBootDemo;

    填写包名--Package,我这里填写的是com.delav,其他的可以默认,点击 Next,进入如下界面

 

4. 勾选 Spring Web Starter 复选框,点击 Finish,可以看到项目的目录如下(忽略 log 目录)

如果发现 pom.xml 有个红叉,打开 pom.xml 文件后,红叉提示在第一行。这是 maven 的版本导致的,

解决方法是指定 maven 的版本,在 pom.xml 中找到如下这个标签

    <properties>
        <java.version>1.8</java.version>
    </properties>

添加一行来指定版本,添加后如下

    <properties>
        <maven-jar-plugin.version>3.0.0</maven-jar-plugin.version>
        <java.version>1.8</java.version>
    </properties>

然后红叉就没了,不然项目运行不了。

好了,一个 springboot 空项目创建好了,接下来就是在这个空的项目中填充东西进去了。

 

二、 完善详细目录结构与编码

如下图,在 com.delav (包)下,创建四个子包 controller、entity、mapper、service.

controller:接收请求

entity:存放 Java Bean 类

mapper:关联 SQL 语句

service:处理业务逻辑

纯属个人理解,处理流程:controller --> service --> mapper (entity的bean类用来存放和获取数据)

 

1.创建数据表

一个项目的第一步,都应该是先设计数据库,先设计一个表 user。

create table user(
    id int(16) not null auto_increment
    ,userName varchar(32) not null
    ,passWord varchar(32) not null
    ,realName varchar(64)
    ,primary key(id)
 ) engine=myisam default charset=utf8;           

然后插入几条数据

insert into user 
    (userName,passWord,realName) 
    values
    ("aaa","111","admin")
....

最后表的数据是这样,它位于名叫 \'java\' 的数据库中

 

2.修改配置文件 

修改 pom.xml。在这个配置文件中引入 mybatis、mysql 等依赖包,整个文件全部配置如下

<?xml version="1.0" encoding="UTF-8"?>
<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.delav</groupId>
    <artifactId>SpringBootDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringBootDemo</name>
    <description>Demo project for Spring Boot</description>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <maven-jar-plugin.version>3.0.0</maven-jar-plugin.version>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <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>
        
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>    
            <artifactId>mybatis-spring-boot-starter</artifactId>   
            <version>1.3.1</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

修改 resource 目录下 application.properties 文件。由于现在流行使用 .yml 来配置,就尝试一下这种配置,删除 application.properties,

并新建一个 application.yml 和  application-dev.yml 文件。

 application.yml文件内容如下。通过修改 active 的值可配多套环境,这里表示使用 application-dev.yml 的配置。如果再新建一个 application-test.yml ,

再把 dev 改为 test ,就表示使用 application-test.yml 的配置。

spring:
  profiles:
    active: dev

 application-dev.yml文件的内容如下,四个大块分别配置了端口号、MySQL数据库信息、mybatis信息、日志信息

server:
  port: 8080
  
spring:
  datasource:
    username: root
    password: 666666
    url: jdbc:mysql://localhost:3306/java?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:com/delav/mapper/*Mapper.xml
  type-aliases-package: com.delav.entity
  
logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n"    
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} - %msg%n"     
  file: log/info.log
  level:
    com: 
      delav: 
        info

 

3. 在 com.delav.entity 包下新建 User.java,内容如下

package com.delav.entity;

/**
 * @author Delav
 * @date   2019/06/27
 */
public class User {
    private Integer id;
    private String userName;
    private String passWord;
    private String realName;
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public String getUserName() {
        return userName;
    }
    
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    public String getPassWord() {
        return passWord;
    }
    
    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
    
    public String getRealName() {
        return realName;
    }
    
    public void setRealName(String realName) {
        this.realName = realName;
    }
}

 

4.在 com.delav.mapper包下新建 UserMapper.java 和 UserMapper.xml

UserMapper.java

package com.delav.mapper;

import com.delav.entity.User;

//import com.delav.mapper.IBaseMapper;

public abstract interface UserMapper {
    
    public abstract int InsertUser(User params);
    
    public abstract User SelectUser(int id);
}

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.delav.mapper.UserMapper">
    
    <resultMap id="BaseResultMap" type="com.delav.entity.User">
        <result column="id" jdbcType="INTEGER" property="id" />
        <result column="userName" jdbcType="VARCHAR" property="userName" />
        <result column="passWord" jdbcType="VARCHAR" property="passWord" />
        <result column="realName" jdbcType="VARCHAR" property="realName" />
    </resultMap>
    
    <select id="SelectUser" resultType="com.delav.entity.User">
        select * from user where id = #{id}
    </select>
    
    <insert id="InsertUser" parameterType="com.delav.entity.User" useGeneratedKeys="true" keyProperty="id">
        insert into user (userName,passWord,realName) 
                         values
                         (#{userName},#{passWord},#{realName})
    </insert>
    
</mapper>

 

5. 在 com.delav.service 包下新建 UserService.java,内容如下

package com.delav.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.delav.entity.User;
import com.delav.mapper.UserMapper;

/**
 * @author Delav
 * @date   2019/06/27
 */
@Service
public class UserService {
    
    // 日志器
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    
    @Autowired
    UserMapper userMapper;
    
    public String Sel(int id) {
        logger.info("开始查询数据");
        User user = userMapper.SelectUser(id);
        String result = "{" +
                "id=" + user.getId().toString() +
                ", userName=\'" + user.getUserName() + \'\\'\' +
                ", passWord=\'" + user.getPassWord() + \'\\'\' +
                ", realName=\'" + user.getRealName() + \'\\'\' +
                \'}\';
                
        return result;
    }
    
    public int Ins(User params) {
        logger.info("开始提交数据");
        Integer result = userMapper.InsertUser(params);
        //能获取插入的id是因为UserMapper.xml的insert语句新增了useGeneratedKeys和keyProperty参数
        Integer insertId = params.getId();
        System.out.println("插入数据的ID: " + insertId);
        System.out.println("insert结果: " + result);
        // insert返回结果为 1,表示插入了一条数据
        if (result == 1) {
            return insertId;
        } else {
            return 0;
        }
    }
}

 

6. 在 com.delav.controller包下新建 UserController.java,内容如下

package com.delav.controller;

import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.JsonNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.RestController;
import org.springframework.web.bind.annotation.RequestBody;

import com.delav.service.UserService;
import com.delav.entity.User;


/**
 * @author Delav
 * @date   2019/06/27
 */
@RestController
@RequestMapping("/testSpring")
public class UserController {
    
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private UserService userService;
    
    @RequestMapping(value= {"getUser/{id}"}, method={org.springframework.web.bind.annotation.RequestMethod.GET})
    public String GetUser(@PathVariable int id) {
        logger.info("查询数据ID为: " + id);
        String result = userService.Sel(id);
        logger.info("查询数据成功");
        return result;
    }

    @RequestMapping(value= {"postUser"}, method={org.springframework.web.bind.annotation.RequestMethod.POST})
    public String PostUser(@RequestBody String params) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(params);
        logger.info("解析数据成功");
        User user = new User();
        // user.setId(rootNode.path("id").asInt());
        user.setUserName(rootNode.path("userName").asText());
        user.setPassWord(rootNode.path("passWord").asText());
        user.setRealName(rootNode.path("realName").asText());
        logger.info("数据转为实体bean成功");
        Integer result = userService.Ins(user);
        if (result != 0) {
            logger.info("数据入库成功");
            return "Commit Success";
        } else {
            logger.info("数据入库失败");
            return "Commit Fail";
        }
        
    }
}

 

7. 在 com.delav包下的启动文件SpringBootDemoApplication.java,添加一个注解,让项目启动的时候扫描 mapper 的路径,内容如下

package com.delav;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages="com.delav.mapper")
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }

}

添加了 @MapperScan(basePackages="com.delav.mapper")

 

整个项目已经完成了。现在可以启动项目,然后测试一下它的两个接口。我这里使用的是 Postman 来测试

启动: 选中该项目 --> 单击右键 --> Run As --> Spring Boot App,启动成功如下。输出格式这样是因为在application-dev.yml的日志信息配置中改了输出格式

 

Postman测试 get 请求如下:

 控制台输出:

 

Postman测试 post 请求如下:

 

控制台输出:

看下数据库是否新增了这条数据,确实新增了记录

 

三、单元测试

 

1. 编写单元测试代码

没有装有Postman,那我们就写个单元测试来测一下

进入 src 的 test 目录,找到 com.delav 下的 SpringBootDemoApplicationTests.java,编写内容如下

package com.delav;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import java.util.HashMap;

import org.junit.Before;
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.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootDemoApplicationTests {
    
    @Autowired
    private WebApplicationContext wac;
    // 模拟对Controller发起请求的对象
    private MockMvc mvc;
    
    @Before
    public void Setup() throws Exception {
        // mvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }
    
    @Test
    public void getTest() throws Exception {
        
          HashMap<String, String> result = new HashMap<String, String>(); 
          // 请求ID和对应的预期结果
          result.put("1", "{id=1, userName=\'aaa\', passWord=\'111\', realName=\'admin\'}");
          result.put("2", "{id=2, userName=\'bbb\', passWord=\'222\', realName=\'admin\'}");
          result.put("3", "{id=3, userName=\'ccc\', passWord=\'333\', realName=\'admin\'}");
          result.put("5", "{id=5, userName=\'tom\', passWord=\'999\', realName=\'delav\'}");
          
          for (String key: result.keySet()) { 
              // 执行请求 
              String path ="/testSpring/getUser/" + key; 
              System.out.println("请求URL: " + path);
              mvc.perform(MockMvcRequestBuilders.get(path)
                              .contentType(MediaType.APPLICATION_JSON_UTF8)
                              .accept(MediaType.APPLICATION_JSON)
                      ) 
                      // 响应状态 
                      .andExpect(status().isOk()) 
                      // 响应内容
                      .andExpect(content().string(equalTo(result.get(key)))); 
              }     
    }
    
    @Test
    public void postTest() throws Exception {
        
        String params = "{\"userName\":\"tom\", \"passWord\":\"999\", \"realName\":\"333\"}";
        
        mvc.perform(MockMvcRequestBuilders.post("/testSpring/postUser")
                        .accept(MediaType.APPLICATION_JSON_UTF8)
                        .content(params)
                )
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("Commit Success")));
    }
        
}

 

2. 运行测试

选中该项目 --> 单击右键 --> Run As --> JUnit Test ,结果如下

 

该Demo的github地址:https://github.com/delav/SpringBootDemo

这个项目会不断更新,当你阅读该文章时,可能会跟该文章不一样。