victory的博客

长安一片月,万户捣衣声

0%

我的想法 2023.7.15

  • Theme: 让技术有用

  • 我的想法

    • 增加gitee的使用频率,系统学习某个技术并将学习过程或经验推送到gitee

    • 时常维护自己的代码仓库以及个人博客

    • 开发小工具/有用的功能,在gitee建立仓库

    • 在建仓和维护仓库的同时,深入掌握git技术

    • 希望在一年后能够有一个成熟的代码仓库(主题待定)

    • 学习人工智能技术,并注意新技术的体验(例如yolo目标检测这样的技术)

Docker的安装及常用命令

  • Docker是什么?Docker的作用?

    • Docker是一个开源的应用容器引擎,基于Go语言开发,可以让开发者打包应用以及依赖包到容器中,然后发布到任何linux机器上,在移植应用时不需要重新搭建环境和导入依赖,具备强大的可移植性。与虚拟机有所区别,虚拟机虚拟出一套硬件并在其上搭建环境并部署应用,而docker通过将应用与依赖打包,从而达到可移植、快速部署的目的。
  • Docker安装

    ubuntu环境下Docker安装教程

  • 常用镜像(image)操作

    • 查找镜像

      1
      docker search image_name
    • 获取镜像

      1
      docker pull image_name
    • 列出镜像列表

      1
      docker images # 或docker image ls
    • 删除镜像

      1
      docker rmi image_name
  • 常用容器(container)操作

    • 查看正在运行的容器

      1
      2
      docker ps -a
      docker ps -q#只输出容器id
    • 启动容器

      1
      docker run -itd --name container_name image_name /bin/bash
      • -i:交互式操作
      • -t:终端
      • -d:docker服务在后台运行,启动后不会进入容器
    • 交互方式进入容器

      1
      docker exec -it container_id /bin/bash
    • 将主机内容复制到容器中

      1
      docker cp file_name container_id:/path/directory
    • 启动已停止容器

      1
      docker start conatainer_id
    • 停止容器

      1
      docker stop container_id
    • 重启容器

      1
      docker restart container_id
    • 删除容器

      1
      docker rm container_id
    • 导出和导入容器

      1
      2
      3
      docker export container_id > xxx.tar # 导出容器

      docker import - image_name:image_tag # 根据镜像导入容器
    • 清理所有处于终止状态的容器

      1
      docker container prune

135.分发糖果

题目描述

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:
1)每个孩子至少分配到 1 个糖果。
2)相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:
输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:
输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

题目链接

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def candy(self, ratings: List[int]) -> int:
n = len(ratings)
left = [0] * n
for i in range(n):
if i > 0 and ratings[i] > ratings[i - 1]:
left[i] = left[i - 1] + 1
else:
left[i] = 1

right = ret = 0
for i in range(n - 1, -1, -1):
if i < n - 1 and ratings[i] > ratings[i + 1]:
right += 1
else:
right = 1
ret += max(left[i], right)

return ret

695.岛屿的最大面积

题目描述

给你一个大小为 m x n 的二进制矩阵 grid 。

岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

示例 1:
输入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出:6
解释:答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 。

示例 2:
输入:grid = [[0,0,0,0,0,0,0,0]]
输出:0

题目链接

思路

  1. 深度优先搜索(DFS)
    利用深度优先搜索(DFS)对每个岛屿进行遍历,找出最大值
    (1)从每个陆地出发,遍历该陆地所在的岛屿
    (2)在遍历某一岛屿的时候:
    1)从隶属于该岛屿的某一块陆地出发,向四个方向递归地DFS
    2)每次递归对下标进行判断,以区域的边界作为递归边界
    3)为保证每块陆地只访问一次,将已访问过的陆地置0
    4)递归地返回整块岛屿的面积
    (3)找出所有岛屿的最大值,即为答案

邻接矩阵和邻接表表示的图的DFS和BFS

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
package test;

import java.util.LinkedList;
import java.util.Scanner;

