demo4:在Springboot框架上搭建访问mysql数

经历了各种不可控与不可预知的磨难(包括但不限于idea闪退、navicat闪退、系统闪退、莫名其妙的bug无数、疯狂搜索各种注解是为什么无数、jdbcTemplate为什么失效了、@autowired为什么失效了,等等!),终于搞定了这个主题!!!!

本篇就来手把手教你搞定这个应用!


  1. 大致思路

首先,大致总结一下,如果你想要从零开始,利用springboot框架,写一个能访问数据库并进行crud操作的,能给RESTful风格的接口的应用,应该怎么做:

  1. 安装一个mysql环境,不会/不喜欢使用命令行的话,需要再装一个数据库软件,例如navicat或者mysqlworkbench,本文以navicat来说明
  2. 建数据库、数据表、可访问数据库的用户名+密码(最好不要直接给root权限)
  3. 推荐:装一个postman,方便请求接口查看结果
  4. 初始化一套springboot的框架,装上我们需要的插件依赖(后续会提到)
  5. application.properties文件中,可以配置上连接数据库需要用的信息,也可以配置上想要应用启动所用的端口号
  6. 写三个java类:controllerentityservice
  • entity:用于写数据表对应的字段在java里面对应的对象,需要具有Bean的特征:getter、setter等;
  • service:用于写mysql语句与对应的jdbc请求
  • controller:用于调用service,制作对应的get/post接口
  1. 启动运行整个app
  1. 建mysql数据库

懂得怎么搞这玩意的可以跳过这一part~

另外,此处不讨论如何本地搭一个docker,并在容器里面安装mysql

2.1 下载一个适合你的电脑版本的mysql

参考教程:blog.csdn.net/baidu_26315…

2.2 下载一个mysql软件

免费:mysqlWorkbench
付费:navicat

2.3 建库、表、数据、用户

2.3.1 启动mysql

image.png

image.png

2.3.2 navicat连接数据库

image.png

2.3.3 新建数据库 spring_example

image.png

2.3.4 新建数据表 user

image.png

image.png

2.3.5 填充数据

image.png

2.3.6 新建用户,用于spring访问该数据库

选择新建用户
image.png

添加常规信息,设置用户的名称和密码
image.png

添加用户的对象权限
image.png

勾选所需要的数据库的权限
image.png

  1. 创建springboot工程

3.1 初始化一个springboot项目

利用官网生成一个springboot项目:start.spring.io/

所需要的依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
xml复制代码<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.13</version>
<scope>compile</scope>
</dependency>
</dependencies>

重点依赖说明:

  • lombok:是一个可以简化代码的库,可以帮助你不用自己去写getter()或者setter(),就能自动在调试编译的时候,生成Bean的相关方法。可以参考这篇文章来理解:# 整合Lombok简化接口对象代码
  • spring-boot-starter-web:用于创建springboot的web服务,可以提供REST风格相关api
  • mysql-connector-javaspring-boot-starter-jdbc:提供了mysql的JDBC连接方法,尤其是JdbcTemplate

然后,我们还需要配置这个工程项目和我们创建的数据库的连接信息:

image.png

1
2
3
4
5
ini复制代码# mysql connection settings
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/spring_example
spring.datasource.username=spring
spring.datasource.password=spring
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3.2 新建相关的package和java class

image.png

正如本篇开头所提到的,按照规范来说,java代码应该分好层次,所以我们会建立以上所示的三个package,分别代表以下含义:

  • entity:用于写数据表对应的字段在java里面对应的对象,需要具有Bean的特征:getter、setter等;
  • service:用于写mysql语句与对应的jdbc请求
  • controller:用于调用service,制作对应的get/post接口

然后分别对应创建相应的class,下面我们会分别讲解:

3.2.1 user.class

首先,我们要创建一个对应了数据表字段内容的类,便于我们从数据库取得数据后,可以存放在实例化的对象中。

常规来说,我们需要声明了一堆private的变量,然后写一些公共的getter()、setter()方法,来实现一个标准的java bean,便于我们在其他方法中实例化这个类型的对象。

但是,下面的代码就说明了,我们可以轻轻松松的用lombok的方法,添加@Data注解,让自己不用再写一长串getter()、setter(),而让代码在编译的时候给我们自动生成这些东西。

