JavaWeb


JavaWeb笔记

0.web标准

image-20240411200521512

1
2
[w3school 在线教程](https://www.w3school.com.cn/)
这里面可以找到HTML/CSS/JS的所有语法

1.标签语法

image-20240504110022693

*加粗语法*

1
2
3
<strong>我是帅哥</strong>
<br> 换行
<hr> 水平线

2.HTML基本骨架(快速生成方法: !加Enter键或者Tab键)

image-20240504110130176

3.标签的关系

image-20240504110142670

4.注释

1
<!--注释内容--> 使用ctrl+/进行快速生成注释

5.标签标题

image-20240504110151765

1
2
3
<h1>一级标题</h1>

<h2>二级标签</h2>

7.段落标签

image-20240504110204450

1
<p>123456</p>

8.换行与水平线标签

image-20240504110213687

9.文本格式化标签

image-20240504110222378

1
<del><strong> 这是加粗的 </strong></del> 

可以复合使用

10.图片(图形)标签

image-20240504110230846

1
<img src="./图片.jpg">

11.图片属性(alt title)

image-20240504110238549

1
<img src="./图片.jpg" alt="这是一个图片" title="这是图片" width="1000" height="1000">

12.相对路径和绝对路径和网络路径

(不仅可以从本地路径 也可以从在线网址找)

image-20240504110249885

image-20240504110254814

13.超链接a href(不仅可以跳转网址 也可以跳转本地文件)

image-20240504110302537

1
<a href="https://www.baidu.com/?tn=68018901_2_oem_dg">跳转到百度</a>

效果如下

image-20240504110311952

1
<a href="./图片.jpg">跳转到图片</a>

实现在新窗口进行跳转

1
<a href="https://www.baidu.com" target="_blank">跳转到百度</a>

可以设置超链接的样式

image-20240411205238752

image-20240411205300472

14.音频标签(audio)

image-20240504110325702

1
<audio src="./bgm.mp3" controls loop autoplay></audio>

15.css嵌入html语句 从而修改样式

image-20240411203313020

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
h1{
color:red
}
</style>
<link rel="stylesheet" href="./css文件">
</head>
<body>
<h1 style="color:red">这是一级标题</h1>
<del>我很高兴</del>
<br>
<del><strong>这是加粗的</strong></del>
</body>
</html>

16.无语义标签

1
<span>123</span>

17.设置样式(元素选择器 id选择器 类选择器)

image-20240411204731655

18.视频标签

1
<video src="video/1.mp4" controls="controls"></video>

19.css页面布局image-20240411210233298

image-20240411210258999

20.css的盒子模型

image-20240411211444345

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
div{
width: 200px;
height: 200px;
box-sizing: border-box;
background-color: aquamarine;

padding: 20px;/* 内边距 上 右 下 左*/
border: 10px solid red; /*边框 宽度 线条类型*/
margin: 30px 30px 30px 30px;/*外边距 上 右 下 左*/
}
</style>
</head>
<body>
<div>
今天是个好日子 哈哈哈哈哈哈哈 啦啦啦啦啦啦
</div>
</body>
</html>

21.表格标签

image-20240418115537184

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- #border是设置边框的 cellspacing设置单元格之间空格 width是设置宽度的-->
<table border="1px" cellspacing="0" width="600px">
<tr>
<th>序号</th>
<th>品牌logo</th>
<th>品牌名称</th>
<th>企业名称</th>
</tr>
<tr>
<td>1</td>
<td><img src="https://img2.baidu.com/it/u=2950888892,3212136858&fm=253&fmt=auto&app=120&f=JPEG?w=608&h=375" width="100px"></td>
<td>华为</td>
<td>华为技术有限公司</td>
</tr>
<tr>
<td>2</td>
<td><img src="https://img0.baidu.com/it/u=2101785888,821758088&fm=253&fmt=auto&app=120&f=PNG?w=500&h=500" width="100px"></td>
<td>阿里</td>
<td>阿里巴巴有限公司</td>
</tr>
</table>
</body>
</html>

image-20240418120216710

22.表单标签

image-20240418120536559

23.表单标签-表单项

image-20240418121850409

23.JavaScript引入方式

image-20240418122931638

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!--
内部脚本
<script>
alert("Hello")
</script>
-->
<!-- 外部脚本 -->
<script src="./demo.js"></script>

</head>
<body>

</body>
</html>

24.JS输出语句

image-20240418123713287

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
window.alert("你好");
document.write("Hello world");
console.log("123456");
</script>
</body>
</html>

25.JS的变量

image-20240418124349628

var定义的变量的作用域较大为全局变量 并且 可以重复定义(新定义的覆盖原来的)

26.JS的数据类型

image-20240418124720539

27.JS的运算符

image-20240418125427010

28.JS的函数

image-20240418125923375

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//定义函数方法1
function add1(a, b)
{
return a+b;
}
document.write(add1(10,20));
document.write("<br>");
//定义函数方法2
var add2 = function(a,b){
return a+b;
}
document.write(add2(30,40));
</script>
</body>
</html>

29.JS的对象(Array String JSON BOM DOM)

(JavaScript 和 HTML DOM 参考手册 (w3school.com.cn))

①Array对象

image-20240418131828890

image-20240418132631175

②String对象

image-20240418132724807

③JSON对象

image-20240418133512458

image-20240418133725356

④自定义的对象

image-20240418133129420

⑤BOM对象

image-20240418133948048

BOM中的Window对象

image-20240418134000286

image-20240418134135375

BOM中的location对象

image-20240418134801636

⑥DOM对象

image-20240418135258700

image-20240418135759844

DOM案例(属性 函数参考HTML DOM Anchor 对象 (w3school.com.cn)

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img id = 'h1' src="https://img0.baidu.com/it/u=3854371968,2837637628&fm=253&fmt=auto&app=138&f=JPEG?w=610&h=486"> <br><br>
<div class="cls">我是大帅比</div> <br>
<div class="'cls">12345 上山打老虎</div> <br>

<input type="checkbox" name ='hobby'> 电影
<input type="checkbox" name ='hobby'> 游戏
<input type="checkbox" name ='hobby'> 学习
</body>
<script>
//点亮爱心
var img = document.getElementById('h1');
img.src = "https://img0.baidu.com/it/u=1848150008,1086365409&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=472";

//将所有div标签的内容后面加上very good
var divs = document.getElementsByTagName('div');
for (let i = 0; i < divs.length; i++) {
divs[i].innerHTML+="<font color='red'> very good </font>";
}

//将所有复选框都呈现选中
var hobbys = document.getElementsByName('hobby');
for (let index = 0; index < hobbys.length; index++) {
const element = hobbys[index];
element.checked = true;
}

</script>
</html>

30.JS时间监听

image-20240418141823493

image-20240418141852252

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="button" id="btn1" value="事件绑定1" onclick="on1()">
<input type="button" id="btn2" value="事件绑定2">
</body>
<script>
function on1(){
alert("按钮1被点击");
}

document.getElementById('btn2').onclick=function(){
alert("按钮2被点击");
}
</script>
</html>

JS的常见事件

image-20240418142521557

监控事件的案例

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img id = 'h1' src="https://img0.baidu.com/it/u=3854371968,2837637628&fm=253&fmt=auto&app=138&f=JPEG?w=610&h=486"> <br>
<input type="button" value="点亮" onclick="on()">
<input type="button" value="熄灭" onclick="off()">

<br><br>

<input type="text" id="name" value="ABCDEF" onfocus="onf()" onblur="onb()">
<br><br>

<input type="checkbox" name ='hobby'> 电影
<input type="checkbox" name ='hobby'> 游戏
<input type="checkbox" name ='hobby'> 学习
<br>
<input type="button" value="全选" onclick="checkall()">
<input type="button" value="反选" onclick="cancleall()">

</body>
<script>
//点亮爱心
function on()
{
var img = document.getElementById('h1');
img.src = "https://img0.baidu.com/it/u=1848150008,1086365409&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=472";
}
//熄灭爱心
function off()
{
var img = document.getElementById('h1');
img.src = "https://img0.baidu.com/it/u=3854371968,2837637628&fm=253&fmt=auto&app=138&f=JPEG?w=610&h=486";
}

//输入聚焦框后 展示小写 离开后 展示大写
//聚焦----->小写
function onf()
{
var tmp = document.getElementById('name');
tmp.value = tmp.value.toLowerCase();
}
//离开---->大写
function onb()
{
var tmp = document.getElementById('name');
tmp.value = tmp.value.toUpperCase();
}

//点击全选就全选 点击反选就全部取消
function checkall()
{
var array = document.getElementsByName('hobby');
for (let index = 0; index < array.length; index++) {
array[index].checked=true;

}
}
function cancleall()
{
var array = document.getElementsByName('hobby');
for (let index = 0; index < array.length; index++) {
array[index].checked=false;

}
}

</script>
</html>

31.VUE

image-20240418145820809

image-20240418145935496

32.vue2的导入链接 和 vue2的导入链接

vue2的导入链接

1
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

vue2的导入链接

1
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

示例代码

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
{{ message }}
</div>

<script>
var app =new Vue(
{
el:"#app",//id选择器选择的是id为app的项
data:{
message:"Hello World!"
}
}
)
</script>
</body>
</html>

image-20240418161052438

33.vue的常用指令

image-20240418161652627

①v-bind指令和v-model指令

image-20240418161819074

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
<div id="app">
<a v-bind:href="url">链接1</a>
<input type="text" v-model="url">
<!-- 根据输入的文本框的内容会导致url发生改变 因为他们发生了链接-->
</div>

</body>
<script>
new Vue({
el:"#app",
data:{
//通过v-bind和v-model所绑定的值 必须在data里面给出
url:"https://www.baidu.com"
}
})
</script>
</html>

②v-on指令

image-20240418162639506

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="button" value="点击" v-on:click="handle()">
<!-- 省略的写法 -->
<input type="button" value="点击" @click="handle()">
</div>

</body>
<script>
new Vue({
el:"#app",
data:{

},
methods:{
handle:function(){
alert("被点击了一下");
}
}
})
</script>
</html>

③v-if v-else-if v-else v-show

image-20240418163033720

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
年龄<input type="text" v-model="age">经判定,为:
<span v-if="age<=35">年轻人(35及以下)</span>
<span v-else-if="age>35 && age < 60">中年人(35-60)</span>
<span v-else>老年人(60以上)</span>
<br><br>
年龄<input type="text" v-model="age">经判定,为:
<span v-show="age<=35">年轻人(35及以下)</span>
<span v-show="age>35 && age < 60">中年人(35-60)</span>
<span v-show="age>=60">老年人(60以上)</span>
</div>

</body>
<script>
new Vue({
el:"#app",
data:{
age:20
},
methods:{

}
})
</script>
</html>

④v-for指令

image-20240418163859137

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div v-for="addr in addrs">{{addr}}</div>
<hr>
<div v-for="(addr,index) in addrs">{{index}} : {{addr}}</div>
</div>

</body>
<script>
new Vue({
el:"#app",
data:{
addrs:["北京","上海","广州","武汉"]
},
methods:{

}
})
</script>
</html>

34.VUE的综合简单案例

image-20240418165653598

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table border="1" cellspacing="0" width="60%">
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>成绩</th>
<th>等级</th>
</tr>
<tr align="center" v-for="(user,index) in users">
<td>{{index+1}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>
<span v-if="user.gender==1"></span>
<span v-if="user.gender==2"></span>
</td>
<td>{{user.score}}</td>
<td>
<span v-if="user.score>=85">优秀</span>
<span v-else-if="user.score>=60">及格</span>
<span style="color:red" v-else>不及格</span>
</td>
</tr>
</table>
</div>

</body>
<script>
new Vue({
el:"#app",
data:{
users:[{
name:"TOM",
age:20,
gender:1,
score:78
},
{
name:"ROSE",
age:19,
gender:2,
score:88
},
{
name:"JERRY",
age:26,
gender:1,
score:90
},
{
name:"JACK",
age:30,
gender:1,
score:30
}]
},
methods:{

}
})
</script>
</html>

35.VUE的生命周期

image-20240418165847591

image-20240418165758711

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
</div>

</body>
<script>
new Vue({
el:"#app",
data:{
},
methods:{
},
mounted(){
//自动调用 无需程序员来调用
alert("挂载完成 发送请求到服务端");
}
})
</script>
</html>

36.Ajax

image-20240420134614819

image-20240420134826096

37.Axios

1
2
<!-- 引入js文件 -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

由于原生的Ajax访问请求数据极为繁琐 于是就出现了封装的Axios

Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

使用方式

image-20240420141738887

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入js文件 -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>

<input type="button" value="读取数据" onclick="getData()">
<input type="button" value="删除数据" onclick="postData()">

</body>
<script>
function getData(){
//通过axios发送异步请求get
axios({
method:"get",
url:"https://mock.apifox.cn/m1/3128855-0-default/emp/list"
}).then(result=>{
console.log(result.data);
})
}
function postData(){
//通过axios发送异步请求post
axios({
method:"post",
url:"https://mock.apifox.cn/m1/3128855-0-default/emp/deleteById",
data:"id=1"
}).then(result=>{
console.log(result.data);
})
}
</script>
</html>

封装成函数的简化后:

image-20240420143057890

Axios的案例

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入js文件 -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- 引入Vue文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table border="1" cellspacing="0" width="60%">
<tr>
<th>编号</th>
<th>姓名</th>
<th>图像</th>
<th>性别</th>
<th>职位</th>
<th>入职日期</th>
<th>最后操作时间</th>
</tr>
<tr align="center" v-for="(emp,index) in emps">
<td>{{index+1}}</td>
<td>{{emp.name}}</td>
<td>
<img v-bind:src="emp.image" width="70px" height="50px">
</td>
<td>
<span v-if="emp.gender==1"></span>
<span v-if="emp.gender==2"></span>
</td>
<td>{{emp.job}}</td>
<td>{{emp.entrydate}}</td>
<td>{{emp.updatetime}}</td>
</tr>
</table>
</div>
</body>
<script>
new Vue({
el:"#app",
data:{
emps:[]
},
mounted(){
//发送异步请求 加载数据
axios.get("https://mock.apifox.cn/m1/3128855-0-default/emp/list").then(result=>{
this.emps=result.data.data;
//将数据返回到emps上
})
}
})
</script>
</html>

image-20240420150514345

38.Vue-cil

vue的npm镜像

npm config set registry https://mirrors.huaweicloud.com/repository/npm/ (华为)

npm config set registry http://mirrors.cloud.tencent.com/npm/ (腾讯)

image-20240420153052819

进入vue的方式

image-20240421102241265

vue项目的目录结构

image-20240421102504749

运行npm的方法

ctrl+shift+p 搜索npm 然后选择serve运行即可

39.修改vue项目的端口号

image-20240421104150950

40.Vue项目的开发

image-20240421105004460

41.Vue的Element组件库

参考文档:https://element.eleme.cn/#/zh-CNListener

image-20240421114702395

主要就是为了美化各种组件,图形等

image-20240421105421524

①安装组件

②在main.js中引入ElementUi组件库

③创建一个ElementView.vue的文件 里面存放的是官网中的组件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
<el-row>
<!-- 按钮 -->
<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="info">信息按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>
</el-row>
</div>
</template>

<script>
export default{

}
</script>

<style>

</style>

④在App.vue中导入我的ElementView.vue文件

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
<template>
<div>
<element-view>

</element-view>
</div>
</template>

<script>
import ElementView from './views/element/ElementView.vue'
export default{
components:{ElementView},
data(){
return{
message:"Hello World"
}
},
methods:{

}
}
</script>

<style>

</style>

42.Vue项目的部署

image-20240421143702603

43.Maven学习(Maven就是管理和构建java项目的工具)

image-20240421145323514

image-20240421145334959

image-20240421145504410

44.创建Maven项目的时候出现问题解决办法

img

只需要再pom.xml文件加入下面的代码即可

1
2
3
4
5
6
7
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

45.导入Maven文件

只需要导入pox.xml文件即可

image-20240421162121039

46.依赖配置

依赖的参考链接为:mvnrepository.com

image-20240421163350608

依赖具有传递性 配置一个依赖的时候 会顺便导入父项的依赖

排除依赖的语法

image-20240421163900237

47.依赖范围

image-20240421164028172

48.Maven生命周期

image-20240421164531839

image-20240421164600894

49.Spring(官网:Spring | Home)

Spring是一个强大的Java开发框架,而Spring Boot是在Spring框架基础上构建的简化开发的工具

Spring提供了很多模块,用于处理不同的方面,如数据访问、Web开发、安全性等。开发者可以根据自己的需求选择合适的模块来构建应用程序。Spring框架也很受欢迎,因为它具有广泛的社区支持和丰富的文档资源。

Spring Boot则是在Spring框架基础上构建的一种简化开发的框架。它旨在减少开发者在构建应用程序时需要进行的繁琐配置和集成工作。Spring Boot通过自动配置和约定大于配置的原则,让开发者能够快速启动和运行应用程序,而无需太多的手动配置。

50.SpringBootWeb入门

Springboot的url选择阿里云的镜像网站可选java11(https://start.aliyun.com)

注意:

在idea2023中 创建springboot后 编译器自动创建了BasicController 如果再重复创建会报错

通过(localhost:8080/hello)来调用 同时可以(http://127.0.0.1:8080/hello?name=lisi)问号后面是参数

image-20240425123005182

image-20240425123033278

image-20240425131842816

51.HTTP协议

image-20240425123700067

①HTTP请求协议

image-20240425124234588

image-20240425124150492

②HTTP响应协议

image-20240425125326011

响应头

image-20240425125348424

响应行的状态码

状态码大全:https://cloud.tencent.com/developer/chapter/13553

image-20240425125032738

52.Web服务器(Tomcat)

image-20240425130603945

image-20240425130000882

由于程序员自己书写服务端和客户端的代码量极大 所以出现了已经封装好的web服务器

只需要将程序的代码部署到web服务器上即可 程序员就只需要关注当前的业务逻辑

image-20240425130455150

53.Tomcat基本使用

image-20240425130747386

如果端口号冲突

image-20240425131055552

54.请求响应

image-20240425132532548

postman的使用

image-20240425133725280

55.简单参数(原始方式和SpringBoot方式)

image-20240425140801332

image-20240425141122209

image-20240425141419021

image-20240425150352210

56.实体参数

只需要名称对应即可

image-20240425142200646

57.数组集合参数

数组参数

image-20240425143102659

1
2
3
4
5
@RequestMapping("/arrayparam")
public String arrayparam(String []hobby){
System.out.println(Arrays.toString(hobby));
return "OK";
}

image-20240425143004551

集合参数

image-20240425143127787

1
2
3
4
@RequestMapping("/listparam")
public String listparam(@RequestParam List<String> hobby){
System.out.println(hobby);
return "OK";

image-20240425143430179

58.日期参数

image-20240425144053417

1
2
3
4
5
@RequestMapping("/dateparam")
public String dateparam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")LocalDateTime updatetime){
System.out.println(updatetime);
return "OK";
}

image-20240425144102187

59.Json格式参数

image-20240425145640505

1
2
3
4
5
@RequestMapping("/jsonparam")
public String jsonparam(@RequestBody user u){
System.out.println(u);
return "OK";
}

image-20240425145705322

60.路径参数

image-20240425150123757

1
2
3
4
@RequestMapping("/path/{id}")
public String pathparam(@PathVariable Integer id){
System.out.println(id);
return "OK";

image-20240425150131464

61.响应数据

代码中一般使用@RestController

@RestController=@Contorller+@RespondBody

image-20240425151133755

image-20240425151608154

统一响应结果

image-20240425151657773

由于数据的响应不唯一 所以定义一个统一的Result类 来统一返回的值

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
package com.example.springbootwebstudy01.pojo;

/**
* 统一响应结果封装类
*/
public class Result {
private Integer code;//1 成功 , 0 失败
private String msg; //提示信息
private Object data; //数据 data

public Result() {
}

public Result(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public String getMsg() {
return msg;
}

public void setMsg(String msg) {
this.msg = msg;
}

public Object getData() {
return data;
}

public void setData(Object data) {
this.data = data;
}

public static Result success(Object data) {
return new Result(1, "success", data);
}

public static Result success() {
return new Result(1, "success", null);
}

public static Result error(String msg) {
return new Result(0, msg, null);
}

@Override
public String toString() {
return "Result{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}

image-20240425153502435

image-20240425153521085

62.请求响应实例

image-20240425154259704

image-20240425160059151

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
//Controller程序
package com.example.springbootwebstudy01.demos.web;

import com.example.springbootwebstudy01.pojo.Emp;
import com.example.springbootwebstudy01.pojo.Result;
import com.example.springbootwebstudy01.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class Empcontroller {

@RequestMapping("/listEmp")
public Result list()
{
//1.加载并解析emp.xml文件
String file =this.getClass().getClassLoader().getResource("emp.xml").getFile();
//将emp.xml文件转换成emp对象 并存入List<Emp>中
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);

//2.对数据进行转换处理(gender,job)
empList.stream().forEach(emp -> {
String gender = emp.getGender();
if(gender.equals("1"))
{
emp.setGender("男");
}
else if(gender.equals("2"))
{
emp.setGender("女");
}

String job = emp.getGender();
if(job.equals("1"))
{
emp.setJob("讲师");
}
else if(job.equals("2"))
{
emp.setJob("班主任");
}
else if(job.equals("3"))
{
emp.setJob("就业指导");
}
});

//3.响应数据
return Result.success(empList);
}

}

image-20240425160604961

63.分层解耦-三层架构

image-20240425161236381

image-20240425161415088

image-20240425162731282

DAO数据访问层(实现了接口)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.example.springbootwebstudy01.dao.imple;

import com.example.springbootwebstudy01.dao.Empdao;
import com.example.springbootwebstudy01.pojo.Emp;
import com.example.springbootwebstudy01.utils.XmlParserUtils;

import java.util.List;

public class EmpdaoA implements Empdao {
@Override
public List<Emp> listEmp()
{
//1.加载并解析emp.xml文件
String file =this.getClass().getClassLoader().getResource("emp.xml").getFile();
//将emp.xml文件转换成emp对象 并存入List<Emp>中
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
return empList;
}

}

Service逻辑处理层

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
package com.example.springbootwebstudy01.service.imple;

import com.example.springbootwebstudy01.dao.Empdao;
import com.example.springbootwebstudy01.dao.imple.EmpdaoA;
import com.example.springbootwebstudy01.pojo.Emp;
import com.example.springbootwebstudy01.service.empservice;

import java.util.List;

public class empserviceA implements empservice {
//面向接口的编程
private Empdao empdao = new EmpdaoA();
public List<Emp> listEmp()
{
//调用empdao获取emplist数据
List<Emp> empList = empdao.listEmp();
//2.对数据进行转换处理(gender,job)
empList.stream().forEach(emp -> {
String gender = emp.getGender();
if(gender.equals("1"))
{
emp.setGender("男");
}
else if(gender.equals("2"))
{
emp.setGender("女");
}

String job = emp.getGender();
if(job.equals("1"))
{
emp.setJob("讲师");
}
else if(job.equals("2"))
{
emp.setJob("班主任");
}
else if(job.equals("3"))
{
emp.setJob("就业指导");
}
});
return empList;
}

}

Controller层 接收数据返回请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.springbootwebstudy01.demos.web;

import com.example.springbootwebstudy01.pojo.Emp;
import com.example.springbootwebstudy01.pojo.Result;
import com.example.springbootwebstudy01.service.empservice;
import com.example.springbootwebstudy01.service.imple.empserviceA;
import com.example.springbootwebstudy01.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
@RestController
public class Empcontroller {
//面向接口的编程
private empservice empser = new empserviceA();
@RequestMapping("/listEmp")
public Result list()
{
//调用empser获取数据
List<Emp> empList = empser.listEmp();
//3.响应数据
return Result.success(empList);
}
}

64.分层解耦-IDC和DI简单示例

image-20240425163839421

image-20240425164441558

image-20240425164905894

image-20240425164921560

image-20240425164932379

image-20240425164945239

这样修改之后 当修改某个类的代码的时候 其它层就不需要动了

只需要将修改前的类不交给容器管理 把修改后的类交给容器管理(也就是加上@Component)

65.分层解耦-IDC和DI详细介绍

image-20240425165624287

bean的名称默认是—类名首字母小写—-

image-20240425165920153

image-20240425170251182

image-20240425170447142

66.Mybatis是什么?

我们做为后端程序开发人员,通常会使用Java程序来完成对数据库的操作。

Java程序操作数据库,现在主流的方式是:Mybatis。

image-20240426103015563

67.Mybatis快速入门(代码实例)

image-20240426103641390

image-20240426112229769

测试类的代码

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
package com.example;

import com.example.mapper.UserMapper;
import com.example.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

//Maven工程的测试类
@SpringBootTest //SpringBoot 整合单元测试的注解
class SpringbootMybatisQuickstartApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testlistUser() {
List<User> userList = userMapper.list();
userList.stream().forEach(user->{
System.out.println(user);
});
}

}

UserMapper对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.mapper;

import com.example.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

//声明为Mapper类后 在运行的时候会自动生成该接口的实现类
//并且会将该对象交给IOC容器管理
@Mapper
public interface UserMapper {
//查询全部用户信息
@Select("select * from User") //注解代表查询操作
public List<User> list();
}

Recourser类中连接数据库

1
2
3
4
5
6
7
8
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456

User类

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
package com.example.pojo;

import javax.sound.sampled.Port;

public class User {
private Integer id;
private String name;
private Short age;
private Short gender;
private String phone;


public User() {
}

public User(Integer id, String name, Short age, Short gender, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.phone = phone;
}

/**
* 获取
*
* @return id
*/
public Integer getId() {
return id;
}

/**
* 设置
*
* @param id
*/
public void setId(Integer id) {
this.id = id;
}

/**
* 获取
*
* @return name
*/
public String getName() {
return name;
}

/**
* 设置
*
* @param name
*/
public void setName(String name) {
this.name = name;
}

/**
* 获取
*
* @return age
*/
public Short getAge() {
return age;
}

/**
* 设置
*
* @param age
*/
public void setAge(Short age) {
this.age = age;
}

/**
* 获取
*
* @return gender
*/
public Short getGender() {
return gender;
}

/**
* 设置
*
* @param gender
*/
public void setGender(Short gender) {
this.gender = gender;
}

/**
* 获取
*
* @return phone
*/
public String getPhone() {
return phone;
}

/**
* 设置
*
* @param phone
*/
public void setPhone(String phone) {
this.phone = phone;
}

public String toString() {
return "User{id = " + id + ", name = " + name + ", age = " + age + ", gender = " + gender + ", phone = " + phone + "}";
}
}

配置SQL的提示

image-20240427113725219

68.数据库连接池

image-20240427124849001

image-20240427125019128

切换连接池的操作

image-20240427125106489

Druid数据库连接池的依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>

69.lombok

作用

只需要加上注解 那么就拥有了他的方法

image-20240427130731917

引入lombok的依赖

1
2
3
4
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

70.Mybatis基础操作

在 [application.properties] 中配置日志信息 可以在控制台得到操作记录

1
2
#配置mybatis的日志信息
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

image-20240427140034497

如果一条语句执行两遍的解决方案

img

主键返回

image-20240427144048142

查询操作返回的值因为名字不同而无法数据封装

image-20240427145819545

解决方法:

①查询的时候取别名

image-20240427150154787

②通过 @Result 注解手动映射封装

image-20240427150132791

③字段自动映射到驼峰命名的设置

image-20240427150319076

代码实例

[EmpMapper]代码

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
package com.itheima.mapper;

import com.itheima.pojo.Emp;
import org.apache.ibatis.annotations.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Mapper
public interface EmpMapper {
//动态根据id删除员工操作
@Delete("delete from emp where id = #{id}")
//返回值为此次操作影响了几条记录
public void delete(Integer id);


//根据主键id 更新 用户 操作
@Update("update emp set " +
"username=#{username},name=#{name},gender=#{gender},image=#{image},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} " +
"where id = #{id}")
public void update(Emp e);

//插入数据
@Insert("insert into emp(username,name, gender, image, job, entrydate, dept_id, create_time, update_time) " +
"value(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime});")
public void insert(Emp e);


//根据用户id查询数据
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id deptId, create_time createTime, update_time updateTime from emp where id = #{id}")
public Emp select(Integer id);


//条件查询
//使用$是为了直接拼接 可以使用模糊匹配
//如果是使用#则是预编译的方法
@Select("select * from emp where name like '%${name}%'and gender = #{gender} and entrydate between #{begin} and #{end} order by update_time desc")
public List<Emp> select_list(String name, Short gender, LocalDate begin, LocalDate end);


}

[SpringbootMybatisCrudApplicationTests]代码

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
package com.itheima;

import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.Emp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.ParameterResolutionDelegate;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
@Autowired
private EmpMapper empMapper;

@Test
public void TestDelete()
{
Integer id = 17;
empMapper.delete(id);
}

@Test
public void testInsert()
{
Emp e = new Emp();
e.setUsername("zw");
e.setName("占稳");
e.setImage("TEST.jpg");
e.setGender((short)1);
e.setJob((short)1);
e.setEntrydate(LocalDate.of(2000,1,1));
e.setCreateTime(LocalDateTime.now());
e.setUpdateTime(LocalDateTime.now());
e.setDeptId(1);
empMapper.insert(e);
}

@Test
public void testupdate()
{
Emp e = new Emp();
e.setId(24);//代表要更新的用户的id
//下面设置的数据 都是要更新的数据
e.setUsername("new_zw");
e.setName("new_占稳");
e.setImage("TEST.jpg");
e.setGender((short)1);
e.setJob((short)1);
e.setEntrydate(LocalDate.of(2000,1,1));
e.setUpdateTime(LocalDateTime.now());
e.setDeptId(1);
empMapper.update(e);
}

@Test
public void testselect()
{
Integer id = 1;
Emp e = empMapper.select(id);
System.out.println(e);
}

@Test
public void test_select_list()
{
List<Emp> emp_list = empMapper.select_list("张",(short)(1),LocalDate.of(2010,1,1),LocalDate.of(2020,1,1));
System.out.println(emp_list);
}
}

71.通过XML映射配置文件来配置sql语句

使用注解来映射简单语句会使代码显得更加简洁

但对于稍微复杂一点的语句,lava注解不仅力不队心 还会让你本就复杂的SQL语句更加银乱不堪

因此,如果你需要做一些很复杂的操作,最好用XML来映射语句

image-20240427152325736

步骤

image-20240427153644061

1
2
3
4
5
6
7
8
9
<?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="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>

image-20240427153842872

image-20240427154143582

72.动态SQL语句

image-20240427155150030

①if 标签

image-20240427160050265

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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.itheima.mapper.EmpMapper">
<select id="select_list" resultType="com.itheima.pojo.Emp">
-- resultType 配置的是单条记录的返回值类型的全命名
select *
from emp
<where>
<if test="name!=null">
name like '%${name}%'
</if>
<if test="gender!=null">
and gender = #{gender}
</if>
<if test="gender!=null and end!=null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
</mapper>

②where标签

image-20240427160641601

③set标签

image-20240427160651489

④foreach标签

image-20240427161445434

1
2
3
4
5
6
7
8
<delete id="deleteByid">
delete
from emp
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>

⑤sql include标签

image-20240427161646791

73.开发规范(rest风格)

请求格式-post put get delete

image-20240428110030113

74.三层架构 各自的作用

image-20240428120205197

75.分页查询的改进(PageHelper)

由于分页查询的代码固定并且繁琐 使用PageHelper插件进行快速编写

image-20240428133829375

image-20240428133651150

76.Web开发中一些的注释含义

① @Mapper

代表了是Mapper类

② @RestController

Controller类

③ @Service

Service类(放在实现类上 而不是接口上)

④ @Autowired和@Component

他们搭配使用 目的是为了交给容器管理 依赖注入

⑤ @Data @NoArgsConstructor @AllArgsConstructor

他们简化了操作 Data代表了各个参数的get和set方法

NoArgsConstructor是无参构造 AllArgsConstructor是全参构造

⑥ @Select @Delete @Insert等

都是表示为数据库的操作 他们会执行sql语句并返回给函数的返回值

⑦@PostMapping @PostMapping @GetMapping等

都是代表为各种类型的前端请求

⑧ @Slf4j 代表了生成了一个可生成日志的类

通过

1
log.info("执行删除操作:ids:{}",ids);

来得到日志信息

⑨ @RequestBody

表示该参数应该从请求的 body(请求体)中获取数据 将请求体中的数据绑定到方法参数上 以便在后续的处理逻辑中使用

⑩ @PathVariable

PathVariable 注解允许url中的占位符中的值提取出来 并将其作为方法的参数进行处理

⑪@RequestParam(defaultValue = “1”)

可以设置参数的默认值

⑫ @DateTimeFormat(pattern = “yyyy-MM-dd”)

设置日期格式

⑬⑭⑮⑯⑰⑱⑲⑳

77.文件上传

image-20240504110810296

image-20240504111701202

文件上传端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
</head>
<body>
<!--加上"multipart/form-data"才能正常提交文件的内容 否则只提交文件的名称-->
<form action="/upload" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="username"><br>
年龄: <input type="text" name="age"><br>
头像: <input type="file" name="image"><br>
<input type="submit" value="提交">
</form>

</body>
</html>

服务端接受文件并将文件存储到本地代码

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
package com.itheima.controller;

import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上传: {}, {}, {}",username,age,image);
// 1.将文件存储到服务器的磁盘目录中 D:\study_images

// 需要构建唯一的文件名(不能重复) 构建uuid(通用唯一识别码)
String OriginalFilename = image.getOriginalFilename();
int index = OriginalFilename.indexOf(".");
//获取文件后缀名
String extname = OriginalFilename.substring(index);
//uuid+后缀名(.txt等)构建新文件名
String newFileName = UUID.randomUUID().toString()+extname;
log.info(newFileName);
image.transferTo(new File("D:\\study_images\\"+newFileName));
return Result.success();
}
}

image-20240504115423342

image-20240504120214861

文件上传大小的配置(在 application.properties 中配置)

image-20240504115613705

1
2
3
4
#配置单个文件上传大小配置
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大大小限制(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB

78.文件存储到阿里云OSS

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
package com.itheima;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.FileInputStream;
import java.io.InputStream;

public class Demo {

public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "web-tlias-zw-study";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
// 意思是 存储到OSS中的地址和名字
String objectName = "test01.pdf";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 意思是上传哪个文件?文件的地址是什么?
String filePath= "C:\\Users\\ZW\\Desktop\\Temporary\\准考证.pdf";

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);

try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}

如果发生了报错信息([ERROR] Command execution failed.)

那么需要再xml中加入下面的插件

1
2
3
4
5
6
7
8
9
10
11
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<classpathScope>test</classpathScope>
</configuration>
</plugin>
</plugins>

image-20240504130537469

79.阿里云集成

image-20240504130856731

AliOSSUtils.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
package com.itheima.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;

/**
* 阿里云 OSS 工具类
*/
@Component
public class AliOSSUtils {

private String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
private String accessKeyId = "LTAI5tBuBtACUg1QvnfjMzFj";
private String accessKeySecret = "bDD2xF2Km7zC9F2rrKP3aBkZSLovu3";
private String bucketName = "web-tlias-zw-study";

/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws IOException {
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();

// 避免文件覆盖
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

//上传文件到 OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.putObject(bucketName, fileName, inputStream);

//文件访问路径
String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
// 关闭ossClient
ossClient.shutdown();
return url;// 把上传到oss的路径返回
}

}

UploadController.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
package com.itheima.controller;

import com.itheima.pojo.Result;
import com.itheima.utils.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@RestController
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
//本地存储文件
/*@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上传: {}, {}, {}",username,age,image);
// 1.将文件存储到服务器的磁盘目录中 D:\study_images

// 需要构建唯一的文件名(不能重复) 构建uuid(通用唯一识别码)
String OriginalFilename = image.getOriginalFilename();
int index = OriginalFilename.indexOf(".");
//获取文件后缀名
String extname = OriginalFilename.substring(index);
//uuid+后缀名(.txt等)构建新文件名
String newFileName = UUID.randomUUID().toString()+extname;
log.info(newFileName);
image.transferTo(new File("D:\\study_images\\"+newFileName));
return Result.success();
}*/

//阿里云OSS存储文件
@PostMapping("/upload")
public Result upload(MultipartFile image) throws IOException {
log.info("文件上传:文件名为{}",image.getOriginalFilename());
//调用阿里云OSS工具类进行文件上传
String url = aliOSSUtils.upload(image);
log.info("文件上传完成,文件访问的url为{}",url);
return Result.success(url);
}

}

80.参数配置化

多个项目均依赖 不便维护 但是 application.properties 只有一个 将参数配置到里面去后更加方便整洁

image-20240504145401016

image-20240504145315504

81.Yml配置文件

image-20240504150021073image-20240504150002761

基本语法

image-20240504150118185

image-20240504150325918

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
spring:
#数据库的连接信息
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/tlias
username: root
password: 123456
#文件上传的配置
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB


mybatis:
#日志信息的配置
configuration:
#输出到控制台
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#驼峰命名的自动映射
map-underscore-to-camel-case: true

#阿里云OSS
aliyun:
oss:
endpoint: https://oss-cn-hangzhou.aliyuncs.com
accessKeyId: LTAI5tBuBtACUg1QvnfjMzFj
accessKeySecret: bDD2xF2Km7zC9F2rrKP3aBkZSLovu3
bucketName: web-tlias-zw-study

82.简化注入方式的配置

image-20240504154019529

image-20240504154109235

创建一个 AliOSSProperties.java 在其中声明各个参数 要求与配置 application.yml 的参数一致

image-20240504161606083

AliOSSUtils.java 中获取各个参数

image-20240504160539290

83.登录校验

image-20240505110441250

会话技术

image-20240505110859282

cookie技术

image-20240505112022204

session技术

image-20240505112623225

令牌技术(主流技术)

image-20240505112750643

84.JWT令牌技术

JWT是什么?

image-20240505113136097

image-20240505113239998

JWT令牌的生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    /*
生成JWT令牌
*/
@Test
public void testGenJwt()
{
Map<String, Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("name","tom");
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, "zw666")//设置 签名算法(密钥必须大于三位))
.setClaims(claims)//设置 自定义的内容(载荷部分)
.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置 有效期(一个小时)
.compact();
System.out.println(jwt);
}
}

image-20240505115246055

Jwt令牌的解析校验

image-20240505115458544

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
解析jwt
*/
@Test
public void testParseJwt()
{
Claims claims = Jwts.parser()
.setSigningKey("zw666") // 指定秘钥
.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcxNDg4NDMyOH0.UABZdznAir57L0_XZEVz7K6k2tNlvqD3vq4iJaKbCrg")
.getBody();
System.out.println(claims);

}

image-20240505115211158

image-20240505114710065

85.统一拦截校验令牌技术(选择其一即可)

①过滤器Filter

image-20240505121138338

image-20240505124416898

image-20240505130501422

Filter演示代码实现

注意在启动类中必须加上注释

image-20240505122453732

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.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/*") // "/*" 代表拦截所有路径
public class DemoFilter implements Filter {

@Override //初始化方法 调用一次
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init方法执行");
}

@Override // 拦截到请求后都会调用 调用多次
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("拦截到请求");
/*
执行令牌检验逻辑....
*/
//拦截到请求后 需要进行放行操作
filterChain.doFilter(servletRequest,servletResponse);
}