class MGraph{
private static final int MAXVEX = 100;
private static final int INFINITY = 65535;

int[] vexs = new int[MAXVEX];
int[][] arc = new int[MAXVEX][MAXVEX];
int numVertexes;
int numEdges;
boolean[] visited = new boolean[MAXVEX];

public void createMGraph() {
System.out.println("输入顶点数和边数:\n");
Scanner scanner = new Scanner(System.in);
numVertexes = scanner.nextInt();
numEdges = scanner.nextInt();

for(int i = 0; i < numVertexes; i++) {
vexs[i] = scanner.nextInt();
}

for(int i = 0; i < numVertexes; i++) {
for(int j = 0; j < numVertexes; j++) {
arc[i][j] = INFINITY;
}
}

for(int k = 0; k < numEdges; k++) {
System.out.println("输入边(vi,vj)上的下标i,j和权w:\n");
int i = scanner.nextInt();
int j = scanner.nextInt();
int w = scanner.nextInt();
arc[i][j] = w;
arc[j][i] = arc[i][j];
}
}

public void DFS(int i) {
visited[i] = true;
System.out.println(vexs[i] + " ");
for(int j = 0; j < numVertexes; j++) {
if(arc[i][j] == 1 && !visited[j]) {
DFS(j);
}
}
}

public void DFSTraverse() {
for(int i = 0; i < numVertexes; i++) {
visited[i] = false;
}

for(int i = 0; i < numVertexes; i++) {
if(!visited[i]) {
DFS(i);
}
}
}

public void BFSTraverse() {
LinkedList<Integer> queue = new LinkedList<Integer>();

for(int i = 0; i < this.numVertexes; i++) {
this.visited[i] = false;
}

for(int i = 0; i < this.numVertexes; i++) {//对每一个顶点做循环
if(!visited[i]) {//若是未访问过就处理
visited[i] = true;//设置当前顶点访问过
System.out.println(this.vexs[i]);//打印顶点,也可以其他操作
queue.addLast(i);//将此顶点入队列
while(!queue.isEmpty()) {
queue.pop();
for(int j = 0; j < this.numVertexes; j++) {
if(this.arc[i][j] == 1 && !this.visited[j]) {
visited[j] = true;
System.out.println(this.vexs[j]);
queue.addLast(j);
}
}
}
}
}
}
}

class EdgeNode{
int adjvex;
EdgeNode next;
}

class VertexNode{
int data;
EdgeNode firstedge;
}

class GraphAdjList{
private static final int MAXVEX = 100;
VertexNode[] adjList= new VertexNode[MAXVEX];
int numVertexes;
int numEdges;
boolean[] visited = new boolean[MAXVEX];

public void createALGraph() {
Scanner scanner = new Scanner(System.in);
System.out.println("输入顶点数和边数:");
this.numVertexes = scanner.nextInt();
this.numEdges = scanner.nextInt();
for(int i = 0 ; i < this.numVertexes; i++) {
VertexNode node = new VertexNode();
node.data = scanner.nextInt();
node.firstedge = null;
this.adjList[i] = node;
}
for(int k = 0; k < this.numEdges; k++) {
System.out.println("输入边(vi,vj)上的顶点序号:\n");
int i = scanner.nextInt();
int j = scanner.nextInt();
EdgeNode e = new EdgeNode();
e.adjvex = j;
e.next = this.adjList[i].firstedge;
this.adjList[i].firstedge = e;

EdgeNode e2 = new EdgeNode();
e2.adjvex = i;
e2.next = this.adjList[j].firstedge;
this.adjList[j].firstedge = e2;
}
}

public void DFS(int i) {
visited[i] = true;
System.out.println(this.adjList[i].data + " ");
EdgeNode p = new EdgeNode();
p = this.adjList[i].firstedge;
while(p != null) {
if(!visited[p.adjvex]) {
DFS(p.adjvex);
}
p = p.next;
}
}

public void DFSTraverse() {
for(int i = 0; i < this.numVertexes; i++) {
this.visited[i] = false;
}

for(int i = 0; i < this.numVertexes; i++) {
if(!visited[i]) {
this.DFS(i);
}
}
}

public void BFSTraverse() {
LinkedList<Integer> queue = new LinkedList<Integer>();
EdgeNode p = new EdgeNode();
for(int i = 0; i < this.numVertexes; i++) {
this.visited[i] = false;
}
for(int i = 0; i < this.numVertexes; i++) {
if(!this.visited[i]) {
this.visited[i] = true;
System.out.println(this.adjList[i].data);//打印顶点
queue.addLast(i);
while(!queue.isEmpty()) {
queue.pop();
p = this.adjList[i].firstedge;
while(p != null) {
if(!this.visited[p.adjvex]) {
this.visited[p.adjvex] = true;
System.out.println(this.adjList[p.adjvex].data);
queue.add(p.adjvex);
}
p = p.next;
}
}
}

}
}
}

public class DFSAndBFS {
public static void main(String[] args) {
//邻接矩阵
MGraph graph = new MGraph();
graph.createMGraph();
System.out.println("邻接矩阵:\n");
for(int i = 0; i < graph.numVertexes; i++) {
for(int j = 0; j < graph.numVertexes; j++) {
System.out.print(graph.arc[i][j]+"\t");
}
System.out.println();
}
System.out.println("深度优先搜索遍历图(邻接矩阵):\n");
graph.DFSTraverse();
System.out.println("广度优先搜索遍历图(邻接矩阵):\n");
graph.BFSTraverse();

//邻接表
GraphAdjList GL = new GraphAdjList();
GL.createALGraph();
System.out.println("深度优先搜索遍历图(邻接表):\n");
GL.DFSTraverse();
System.out.println("广度优先搜索遍历图(邻接表):\n");
GL.BFSTraverse();
}
}