1
2
3
4
5
6
7
8
9
10
java复制代码package shenling.example.springbootJDBC.entity;

import lombok.Data;

@Data
public class user {
private Integer id;
private String firstname;
private String lastname;
}

要注意的是,如果要让lombok生效,还需要让idea中下载并开启插件:lombok

image.png

3.2.2 userService.class

在service层中,我们提供针对这个表的JDBC连接服务。基本上下面代码的逻辑就是:写一个sql,用JdbcTemplate来进行数据库连接和请求。

特别指出:相比起常规的普通框架,这里面由于我们使用了JdbcTemplate这些方法,所以不用再考虑要做database.connection这些“连接数据库 - crud - 关闭连接”这些额外的操作了,让我们更为集中精力在业务逻辑的实现上。这也是springboot的一大特色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
java复制代码package shenling.example.springbootJDBC.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import shenling.example.springbootJDBC.entity.user;

import java.util.List;

@Service
@Component
public class userService {

@Autowired
private JdbcTemplate jdbcTemplate;

// 查询列表
public List<user> getList() {
String sql = "SELECT * FROM user";
List<user> result = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(user.class));
return result;
}


// 新增
public int addUser(user newUser) {
String sql = "INSERT INTO user(id, firstname, lastname)values(?,?,?)";
return jdbcTemplate.update(sql, newUser.getId(), newUser.getFirstname(), newUser.getLastname());
}

// 更新
public int updateUser(user newUser) {
String sql = "update user set firstname = ?, lastname=? where id = ?";
return jdbcTemplate.update(sql, newUser.getFirstname(), newUser.getLastname(), newUser.getId());
}

// 删除
public int deleteUser(int id) {
String sql = "delete from user where id = ?";
return jdbcTemplate.update(sql, id);
}

}

要注意几个点:

  1. 我们引入了JdbcTemplate的对象,来使用相关的方法,对数据库进行sql查询请求,完成crud操作。这里可以参考学习这篇文章:www.jianshu.com/p/f0cbed671…
  2. 在springboot里面,只要用@Component注解过的class,就不用在调用的时候使用new进行实例化对象了,而是用@Autowired注解搞定。所以:
  • JdbcTemplate变量声明的前面添加@Autowired注解
  • userService类,要在controller那边通过@Autowired使用,所以这个类的前面需要添加@Component注解
  1. query的时候,一般来说,使用的是List<Map<T, P>>的方法来保存结果,query的第二个参数也是用的这种map类。但是根据一些文的讨论和推荐,更为建议使用RowMapper的方式保存数据结果,认为速度更快更优。

3.2.3 userController.class

在controller里面,便是要创建这些接口了。就可以参考前面的关于如何建接口的demo来理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
java复制代码package shenling.example.springbootJDBC.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.web.bind.annotation.*;
import shenling.example.springbootJDBC.entity.response;
import shenling.example.springbootJDBC.entity.user;
import shenling.example.springbootJDBC.service.userService;

import java.util.List;

@RestController
@RequestMapping("/user")
public class userController {

@Autowired
private userService userService;

@Autowired
private response res;


@GetMapping("/list")
public @ResponseBody response getUserList(){
try {
List<user> result = userService.getList();

res.setResult(result);
res.setCode(10000);
res.setMsg("查询成功");

}
catch(DataAccessException e) {
e.printStackTrace();

String exceptionMsg = e.getRootCause().getMessage();
System.out.println("ERROR:" + exceptionMsg);
res.setCode(500);
res.setMsg(exceptionMsg);
}

return res;
}

@PostMapping("/add")
public @ResponseBody response addUser(user newUser) {
try {
Integer result = userService.addUser(newUser);

res.setResult(newUser);
res.setCode(10000);
res.setMsg("新增成功");

}
catch(DataAccessException e) {
e.printStackTrace();

String exceptionMsg = e.getRootCause().getMessage();
System.out.println("ERROR:" + exceptionMsg);
res.setCode(500);
res.setMsg(exceptionMsg);
}

return res;
}

@PostMapping("/update")
public @ResponseBody response updateUser(user newUser) {
try {
Integer result = userService.updateUser(newUser);

res.setResult(newUser);
res.setCode(10000);
res.setMsg("更新成功");

}
catch(DataAccessException e) {
e.printStackTrace();

String exceptionMsg = e.getRootCause().getMessage();
System.out.println("ERROR:" + exceptionMsg);
res.setCode(500);
res.setMsg(exceptionMsg);
}

return res;
}

@PostMapping("/delete")
public @ResponseBody response deleteUser(int id) {
try {
Integer result = userService.deleteUser(id);

res.setResult(id);
res.setCode(10000);
res.setMsg("删除成功");

}
catch(DataAccessException e) {
e.printStackTrace();

String exceptionMsg = e.getRootCause().getMessage();
System.out.println("ERROR:" + exceptionMsg);
res.setCode(500);
res.setMsg(exceptionMsg);
}

return res;
}
}

