所需技术
web标准组成
html:负责网页的结构(页面元素和内容)
css:负责网页的表现(页面元素的外观,位置等页面样式,如:颜色,大小等)
javasc:负责网页行为(交互效果)
web前端开发
html,css学习
html:超文本标记语言
超文本:超越了文本的限制,比普通文本根强大
标记语言:由标签构成的语言
css
层叠样式表,用于控制页面布局
css标签可进入w3school官方文档查看
html快速入门
HTML结构(Hypertext Markup Language)是一种用于创建网页和其他信息展示的标记语言。它由HTML标签和文本组成,标签用于定义文档的结构和内容,文本则是实际内容的主体。
HTML结构由以下几个部分组成:
-
文件声明:
<!DOCTYPE html>
,用于告诉浏览器使用哪个HTML版本。 -
html 标签:
<html>
,用于定义文档的根元素。 -
head 标签:
<head>
,用于定义文档的头部,包含元数据和其他信息。 -
title 标签:
<title>
,用于定义文档的标题。 -
body 标签:
<body>
,用于定义文档的主体,包含文档显示的所有内容。 -
header 标签:
<header>
,用于定义文档的页眉,通常包含网站的logo和导航菜单等。 -
nav 标签:
<nav>
,用于定义文档的导航菜单。 -
section 标签:
<section>
,用于定义文档中的节或段落。 -
article 标签:
<article>
,用于定义独立的文章或故事。 -
aside 标签:
<aside>
,用于定义文档的侧边栏。 -
footer 标签:
<footer>
,用于定义文档的页脚。 -
div 标签:
<div>
,用于定义文档中的区块,通常用于布局。
HTML结构可以根据需要添加其他标签和属性来实现不同的功能和样式。
vs code安装使用
安装:
-
下载Visual Studio Code安装程序:https://code.visualstudio.com/Download
-
运行安装程序,按照提示完成安装即可。
使用:
-
打开Visual Studio Code,可以直接从开始菜单中打开。
-
在打开的界面中,可以选择打开文件夹或者文件。也可以通过终端(Terminal)命令行进入到指定文件夹,输入“code . ”命令打开Visual Studio Code。
-
编写代码:支持多种编程语言的代码编写,如C、C++、Java、Python、JavaScript等等。
-
调试代码:Visual Studio Code支持多种语言的调试,可以通过调试工具检查代码逻辑、变量的值等。
-
安装插件:Visual Studio Code支持自定义插件,用户可以根据自己的需要安装相应的插件。可以通过菜单栏中的“扩展(Extensions)”查看和安装插件。
-
快捷键:Visual Studio Code支持多种快捷键,可以通过菜单栏中的“帮助(Help)”查看快捷键列表。
-
其他功能:Visual Studio Code还提供了很多其他的功能,如代码折叠、代码格式化、自动补全等等。用户可以根据自己的需要使用这些功能。
html基础标签&样式
标题样式
- 行内样式:<h1 style="color: brown;">旅游热点</h1>
- 内嵌样式:
<style>
h1{
color: red;
}
</style>
- 外联样式
h1{
color: red;
}
<link rel="stylesheet" href="标题样式.css">
选择器
HTML选择器是CSS中用来选择HTML元素的方法。HTML选择器可以通过元素的标签名、类名、ID、属性、伪类和伪元素等多种方式来匹配元素。
HTML选择器分类如下:
-
标签选择器:使用HTML标签名作为选择器,可以匹配所有该标签的元素,如p、div等。
-
类别选择器:使用CSS类名作为选择器,只匹配具有指定类名的元素,如.class。
-
ID选择器:使用CSS ID作为选择器,只匹配具有指定ID的元素,如#id。(id名称不能重复,优先级最高)
-
属性选择器:匹配具有指定属性的元素,如[type="text"]。
-
伪类选择器:匹配一些特定状态下的元素,如:hover、:active等。
-
伪元素选择器:匹配元素的特定部分,如::before、::after等。
颜色表示形式
- 关键字:预定义的颜色名,如red...
- rgb表示法:红绿蓝三原色。每项取值范围:0-255,如:rgb(0,0,0)
- 十六进制表示法:#开头,将数字转换成十六进制表示。如:#000000...
文本标签
HTML(HyperText Markup Language)是一种用于创建网页的标记语言,它使用标签来描述网页内容的各个部分。
以下是一些常见的HTML标签及其用途:
<html>
:定义HTML文档的根元素<head>
:定义文档头部,其中包含了一些元数据信息,如文档标题、字符集等<title>
:定义文档的标题,通常会显示在浏览器的标签栏中<body>
:定义文档的主体部分,包含了页面的内容<h1>
~<h6>
:定义标题,<h1>
最大,<h6>
最小<p>
:定义段落,可以包含文本、图像、链接等<img>
:定义图像,需要指定图像的源文件(src)、替代文本(alt)等属性<a>
:定义链接,需要指定链接的目标(href)、链接文本等属性<ul>
、<ol>
、<li>
:定义无序列表、有序列表和列表项<table>
:定义表格,需要使用<tr>
、<td>
等标签来指定表格的行、列和单元格<form>
:定义表单,可以包含输入控件,如文本框、单选框、复选框等<input>
:定义输入控件,在<form>
中使用,需要指定类型(type)和名称(name)等属性<textarea>
:定义文本域,用于输入大段文本,如评论、简介等<button>
:定义按钮,通常与 JavaScript 一起使用来实现交互功能<div>
:定义文档中的一个区块,通常用来分组其他元素<span>
:定义文档中的一个内联区块,通常用来修饰文本(组合行内元素,没有语义)
以上仅是 HTML 中的一部分标签,完整列表可以在 W3Schools 中查看。
字体标签
HTML字体标签是一种用来定义文本字体、大小、颜色等样式的标签。以下是常用的HTML字体标签:
-
<font>:用于定义文本字体、大小、颜色等样式。可以通过属性指定字体、大小、颜色等样式。
-
<strong>:用于定义加粗效果。默认字体为粗体。
-
<em>:用于定义强调效果。默认字体为斜体。
-
<u>:用于定义下划线效果。
-
<strike>:用于定义删除线效果。
-
<sup>和<sub>:分别用于定义上标和下标效果。
-
<h1>-<h6>:用于定义标题。h1最大,h6最小,依次递减。
示例:
<p style="font-family:Arial;font-size:18px;color:red;">这是一段红色、Arial字体大小为18px的文本。</p>
<strong>这是加粗的文本</strong>
<em>这是斜体的文本</em>
<u>这是下划线的文本</u>
<strike>这是删除线的文本</strike>
2<sup>10</sup>等于1024
H1标签:这是一级标题
H2标签:这是二级标题
超链接
HTML超链接标签是<a>标签,用于创建一个超链接。它的语法如下:
<a href="链接地址">链接文本</a>
其中,href
属性指定了链接的地址,链接文本
则是用户点击链接时看到的文本内容。
示例:
创建一个指向百度首页的链接:
<a href="https://www.baidu.com/">百度首页</a>
点击「百度首页」,会跳转到百度首页。
视频标签和音频标签
HTML中的视频标签和音频标签分别为<video>
和<audio>
标签。
视频标签(<video>
)
语法:
<video src="视频文件地址" width="宽度" height="高度" controls="controls">
您的浏览器不支持 video 标签。
</video>
其中,src
属性指定了视频文件的地址,width
和height
属性指定了视频播放器的宽度和高度,controls
属性用于显示视频控制按钮。
示例:
<video src="video.mp4" width="640" height="480" controls="controls">
您的浏览器不支持 video 标签。
</video>
音频标签(<audio>
)
语法:
<audio src="音频文件地址" controls="controls">
您的浏览器不支持 audio 标签。
</audio>
其中,src
属性指定了音频文件的地址,controls
属性用于显示音频控制按钮。
示例:
<audio src="audio.mp3" controls="controls">
您的浏览器不支持 audio 标签。
</audio>
需要注意的是,视频和音频文件格式有很多种,不同的格式支持情况也有所不同。在实际使用中,最好提供多种格式的文件,以便于不同浏览器和设备能够正常播放。
换行标签
HTML换行标签是 <br>
。在 HTML 中,<br>
表示换行符,可以在段落中插入一个简单的换行符,而不是分段。
例如:
<p>这是第一行。<br>这是第二行。</p>
上面的代码将生成一个段落,其中一行包含两个句子,这两个句子之间用换行符分隔。
需要注意的是,<br>
标签是一个单标签,不需要闭合标签。
空格
在 HTML 中,空格占位符可以使用
实现。实际上,HTML 中默认是忽略连续的空格的,可以使用空格占位符来强制浏览器显示空格。这对于需要在 HTML 中控制布局的情况特别有用。
例如,如果您希望在段落中有一些额外的间距而不想使用 CSS,请使用空格占位符:
<p>这是一些 额外的间距。</p>
在上面的例子中,我们在“一些”和“额外的间距”之间插入了七个空格占位符,以便在这些单词之间添加一些额外的间距。
需要注意的是,
是一个实体名称,而不是一个标签,因此不能使用  
或其他类似的形式。
div标签
<div>是HTML中最基本的容器标签,其作用是为一组相关的元素提供容器,用于组织页面内容的布局结构。同时,<div>标签也可以用作CSS样式的容器,方便开发者为其内部元素应用相同的样式。
<div>标签没有特定的语义含义,具有很强的通用性和灵活性。HTML中的大部分元素都可以放置在<div>标签内部,如文本、图片、视频、音频等。
<div>标签的使用范例:
<div>
<h1>这是一个标题</h1>
<p>这是一段文字</p>
<img src="image.jpg" alt="图片">
</div>
上述代码中,<div>标签作为一个容器,包含了一个标题、一段文字和一张图片。开发者可以为这个<div>容器设置样式,例如设置其宽度、背景颜色、边框等。
span标签
<span>标签是HTML中用于标记短小文本片段的标签,相较于<div>标签,<span>标签更为精细和细致,其通常用来对文本进行局部样式设置、添加超链接、标记颜色、标记语义等操作。
<span>标签可用于内联文本,例如,在一段文本中用于标记一个词或一个短语。与<div>标签不同,<span>标签不会自动换行,而是将内嵌的内容作为一整个行内元素展示出来。
例如:
<p>这是一段包含<span>重要信息</span>的文本。</p>
上述代码中,<span>标签用于对“重要信息”一词进行标记,可以方便地为其设置样式,例如加粗、变色、添加下划线等效果。
表格标签
HTML中用于创建表格的主要标签有以下几个:
-
<table>:定义一个表格。
-
<tr>:定义表格中的一行。
-
<td>:定义行中的一个单元格。
-
<th>:定义行中的一个表头单元格。
-
<caption>:定义表格的标题。
-
<thead>:定义表格的头部。
-
<tbody>:定义表格的主体部分。
-
<tfoot>:定义表格的脚注部分。
<table>标签是创建表格的基础标签,其内部必须包含至少一个<tr>标签,每个<tr>标签必须包含至少一个<td>或<th>标签,而<th>标签用于定义表格的表头,会自动加粗并居中显示。
例如,下面是一个包含表头、主体和脚注部分的简单表格:
<table>
<caption>2019年度休假情况</caption>
<thead>
<tr>
<th>姓名</th>
<th>职位</th>
<th>年假</th>
<th>事假</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>经理</td>
<td>15天</td>
<td>2天</td>
</tr>
<tr>
<td>李四</td>
<td>主管</td>
<td>12天</td>
<td>3天</td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="2">总计</th>
<td>27天</td>
<td>5天</td>
</tr>
</tfoot>
</table>
表单标签
HTML中用于创建表单的主要标签有以下几个:
-
<form>:定义一个表单,用于向服务器发送用户输入的数据。
-
<input>:定义表单中的输入控件,可以输入文本、选项、按钮等。
-
<label>:定义表单控件的标签。
-
<select>:定义一个下拉菜单,供用户选择其中一个选项。
-
<option>:定义下拉菜单的选项。
-
<textarea>:定义一个文本输入区域。
-
<button>:定义一个按钮。
-
<fieldset>:定义一个表单的一组相关控件。
-
<legend>:定义<fieldset>标签的标题。
<body>
<!-- form表单属性:
action:表单提交的url,往何处提交数据,如果不指定,默认提交到当前页面
method:表单的提交方式
get:在url后面凭借表单数据,比如:?username=tom&password=123& age=22,
url长度有限制,默认值
post:在消息体(请求体)中传递,参数大小无限制-->
<form action="" method="get">
用户名:<input type="text" name="username"></input>
密码:<input type="password" name="password"></input>
年龄:<input type="text" name="age"></input>
<input type="submit" value="提交">
<form action="" method="post">
用户名:<input type="text" name="username"></input>
密码:<input type="password" name="password"></input>
年龄:<input type="text" name="age"></input>
<input type="submit" value="提交">
</form>
</body>
例如,下面是一个包含文本输入框、密码输入框、单选框、多选框、下拉菜单、文本输入区域、按钮等控件的表单:
<form action="/submit-form" method="post">
<fieldset>
<legend>个人信息</legend>
<label for="name">姓名:</label>
<input type="text" id="name" name="name" required>
<br>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
<br>
<label>性别:</label>
<input type="radio" name="gender" value="male" checked>男
<input type="radio" name="gender" value="female">女
<br>
<label>爱好:</label>
<input type="checkbox" name="hobby" value="reading">阅读
<input type="checkbox" name="hobby" value="music">音乐
<input type="checkbox" name="hobby" value="travel">旅游
<br>
<label for="city">城市:</label>
<select id="city" name="city" required>
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
</select>
<br>
<label for="message">留言:</label>
<textarea id="message" name="message" rows="5"></textarea>
</fieldset>
<br>
<button type="submit">提交</button>
</form>
表单标签-表单项
<body>
<form action="">
姓名:<input type="text" name="username"><br>
密码:<input type="password" name="password"></input><br>
性别<label><input type="radio" name="gender" value="1">男</input></label>
<label><input type="radio" name="gender" value="2">女</input> </label><br>
Java <label> <input type="checkbox" name="学科" id=""></label>
python<label><input type="checkbox" name="学科" id=""></label><br>
邮箱:<input type="email" name="e-mal" id=""><br>
数字输入框<input type="number" name="number" id=""><br>
定义文件上传 <input type="file" name="file" id=""><br>
学历 <select name="degree">
<option value="">请选择</option>
<option value="1">大专</option>
<option value="2">本科</option>
<option value="3">博士</option>
<option value="4">硕士</option>
</select>
</form>
</body>
css样式-首行缩进
在 CSS 中实现首行缩进的方法有两种:使用 text-indent
属性和使用 padding-left
属性。
使用 text-indent
属性:
语法:
selector {
text-indent: length;
}
其中,selector
为要应用样式的元素选择器,length
为缩进距离,可以是像素值、百分比、em 等长度单位。如果缩进距离为负数,则表示向左侧缩进。
示例:
p {
text-indent: 2em;
}
上面的样式将会使 <p>
元素的首行缩进 2 个字符的宽度。
使用 padding-left
属性:
语法:
selector {
padding-left: length;
text-indent: -length;
}
其中,selector
为要应用样式的元素选择器,length
为缩进距离,可以是像素值、百分比、em 等长度单位。如果缩进距离为负数,则表示向左侧缩进。需要注意的是,为了使首行缩进生效,需要将 text-indent
属性设置为负数的同等距离。
示例:
p {
padding-left: 2em;
text-indent: -2em;
}
上面的样式将会使 <p>
元素的首行缩进 2 个字符的宽度。这种方法还可以通过设置不同的 padding-left
值来实现不同级别的缩进。
盒子模型
CSS盒子模型是指在网页中每个元素都是一个矩形的盒子,由四条边和四个角组成。CSS盒子模型包括以下几个部分:
- 内容区(Content):元素的内容,比如文本、图片等,属于内容的展示部分。
- 填充区(Padding):紧贴内容区的区域,属于元素内部的空白区域。
- 边框(Border):包围着填充区的边框线,可以设置边框的样式、宽度和颜色等属性。
- 外边距(Margin):位于填充区和周围元素之间的空白区域。
上述四个部分形成了一个完整的盒子模型,可以通过CSS设置它们的各种属性,包括宽度、高度、边框样式、内外边距等等。盒子模型的尺寸计算方式为:元素的宽度 = 左右内边距 + 左右边框 + 左右外边距 + 内容区宽度,元素的高度则是上下内边距 + 上下边框 + 上下外边距 + 内容区高度。
CSS盒子模型的标准模型和IE盒子模型的区别在于,标准模型的宽高只包括内容区,而IE盒子模型的宽高包括了填充和边框。在CSS中采用标准盒子模型,可以通过box-sizing属性控制。
JavaScript
跨平台面向对象的脚本语言
js的引入方式
JavaScript可以通过以下方式引入:
-
内联方式:直接在网页中嵌入JavaScript代码,例如:
<script> // JavaScript代码 </script>
-
外部引用方式:将JavaScript代码写入一个单独的文件中,然后在HTML文件中通过
<script>
标签引用该文件,例如:<script src="path/to/javascript.js"></script>
这里的
path/to/javascript.js
是JavaScript代码所在的路径。 -
模块导入方式:通过
<script type="module">
标签引入JavaScript模块,例如:<script type="module" src="path/to/javascript.js"></script>
此时,
javascript.js
文件必须是符合ES6模块标准的JavaScript代码。
JS基础语法
书写语法
1.区分大小写
2.每行结尾的分号可有可无
注释:
单行注释://注释内容
多行注释:/*注释内容*/
大括号表示代码块
//判断
if(count==3){
alert(count);
}
输出语句
<script>
window.alert("hello js");//浏览器弹出警告框
document.write("hello js");//写入HTML。在浏览器展示
console.log("hello js")//写入浏览器控制台
</script>
变量
用var来声明变量,js是一门弱类型语言,变量可以存放不同类型的值。
var a = 20;
a ="张三";
变量名需要遵循如下规则:
组成字符可以是任何字母,数字,下划线(_)或者美元符号($)
数字不能开头
建议使用驼峰命名
注意:1.ES6新增了let关键字来定义变量,它的用法类似于var,但是所声明的变量,只在let关键字所在的代码块内有效,且不允许重复声明。
2.ES6新增const关键字,用来声明一个只读的变量,一旦声明,常量的值就不能改变。
<script>
// var定义变量
// var a=10;
// a="张三";
// alert(a);
//var定义变量 特点:1.作用域比较大,全局变量
// 2.可以重复定义
// {
// var x=1;
// var x=A;
// // alert(x);
// }
// alert(x);
// let:局部变量,不能重复定义
{
let x=1;
// let x=0;
alert(x);
}
// const:常量,不能改变
const p=666;
// p1=555;
alert(p);
</script>
数据类型,运算符,流程控制语句
原始类型和引用数据类型
原始类型:
number:数字(整数,小数,Nat(Not a Number))
string:字符串,单双引皆可
boolean:布尔,true,false
null:对象为空
undefined:当声明的变量未初始化时,该变量的默认值是undefined
使用typeof运算符可以获取数据类型:
<script>
// 原始数据类型
alert(typeof 3);//number
alert(typeof 3.14);//number
alert(typeof "A");//string
alert(typeof 'HELLO');//string
alert(typeof true);//boolean
alert(typeof false);//boolean
alert(typeof null);//object:一个对象
var a;
alert(typeof a);//undefined
</script>
运算符
js函数
执行特定任务的代码块
定义需通过function关键字来定义,语法为:
<script>
function functionName(参数1,参数2){
//要执行的代码
}
</script>
例如:
function functionName(a,b){
//要执行的代码
return a+b;
}
注意:形式参数不需要类型,因为js是弱类型语言。返回值也不需要定义类型,可以在函数内部直接使用return返回即可
调用:函数名称(实际参数列表)
<script>
//调用函数
var result= add(10,30);
return result;
//定义函数
function add(a,b){
//要执行的代码
return a+b;
}
定义函数2:
// 定义函数-2
var add=function (参数1,参数2){
//执行代码块
}
例如:
<script>
//调用函数
var result= add(10,30);
return result;
// 定义函数-2
var add=function (a,b){
return a+b;
}
注意:JS函数调用可以传递任意参数
js对象
Array
<script>
//定义数组
// var arr= new Array(1,2,3,4,5,6);
// var arr = [1, 2, 3, 4];
// console.log(arr[0]);
// console.log(arr[1]);
//特点:长度可变类型可变
// var arr = [1, 2, 3, 4];
// arr[10] = 50;
// console.log(arr[10]);
// console.log(arr[9]);
// arr[9]="A";
// arr[8]=true;
// console.log(arr);
var arr = [1, 2, 3, 4];
arr[10]=50;
// for (let i = 0; i < array.length; i++) {
// console.log(arr[i]);
// }
// forEach:遍历数组中有值的函数
// arr.forEach(function(e){
// console.log(e);
// })
//ES6箭头函数:{...} => {....} 简化函数定义
// arr.forEach((e) => {
// console.log(e);
// })
//push:添加元素到数组末尾
// arr.push(7,8,9);
// console.log(arr);
//splice:删除元素
arr.splice(2,2);
console.log(arr);
</script>
String
<!-- 创建字符串 -->
<script>
var str="我爱学Java";
alert(str);
console.log(str);
//length获取字符串长度
console.log(str.length);
//charAt获取指定位置的字符
console.log(str.charAt(3));
//indexof检索字符串
console.log(str.indexOf("Java"));
//trim去除字符串左右两侧空格
var s=str.trim();
console.log(s);
//substring(start,end)---start开始索引,end结束索引(含头不含尾)
console.log(s.substring(0,7));
</script>
JSON
自定义对象
<script>
//自定义对象
var user={
name:"TOM",
age:10,
gender:"男",
// eat:function(){
// alert("吃饭")
// }
eat(){
alert("吃饭");
}
}
alert(user.name);
alert.eat();
</script>
JSON介绍
JSON基础语法
<script>
//定义JSON
var str='{"name":"TOM","age":18,"addr":["日本","亚洲"]}';
//json字符串==>js对象
var k=JSON.parse(str);
alert(k.name);
//js对象转为json字符串
var str1= JSON.stringify(k);
alert(str1)
</script>
BOM
Window
<script>
//获取Window
window.alert("你好BOM")
alert("你好,星期天")
//方法
//confirm 对话框 确认:true 取消:false
// confirm("确认打开星期天?")
var k=confirm("确认打开星期天?");
alert(k);
//定时器 setInterval---周期性的执行某一个函数
// var i=0;
// setInterval(function(){
// i++;
// console.log("执行了"+i+"次");
// },1000);
//定时器 setTimeout 延迟指定时间执行一次
setTimeout(function(){
alert("hello")
},2000)
</script>
location
<script>
//location 获取当前域名
alert(location.href)
//设置指定域名
location.href="http://www.baidu.com"
</script>
DOM
获取对象
js事件监听
事件:发生在HTML上的事情;如:按钮被点击了,鼠标移动到元素上,按下键盘
事件监听:JavaScript可以在事件被侦测到时执行代码
事件绑定
<body>
<input type="button" value="事件绑定1" id="but1" onclick="on()">
<input type="button" value="事件绑定2" id="but2">
<script>
function on(){
alert("按钮1被点击了")
}
document.getElementById("but2").onclick=function(){
alert("按钮2被点击了")
}
</script>
</body>
常见事件
Vue
是一套前端框架,免除原生JS中的DOM操作,简化书写。基于MVVM思想,实现数据双向绑定
官网:https://v2.cn.vuejs.org/
MVVM
MVVM是一种软件架构模式,包括三个核心组件:Model、View、ViewModel。
- Model:即数据模型,是应用程序中处理数据和业务逻辑的部分。它从数据源获取数据、验证数据并对其进行修改。
- View:即用户界面,是应用程序中处理交互的部分,它负责向用户展示数据并响应用户的操作。
- ViewModel:是连接 Model 和 View 的核心组件,它负责将 Model 中的数据转换成View可以使用的数据,并将用户的操作转换成Model可以理解的操作。同时,ViewModel还负责将数据变更通知给View,从而保证View与Model保持同步。
MVVM的核心思想是数据绑定,即通过数据绑定,将ViewModel中的数据与View中的UI元素进行绑定,实现数据的自动更新。这样,当ViewModel中的数据发生变化时,相应的UI元素也会自动更新,无需手动操作。
MVVM的优点有:
- 分离关注点:通过将数据处理、业务逻辑和UI元素分离,MVVM能够使得应用程序的不同部分之间关注点更加清晰,代码更容易维护和扩展。
- 可测试性:ViewModel中的数据和业务逻辑可以进行单元测试,View中的UI元素也可以进行UI测试,从而保证应用程序的质量。
- 可重用性:由于MVVM将数据和UI元素分离,因此可以更加容易地将ViewModel重用于不同的View上。
MVVM是目前较为流行的前端框架(如Vue.js、Angular.js等)所使用的架构模式,也逐渐受到后端开发者的青睐并应用于后端开发中。
快速入门
1.新建HTML页面,引入Vue.jswenjian
2.在JS代码区域,创建Vue核心对象,定义数据模型
3.编写视图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue快速入门</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
{{
message
}}
</div>
</body>
<script>
new Vue({
el:'#app',//vue接管区域
data:{
message:'hello vue!'
}
})
</script>
</html>
插值表达式
形式:{{表达式}}
内容可以是:
变量,三元运算符,函数调用,算数运算
Vue常用指令
v-bind和v-model
v-bind
为HTML标签绑定属性值,如设置href,css样式等
书写格式:
<标签 v-bind:属性名="元素">
例如:
<a v-bind:href="url">星期天</a>
也可简写为:
<a :href="url">星期天</a>
v-model
在表单元素上创建双向绑定数据
书写格式
<input type=""text" v-model="url">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/vue.js"></script>
</head>
<body>
<div id="app">
<!-- <a v-bind:href="url">点一下</a> -->
<a :href="url">点一下</a>
<input type="text" v-model="url">
</div>
<script>
new Vue({
el:"#app",
data:{
url:'https://www.baidu.com'
}
})
</script>
</body>
</html>
注意:通过v-bind或者v-model绑定的变量,必需在数据模型中声明
v-on
为HTML标签绑定事件
<input type="button" value="按钮" v-on:click="h">
<input type="button" value="按钮" @click="h">
methods:{
h:function(){
alert('我被点击了')
}
}
<body>
<div id="app">
<!-- <input type="button" value="点我一下" v-on:click="handle()"> -->
<input type="button" value="点我一下" @click="handle()">
</div>
<script>
new Vue({
el:"#app",
data:{
},
methods:{
handle:function(){
alert("我被点击了");
}
}
})
</script>
</body>
v-if,v-show,v-else和v-else-if
<div id="app">
年龄<input type="text" v-model="age">经判定,为:
<span v-if="age<=35">年轻人(35岁以下)</span>
<span v-else-if="age>=36&&age<=60">中年人(35-60)</span>
<span v-else="age>=60"</span>>老年人(60及以上)</span>
<br>
年龄<input type="text" v-model="age">经判定,为:
<span v-show="age<=35">年轻人(35岁以下)</span>
<span v-show="age>=36&&age<=60">中年人(35-60)</span>
<span v-show="age>=60"</span>>老年人(60及以上)</span>
</div>
<script src="../lib/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
age:20
},
methods:{
}
})
</script>
v-for
列表渲染,便案例容器的元素或者对象的属性
Vue的生命周期
<script src="../lib/vue-2.4.0.js"></script>
<script>
new Vue({
el: '#app',
data: {
},
methods:{
},
mounted(){
alert("vue挂载完成,发送请求到服务器")
}
})
</script>
Ajax
同异步请求
原生Ajax
- 准备数据地址
- 创建XMLHttpRequest对象:用于和服务器交换数据
- 向服务器发送请求
- 获取服务器相应数据
具体可以去W3c查看
Axios
介绍:Axios对原生的Ajax进行了封装,简化书写,快速开发
官网:https://www.axios-http.cn/
快速入门
可简化为:
前后端分离开发
YAPI
YAPI是高效,易用,功能强大的api管理平台,旨在为开发,产品,测试人员提供更优雅的接口管理服务
地址:http://yapi.smart-xwork.cn/
前端开发工程化
环境准备
vue-cli
安装NodeJS
官网下载
配置
完成
v-cli安装
配置淘宝镜像全局配置
下载vue-cli脚手架
安装完成
Vue项目简介
vue项目创建
图形化界面打不开解决方案:关于Vue ui 的没反应、报错问题解决总结_vue.js_脚本之家
npm install -g @vue/cli 常见问题_我是PHP小白的博客-CSDN博客
npm 下载vue-cli出错npm安装报错(npm ERR! code EPERM npm ERR! syscall mkdir npm ERR! path C:\Program Files\nodejs\node_ca...)_晴雷的博客-CSDN博客
继承终端下载
1.
vue create vue-test
2.
创建完成
结构
项目启动
端口号配置
开发流程
异常处理
原因node.js版本过低,解决方法npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! vue-ts-vite@0.0.0 dev: `vite` npm ERR! Exit statu_礼貌而已的博客-CSDN博客
Element
Vue的组件库Element
快速入门
<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>
常见组件
<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>
<br>
<!-- table -->
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
<!-- 分页 -->
<!-- layout组件布局: -->
<el-pagination background layout="prev, pager, next"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:total="1000"
></el-pagination>
<br>
<!-- Table -->
<el-button type="text" @click="dialogTableVisible = true">打开嵌套表格的 Dialog</el-button>
<el-dialog title="收货地址" :visible.sync="dialogTableVisible">
<el-table :data="gridData">
<el-table-column property="date" label="日期" width="150"></el-table-column>
<el-table-column property="name" label="姓名" width="200"></el-table-column>
<el-table-column property="address" label="地址"></el-table-column>
</el-table>
</el-dialog>
<!-- Dilog打开Form表单 -->
<el-button type="text" @click="dialogFormVisible = true">打开嵌套Form的 Dialog</el-button>
<el-dialog title="打开Form表单" :visible.sync="dialogFormVisible">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="活动名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动区域">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
</el-col>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">提交</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
form: {
name: '',
region: '',
date1: '',
date2: '',
},
gridData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}],
dialogTableVisible: false,
dialogFormVisible:false,
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
},
methods:{
handleSizeChange:function(val){
alert("每页记录数变化"+val)
},
handleCurrentChange:function(val){
alert("每页展示记录数"+val)
},
onSubmit: function() {
alert(JSON.stringify(this.form))
}
}
}
</script>
<style>
</style>
Vue路由
介绍
安装
打包部署
打包
集成终端打包命令:
生成一个dist文件夹即可
部署
异常
端口被占用
查看80端口被谁占用
解决方案:
修改nginx端口
访问
web后端开发
基础技术
Maven
什么是maven?
是一款用于管理和构建Java项目的工具
maven的作用
依赖管理
管理Java相关的jar包
统一项目结构
项目构建
Maven概述
介绍
安装
IDEA集成Maven
配置Maven环境
创建Maven项目
导入Maven
依赖管理
依赖配置
依赖传递
依赖范围
Maven生命周期
springBoot web后端开发
官网:http://spring.io
spring提供了若干个子项目,每个项目用于完成特定的功能,spring boot可以帮助我们非常快速的构架应用程序,简化开发,提高效率
spring boot web入门
案例:
HTTP协议
HHTP-概述
HTTP协议-请求协议
HTTP响应协议
状态码
Web服务器-Tomcat
简介
Tomcat基本是使用
spring bootWeb-入门程序解析
请求响应
概述
请求
请求响应——Postman
简单参数
实体参数
数组集合参数
日期参数
JSON 参数
路径参数
小结
响应数据
统一响应结果
小结
分层解耦
三层架构
分成解耦
IOC&DI入门
@Conponent
将当前类交给IOC容器管理,成为IOC容器中的bean
@Autowired
运行时,IOC容器会提供该类型的bean对像,并取值给该变量---依赖注入
IOC详解
Bean的声明
Bean组件扫描
DI详解
小结
数据库
MySQL概述
安装,配置
数据模型
关系型数据库
SQL简介
SQL分类
数据库设计-DDL
数据库
创建数据库
create database javawebtest;
切换使用数据库
use javawebtest;
查看当前使用数据库
select datdabase();
查看所有数据库
show databases;
查看数据库中所有表
show tables;
删除数据库
drop database javawebtest;
图形化工具
表结构操作-DDL
创建
-- 创建数据库
create database javawebtest;
-- 创建表结构
create table tb_user(
-- 唯一标识 auto_increment:自增长
id int primary key auto_increment comment 'ID,唯一标识',
-- 非空且唯一
username varchar(20) not null unique comment '用户名',
-- 非空
name varchar(10) not null comment '姓名',
age int comment '年龄',
-- 默认值为男
gender char(1) default '男' comment '性别'
)comment '用户表';
常见的数据类型
查询
修改
删除
表结构操作-DML
添加insert
更新update
删除delete
表结构操作-DQL
基本查询
条件查询
分组查询-聚合函数
分组查询
排序查询
分页查询
多表设计
一对多
一对一
多对多
多表查询
内连接
外连接
子查询
标量子查询
列子查询
行子查询
表子查询
事务
四大特性
索引
结构
B+树
语法
Mybatis
入门
配置SQL提示
JDBC
数据库连接池
切换数据库连接池
lombok
<!-- lombok插件引入-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
MyBatis基本操作
环境准备
删除
@Mapper
public interface EmpMapper{
//根据ID 删除数据 #{}:mybatis占位符
@Delete("delete from emp where id="#{id}")
public void delete(Integer id);
// public int delete(Integer id);
}
@SpringBootTest
class SpringbootMybatisCrudApplicationTest{
//声明接口
@Autowired
private EmpMapper empMapper;
@Test
public void testDelete(){
//int delete=empMapper.delete(1);
//System.out.println(delete);
empMapper.delete(1);
}
}
日志输出
SQL执行流程
预编译流程
SQL注入
参数占位符
添加
@Mapper
public interface EmpMapper{
//新增员工
//@Insert(insert into emp(username,name,gender,job) values("Tom","汤姆",1,1)
@Insert(insert into emp(username,name,gender,job) values(#{username},#{name},#{gender},#{job})
public void insert(Emp emp);
}
@SpringBootTest
class SpringbootMybatisCrudApplicationTest{
//构造员工对象
Emp emp=new Emp();
emp.setUsername("Tom");
emp.setName("汤姆");
emp.setGender((short)1);
emp.setJob((short)1);
//执行添加员工信息操作
empMapper.insert(emp);
}
主键返回
在添加成功后,需要获取数据库数据的主键
@Options(userGeneratedKeya=true,keyProperty="id")
@Mapper
public interface EmpMapper{
//新增员工
//@Insert(insert into emp(username,name,gender,job) values("Tom","汤姆",1,1)
@Insert(insert into emp(username,name,gender,job) values(#{username},#{name},#{gender},#{job})
public void insert(Emp emp);
}
@SpringBootTest
class SpringbootMybatisCrudApplicationTest{
//构造员工对象
Emp emp=new Emp();
emp.setUsername("Tom");
emp.setName("汤姆");
emp.setGender((short)1);
emp.setJob((short)1);
//执行添加员工信息操作
empMapper.insert(emp);
System.out.println(emp.getId);
}
修改
@Mapper
public interface EmpMapper{
//修改员工信息
@Update("update emp set username=#{username},name=#{name},gender=#{gender},job=#{job}")
public void update(Emp emp);
}
@SpringBootTest
class SpringbootMybatisCrudApplicationTest{
//构造员工对象
Emp emp=new Emp();
emp.setUsername("Tom");
emp.setName("汤姆");
emp.setGender((short)1);
emp.setJob((short)1);
//修改员工信息
empMapper.update(emp);
}
查询
@Mapper
public interface EmpMapper{
//根据ID查询
@Select("select * from emp where id=#{id} ")
public Emp getById(Integer id);
}
@SpringBootTest
class SpringbootMybatisCrudApplicationTest{
@Test
public void testGetById(){
Emp emp = empMapper.getById(20);
System.out.println(emp);
}
}
数据封装
解决方案
@Mapper
public interface EmpMapper{
//根据ID查询
//方案一:给字段起别名,让别名与实体类属性一致
@Select("select id ,username ,name, gender ,job,create_time createTime,update_time updateTime,dept_id deptId from emp where id=#{1} ")
public Emp getById(Integer id);
//方案二:通过@Results,@Result注解手动映射封装
@Results({
@Result(column="dept_id",property="deptId"),
@Result(column="create_time",property="updateTime"),
@Result(column="update_time",property="updateTime"),
})
@Select("select * from emp where id=#{id} ")
public Emp getById(Integer id);
}
在配置文件application.properties中
#方案三:开启Mybatis的驼峰命名自动映射开关------a_cloumn--------->aCloumn
mybatis.configuration.map-underscore-to-camel-case=true
在mapper中
@Mapper
public interface EmpMapper{
//根据ID查询
@Select("select * from emp where id=#{id} ")
public Emp getById(Integer id);
}
测试类
@SpringBootTest
class SpringbootMybatisCrudApplicationTest{
@Test
public void testGetById(){
Emp emp = empMapper.getById(20);
System.out.println(emp);
}
}
条件查询
@Mapper
public interface EmpMapper{
//条件查询员工
/* @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> list(String name,short gender,LocalData begin,LocalDate end);
*/
//concat:字符串拼接函数
@Select("select * from emp where name=like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc")
public List<Emp> list(String name,short gender,LocalData begin,LocalDate end);
}
@SpringBootTest
class SpringbootMybatisCrudApplicationTest{
@Test
public void List(){
empMapper.list("张",(short)1,LocalDate.of(2000,1,1),LocalDate.of(2001,2,2))
System.out.println(empList)
}
}
XML映射文件
<!--约束 mybatis中文网直接复制-->
<?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">
<!--namespase:命名空间-->
<mapper namespase="">
<!--resultType:单条记录所封装的类型-->
<select id="list" resultType="com.pojo.emp">
sql语句
</select>
</mapper>
Mybatis动态SQL
<if>
<?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.mapper.pojo.Emp">
<select id="list" resultTypr="com.pojo.Emp">
select *
from emp
<where>
<if test="name != null">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender=#{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
order by update_time desc
</where>
</select>
</mapper>
<foreach>
//批量删除员工
public void deleteByIds(List<Integer> ids){
}
<!--批量员工 (18,19,20)-->
<!--
collection:遍历的集合
item:遍历出来的元素
aeparator:分隔符
open:遍历开始前拼接的SQL片段
close:遍历结束后拼接的SQL片段
-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" aeparator="," open="(" close=")">
#{id}
</foreach>
</delete>
@Test
public void deleteByTds(){
List<Integer> ids=Arrays.asList(18,19,20);
empMapper.deleteByIds(ids);
}
<sql><include>
案例
环境搭建
统一结果封装类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}
查询
EmpController
@Slf4j//日志输出管理
@RestController
public class EmpController{
@Autowired
privater EmpService empservice;
//查询所有数据
@GetMapping("/emps")
public Result select(){
//调用service里面的delete方法,并用一个list集合接收
List<Emp> slectList= empservice.select();
return Result.succes(selectList);
}
}
EmpService
public interface EmpService(){
//查询所有
List<Emp> select();
}
EmpServiceImpl
@Service
public class EmpSerViceImpl implements EmpService(){
@Autorwide
private EmpMapper empmapper
//查询所有
@Override
public Result select(){
return empmapper.select();
}
}
EmpMapper
@Mapper
publuc interface EmpMapper(){
//查询所有
@Select("select * from emp")
List<Emp> select();
}
EmpController
//根据ID删除信息
@DeleteMapping("/emps/{id}")
public Result delete(@PathVariable Integer id){
empservice.delete(id);
renturn Result.success();
}
Service
void delete(Integer id);
EmpServiceImpl
@Override
public Result delete(Integer id){
empmapper.deleteById(id);
}
EmpMapper
@Delete("delete from emp where id=#{id}")
void deleteById(id);
新增
分页查询
分页查询插件
分页带条件查询
删除
新增员工
目录
介绍:Axios对原生的Ajax进行了封装,简化书写,快速开发
官网:https://www.axios-http.cn/
文件上传

本地存储
@RestController
@Slf4j
public class UploadController {
@PostMapping("/upload")
public Result upload(String name, Integer age, MultipartFile image) throws Exception {
log.info("上传文件:"+name+age+image);
//获取上传文件名
String originalFilename = image.getOriginalFilename();
//构造唯一的文件名(不能重复)-uuid(通用唯一识别码)
int index = originalFilename.lastIndexOf(".");
String extname = originalFilename.substring(index);
String newFileName= UUID.randomUUID().toString()+extname;
//将上传文件保存到本地
image.transferTo(new File("D:\\项目\\MavneTest\\imager"+newFileName));
return Result.success();
}
}
#配置单个文件上传大小限制
spring.servlet.multipart.max-file-size=10MB
#单个请求最大大小限制(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB
阿里云存储oss
private AliOSSUtils aliOSSUtils;
@PostMapping("/upload")
public Result upload(MultipartFile image) throws IOException {
log.info("文件上传");
//获取对象存储OSS文件上传
String upload = aliOSSUtils.upload(image);
log.info("文件上传,请求url为"+upload);
return Result.success(upload);
}
package com.example.tlias.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-beijing.aliyuncs.com";
private String accessKeyId = "自己的ID";
private String accessKeySecret = "自己的Secret";
private String bucketName = "bucketName";
/**
* 实现上传图片到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的路径返回
}
}
修改员工
查询,实现数据回显
修改员工
配置文件
yml配置文件
常见的yml格式
@ConfigurationProperties
登录认证
登录功能
package com.example.tlias.controller;
import com.example.tlias.pojo.Emp;
import com.example.tlias.pojo.Result;
import com.example.tlias.service.EmpService;
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.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class loginController {
@Autowired
private EmpService empService;
/**
* 登录功能
*/
@PostMapping("/login")
public Result login(@RequestBody Emp emp){
log.info("登录功能");
Emp e =empService.login(emp);
return e!=null ? Result.success():Result.error("用户名或密码不正确");
}
}
/**
* 登录
* @param emp
* @return
*/
Emp login(Emp emp);
/**
* 登录
* @param emp
* @return
*/
@Override
public Emp login(Emp emp) {
return empMapper.getByUserNameAndPwd(emp);
}
/**
* 根据用户名和密码实现登录
* @param emp
* @return
*/
@Select("select * from emp where username=#{username} and password=#{password}")
Emp getByUserNameAndPwd(Emp emp);
登录校验
会话技术
跨域
会话技术对比
JWT令牌
生成JWT令牌
依赖导入
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
/**
* 生成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, "wsulg")//设置签名算法
.setClaims(claims)//自定义内容
.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置有效期为一个小时
.compact();
System.out.println(jwt);
}
/**
* 解析JWT
*/
@Test
public void testParserJwt(){
Claims claims = Jwts.parser()
.setSigningKey("wsulg")
.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVE9NIiwiaWQiOjEsImV4cCI6MTY5MzI4OTY3Nn0.7kVfYCEzIseN4OWStIohc-ZIjrJGG-onb_7Xo7-xgA4")
.getBody();
System.out.println(claims);
}
JWT令牌跟踪会话
/**
* 登录功能
*/
@PostMapping("/login")
public Result login(@RequestBody Emp emp){
log.info("登录功能");
Emp e =empService.login(emp);
//登录成功,下发JWT令牌
if (e !=null){
Map<String, Object> claims= new HashMap<>();
claims.put("id",e.getId());
claims.put("username",e.getUsername());
claims.put("name",e.getName());
//生成JWT令牌
String jwt = JwtUtils.generateJwt(claims);
return Result.success(jwt);
}
//登陆失败返回错误信息
return Result.error("用户名或密码不正确");
}
过滤器Filter
package com.example.tlias.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class FilterDemo implements Filter {
@Override//初始化
public void init(FilterConfig filterConfig) throws ServletException {
//Filter.super.init(filterConfig);
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() {
//Filter.super.destroy();
System.out.println("调用了destroy方法");
}
}
package com.example.tlias;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.web.bind.annotation.RestController;
@ServletComponentScan//支持serclet
@SpringBootApplication
public class TliasApplication {
public static void main(String[] args) {
SpringApplication.run(TliasApplication.class, args);
}
}
登录过滤器
package com.example.tlias.filter;
import com.alibaba.fastjson.JSONObject;
import com.example.tlias.pojo.Result;
import com.example.tlias.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Request;
import org.springframework.util.StringUtils;
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 LoginChexkFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req= (HttpServletRequest) servletRequest;
HttpServletResponse reqs= (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
//手动转换 对象---json------>阿里巴巴fastJSON
String notLogin= JSONObject.toJSONString(error);
reqs.getWriter().write(notLogin);
return;
}
//5.解析token,如果解析失败,返回错误结果(未登录)
try {
JwtUtils.parseJWT(jwt);//校验令牌
}catch (Exception e){//解析失败
e.printStackTrace();
log.info("解析令牌失败,返回未登录的错误信息");
Result error = Result.error("NOT_LOGIN");
//将错误返回结果输出为json
//手动转换 对象---json------>阿里巴巴fastJSON
String notLogin= JSONObject.toJSONString(error);
reqs.getWriter().write(notLogin);
return;
}
//6.放行
log.info("令牌合法,放行");
filterChain.doFilter(servletRequest,servletResponse);
}
}
拦截器interceptor
package com.example.tlias.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 {
//HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
System.out.println("postHandle.....");
}
@Override//视图渲染后执行,最后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
System.out.println("afterCompletion....");
}
}
package com.example.tlias.config;
import com.example.tlias.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) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}
拦截路径
执行流程
拦截器完成登录校验
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override//目标哦资源方法运行前运行,返回true 放行,返回false,不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.获取请求url
String url = request.getRequestURL().toString();
log.info("获取到的url为"+url);
//2.判断请求url中是否包含login,如果包含,说明登录操作,放行
if (url.contains("login")){
return true;
}
//3.获取请求头中的令牌(token)
String jwt = request.getHeader("token");
//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
if (!StringUtils.hasLength(jwt)){
log.info("请求token为空,返回登录信息");
Result error = Result.error("NOT_LOGIN");
//将错误返回结果输出为json
//手动转换 对象---json------>阿里巴巴fastJSON
String notLogin= JSONObject.toJSONString(error);
response.getWriter().write(notLogin);
return false;
}
//5.解析token,如果解析失败,返回错误结果(未登录)
try {
JwtUtils.parseJWT(jwt);//校验令牌
}catch (Exception e){//解析失败
e.printStackTrace();
log.info("解析令牌失败,返回未登录的错误信息");
Result error = Result.error("NOT_LOGIN");
//将错误返回结果输出为json
//手动转换 对象---json------>阿里巴巴fastJSON
String notLogin= JSONObject.toJSONString(error);
response.getWriter().write(notLogin);
return false;
}
//6.放行
log.info("令牌合法,放行");
return true;
}
@Override//目标哦资源方法运行后运行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
System.out.println("postHandle.....");
}
@Override//视图渲染后执行,最后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
System.out.println("afterCompletion....");
}
}
异常处理
/**
* 全局统一异常处理类
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)//捕获所有异常
public Result ex(Exception ex){
ex.printStackTrace();
return Result.error("对不起,操作失败,请联系管理员");
}
}
spring事务管理&AOP
事务管理
日志开关配置
事物进阶
rollbackFor
propagation
AOP基础


AOP核心概念

AOP进阶
通知类型
通知顺序
切入点表达式
execution



@annotation
连接点
web后端开发——原理篇
配置优先级
Bean管理
获取Bean
Bean的作用域
第三方Bean
spring boot原理
自动配置
@Conditional
案例
总结
Maven高级
分模块设计与开发
分模块设计
继承与聚合
继承
版本锁定
聚合
私服
介绍
资源上传与下载
学习结束了,将继续跟随黑马老师啃编程!