代码

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
class Solution:
def island_dfs(self, grid, i, j):
if len(grid) > i >= 0 and len(grid[0]) > j >= 0:
if grid[i][j] == 0:
return 0
else:
grid[i][j] = 0
return 1 + self.island_dfs(grid, i - 1, j) + self.island_dfs(grid, i + 1, j) + \
self.island_dfs(grid, i, j - 1) + self.island_dfs(grid, i, j + 1)
else:
return 0

def max_area_of_island(self, grid):
ans = 0

for i in range(len(grid)):
for j in range(len(grid[0])):
ans = max(ans, self.island_dfs(grid, i, j))

return ans


if __name__ == "__main__":
s = Solution()
grid = [[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]]
max_area = s.max_area_of_island(grid)
print(max_area)

字符串常量池

首先来看下面一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Test {
public static void main(String[] args){
String a = "abc";
String b = "abc";
String c = "ab" + "c";
String d = "a" + "bc";
String e = "a" + "b" + "c";
String f = new String("abc");

System.out.println(a == b);//true
System.out.println(a == c);//true
System.out.println(a == d);//true
System.out.println(a == e);//true
System.out.println(a == f);//false
}
}
  • 在使用String a = “abc”创建字符串对象时,JVM会使用常量池来管理字符串直接量。在执行该语句时,JVM会先检查常量池中是否已经存有”abc”,
    若没有则将”abc”存入常量池,否则就复用常量池中已有的”abc”,将其引用赋值给变量a。
  • 在使用new String(“abc”)创建字符串对象时,JVM会先使用常量池来管理字符串直接量,即将”abc”存入常量池。然后再创建一个新的String对象,
    这个对象会被保存在堆内存中。并且,堆中对象的数据会指向常量池中的直接量。

Java整数常量池

首先来看一段示例代码,我们会发现这样的现象 127 = 127,128 != 128。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);//true
System.out.print(c == d);//false

Integer e = 1;
int f = 1;
System.out.println(e == f); //Integer和int进行比较时,Integer会自动拆箱为int,然后比较两个值是否相等。
}
}

为什么会出现这样的现象,我们来看以下Integer类的源码:

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
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS(Java Language Specification).
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/

private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];

static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;

cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);

// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}

private IntegerCache() {}
}

以上这段代码是Integer类的一个内部类IntegerCache,它缓存了-128 ~ 127之间的整数值,缓存的最小值为low表示的值,缓存的最大值为high表示的值。
在创建这个范围内的整数对象时,可以在常量池中直接引用,而无需重新创建,因此 a == b 返回true。超出此范围的值,会通过new新的对象,因此 c == d返回false。

SpringBoot集成Druid

Java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。
Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。
Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。
Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源,我们来重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控。

Github地址

  • 项目目录
  • 添加Druid数据源依赖
    1
    2
    3
    4
    5
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.11</version>
    </dependency>
  • 切换数据源并配置数据源;之前已经说过 Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源,但可以 通过 spring.datasource.type 指定数据源
    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
    spring:
    datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    #SpringBoot默认是不注入这些的,需要自己绑定
    #druid数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许报错,java.lang.ClassNotFoundException: org.apache.Log4j.Properity
    #则导入log4j 依赖就行
    filters: stat,wall # ,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionoProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  • 现在需要程序员自己为 DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成了;我们需要 自己添加 DruidDataSource 组件到容器中,并绑定属性;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    @Configuration
    public class DruidConfig {
    //绑定全局配置文件中的参数
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource() {
    return new DruidDataSource();
    }

    }
  • 测试Druid数据源是否配置成功
    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
    package com.example;

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;

    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.SQLException;

    @SpringBootTest
    class SpringDataApplicationTests {

    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() throws SQLException {
    //查看默认的数据源
    System.out.println(dataSource.getClass());

    //获得数据库链接
    Connection connection = dataSource.getConnection();
    System.out.println(connection);

    //关闭
    connection.close();
    }
    }

  • 配置Druid数据源监控
    Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提供了一个默认的 web 页面。
    所以第一步需要设置 Druid 的后台管理页面,比如 登录账号、密码 等;配置后台管理;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 后台监控:相当于web.xml,配置ServletRegistrationBean
    //因为SprintBoot内置了servlet容器,所以没有web.xml,替代方法ServletRegistrationBean
    @Bean
    public ServletRegistrationBean statViewServlet() {
    ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");

    // 后台登录进行账号密码配置
    HashMap<String, String> initParameters = new HashMap<>();

    // 增加配置,登录的key是固定的,loginUsername loginPassword
    initParameters.put("loginUsername", "admin");
    initParameters.put("loginPassword", "123456");

    // 允许谁可以访问,如果后面的参数为空代表谁都可以访问,指定参数只能指定的参数进行访问
    initParameters.put("allow", "");

    // 禁止谁可以访问
    // initParameters.put("koko","192.168.43.21");

    bean.setInitParameters(initParameters); // 设置初始化参数
    return bean;
    }
  • 配置完成后,就可以通过http://localhost:8080/druid/login.html访问监控页面
  • 登录成功后显示的监控页面
  • 配置 Druid web 监控 filter 过滤器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //filter
    @Bean
    public FilterRegistrationBean webStatFileter(){
    FilterRegistrationBean bean = new FilterRegistrationBean();

    bean.setFilter(new WebStatFilter());

    //可以过滤那些请求呢?

    Map<String, String> initParameters = new HashMap<>();

    //这些东西不进行统计
    initParameters.put("exclusions", "*.js,*.css,/druid/*");

    return bean;
    }