同样的,我们可以在这里面看到几个关键点:

  1. @RestController:要制作成接口,那么类前面就肯定要写上这个注解才行
  2. @RequestMapping("/user"):由于我们想要让接口访问的时候,第一段是user,然后才是后面的请求list、新增用户add等,所以要在类前面写上这个。当然如果不需要这一段跳转的话,可以不写。
  3. @Autowired:我们前面的userService那里用了@Component注解,所以这里就可以直接用autowired来进行实例化,而不用通过new了
  4. 这段代码中,可以看到,我们通过userService.getList()就可以拿到查询后的结果,并且可以通过抛出异常DataAccessException抓取到异常日志。但是为了规范化我们的输出结果为msg/code/result的样式,所以我们还需要建一个response的类来声明我们的结果,下一小节会进行说明。
  5. @ResponseBody:这个写在了方法那里,是为了让方法返回的结果是JSON样式输出的,具有一种格式化、标准化的作用,来实现非常典型的rest接口返回结果风格。

3.2.4 response.class

为了让我们的输出结果标准化,所以在entity的package中,我们再建了一个class,去保存我们的输出结果的样子:

1
2
3
4
5
6
7
8
9
10
11
12
java复制代码package shenling.example.springbootJDBC.entity;

import lombok.Data;
import org.springframework.stereotype.Component;

@Data
@Component
public class response {
private String msg;
private Integer code;
private Object result;
}

这里面我们可以看到:

  1. 用了@Data来实现一个Bean的风格的类
  2. 用了@Component来保证在controller中,可以通过autowired进行使用

3.3 创建运行这个应用的class

一般来说,通过官网初始化的springboot应用里面就包含了这个部分了:

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码package shenling.example.springbootJDBC;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


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

}

其中,@SpringBootApplication注解就能让这个应用运行的时候去找到我们的controller

  1. 运行并查看结果

4.1 默认的8080端口已经被占用的问题:

有时候,默认8080端口被占用,所以我们可以查看这个端口号的pid并杀掉这个进程
image.png

当然也可以在application.property中设置一个新的端口号,例如:

1
ini复制代码server.port=1234

4.2 控制台结果

运行成功后,控制台会显示当前web运行的端口号
image.png

4.3 用postman发起请求进行查看

当然,我们完全可以用浏览器直接访问get类型的接口,但是为了显得很专业+直观+美观,我们用postman这种接口管理工具

  1. 下载本地postman软件:www.postman.com/downloads/?…
  2. 发送请求并查看结果:

image.png

  1. 要点小结

1. 推荐使用lombok库,非常方便开发,减少你的代码行数,但是在build的时候需要忽略掉,因为编译会自动生成这个库的

image.png

2. 使用@autowired的时候要注意这个被声明的类,需要有@Component的注解

1
2
3
4
5
6
7
8
9
java复制代码@Component
public class FirstClass {
...
}

public class SecondClass {
@Autowired
FirstClass f;
}

3. 要知道controllerentityservice的区别,分别应该写什么内容(有些框架要求写的是dao层这些)

4. 推荐创建标准的接口输出模板,并抓到请求异常msg进行抛出

5. 在写接口的controller的类前面,一定要写上@RestController

1
2
3
4
java复制代码@RestController
public class controller {
...
}

6. 要注意阅读控制台的报错信息,对应去查bug

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%