SpringBoot + Mybatis搭建完整的项目架构
准备工作:
- 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
这个项目会不断更新,当你阅读该文章时,可能会跟该文章不一样。