SpringBoot集成MyBatis

  • 项目目录
  • 导入MyBatis所需要的依赖
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!--mybatis-springboot-->
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
    </dependency>

    <!--lombok-->
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    </dependency>
  • 数据库和表
  • 配置数据库连接信息(application.yaml)、配置mybatis
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    spring:
    datasource:
    username: root
    password: 123456
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver

    # 整合mybatis
    mybatis:
    type-aliases-package: com.example.pojo
    mapper-locations: classpath:mybatis/mapper/*.xml
  • 创建实体类User.java(需要用到lombok)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.example.pojo;

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
    private int id;
    private String name;
    private String pwd;
    }
  • 创建Mapper接口UserMapper.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.example.mapper;

    import com.example.pojo.User;
    import org.apache.ibatis.annotations.Mapper;
    import org.springframework.stereotype.Repository;

    import java.util.List;

    @Mapper
    @Repository
    public interface UserMapper {
    List<User> queryUserList();

    User queryUserById(int id);

    int addUser(User user);

    int updateUser(User user);

    int deleteUser(int id);
    }
  • 创建映射文件UserMapper.xml
    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
    <?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.example.mapper.UserMapper">
    <!--resultType="User"和parameterType="User"只有配置了type-aliases-package后才能起作用-->
    <select id="queryUserList" resultType="User">
    select * from user
    </select>

    <select id="queryUserById" resultType="User">
    select * from user where id = #{id}
    </select>

    <insert id="addUser" parameterType="User">
    insert into user (id, name, pwd) values (#{id}, #{name}, #{pwd})
    </insert>

    <update id="updateUser" parameterType="User">
    update user set name=#{name},pwd=#{pwd} where id = #{id}
    </update>

    <delete id="deleteUser" parameterType="int">
    delete from user where id = #{id}
    </delete>
    </mapper>
  • 编写UserController.java进行测试
    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
    package com.example.controller;

    import com.example.mapper.UserMapper;
    import com.example.pojo.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;

    import javax.websocket.server.PathParam;
    import java.util.List;

    @RestController
    public class UserController {
    @Autowired
    private UserMapper userMapper;

    @GetMapping("/queryUserList")
    public List<User> queryUserList(){
    List<User> userList = userMapper.queryUserList();
    return userList;
    }

    @GetMapping("/queryUserById/{id}")
    public User queryUserById(@PathVariable Integer id){
    User user = userMapper.queryUserById(id);
    return user;
    }

    // @GetMapping("/addUser") //http://localhost:8080/addUser?id=4&name=wangmazi&pwd=91011
    // public String addUser(@PathParam("id")Integer id, @PathParam("name")String name, @PathParam("pwd")String pwd){
    // userMapper.addUser(new User(id, name, pwd));
    // return "ok";
    // }
    @GetMapping("/addUser/{id}/{name}/{pwd}") //http://localhost:8080/addUser/4/wangmazi/123
    public String addUser(@PathVariable("id") Integer id, @PathVariable("name") String name, @PathVariable("pwd") String pwd){
    userMapper.addUser(new User(id, name, pwd));
    return "ok";
    }

    @GetMapping("/updateUser")
    public String updateuser(){
    userMapper.updateUser(new User(5, "liuba", "325"));
    return "ok";
    }

    @GetMapping("/deleteUser/{id}")
    public String deleteUser(@PathVariable("id") Integer id){
    userMapper.deleteUser(id);
    return "ok";
    }
    }