@Override//销毁方法 调用一次
public void destroy() {
System.out.println("destroy方法执行");
}
}

Filter完整代码实现

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
package com.itheima.filter;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.itheima.pojo.Result;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
//1.获取请求url
String url = req.getRequestURL().toString();
log.info("请求的url为{}",url);
//2.判断请求url中是否包含login 如果包含说明是登录操作放行
if(url.contains("login"))
{
//放行
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//3.获取请求头的令牌(token)
String jwt = req.getHeader("token");
//4.判断令牌是否存在 如果不存在 (未登录)
if(!StringUtils.hasLength(jwt))
{
log.info("请求头token为空 返回未登录信息");
Result error = Result.error("NOT_LOGIN");
//手动将对象转为json格式对象
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//5.解析token 如果解析失败 返回错误(未登录)
try {
JwtUtils.parseJWT(jwt);
}catch (Exception e)
{
log.info("解析令牌失败 返回未登录的错误信息");
Result error = Result.error("NOT_LOGIN");
//手动将对象转为json格式对象
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//6.放行
log.info("令牌合法");
filterChain.doFilter(servletRequest,servletResponse);
return;

}
}

②拦截器Interceptor

image-20240505135011923

image-20240505140532219

image-20240505140633119

image-20240505141420483

拦截器的实现代码

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
package com.itheima.interceptor;



import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override //目标资源方法运行前运行 返回true:放行 返回false:不放行
//在这个方法里面实现校验的逻辑
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle运行");
return true;
}

@Override // 目标资源方法运行后运行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle运行");
}

@Override //试图渲染完毕后运行 最后运行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion运行");
}
}

拦截器的注册代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.itheima.config;


import com.itheima.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration//配置类
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;

//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry)
{
//addPathPatterns("/**")代表拦截所有资源
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}

86.异常处理

image-20240505142327440

image-20240505142730381

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.itheima.exception;

import com.itheima.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

//全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class) // Exception.class代表捕获所有异常
public Result ex(Exception exception)
{
exception.printStackTrace();
return Result.error("对不起 操作失败 请联系管理员");
}
}


文章作者: Yolo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yolo !
评论
  目录