文章目录
学习路线
Web开发–介绍(画大饼)
什么是Web?
Web:全球广域网,也成为万维网,能通过浏览器访问的网站
Web网站的工作流程
网站大致是由三个部分组成的
第一部分就是我们能看到的网页程序,也叫做前端程序
主要负责将数据以好看的样式呈现出来
前端程序是运行在前端服务器当中的
第二个部分是数据库程序
数据是在数据库程序当中存储和管理的,也就是数据库服务器
第三个部分就是后端(咱写的爪洼程序)
后端Java程序是运行在后端服务器中的
这个后端程序主要负责数据的逻辑处理
初识web前端
网页有哪些部分组成呢?
文字,图片,音频,视频,超链接…
我们看到的网页,背后的本质是什么?
程序猿写的前端代码
前端的代码是如何转换成用户眼中的网页的?
通过浏览器转化(解析和渲染)成用户看到的网页
浏览器中对代码进行解析渲染的部分,称为浏览器内核
不同的浏览器,内核不同,对于相同的前端代码解析的效果会存在差异。
web标准也称为网页标准,由一系列的标准组成,大部分由W3C(World Wide Web Consortium ,万维网联盟)负责指定。
三个部分组成
HTML:负责网页的结构(网页元素和内容)
CSS:负责网页的表现(页面元素的外观、位置等页面样式,如:颜色、大小等)
JavaScript:负责网页的行为(交互效果)
HTML
HTML:超文本标记语言
what is 超文本?
超越了文本的限制,比普通的文本更强大。除了文字信息,还可以定义图片、音频、视频等内容。
how to understand 标记语言?
由标签构成的语言
HTML标签都是预定义好的。例如:使用<a>
展示超链接,使用<img>
展示图片,<video>
展示视频。
HTML代码直接在浏览器中运行,HTML标签由浏览器解析。
CSS:层叠样式表,用于控制页面的样式(表现)。
W3school:W3school官方文档查询
里面有些流氓小广告,但无伤大雅
html奇奇怪怪的小特点
1、HTML标签不区分大小写
2、HTML标签属性值单双引号都可以
3、HTML语法松散(但还是严谨一点比较好)
VS Code
Visual Studio Code(简称 VS Code)是Microsoft于2015年4月发布的一款代码编辑器
VS Code对前端代码有非常强大的支持,同时也其他编程语言(例如:C++、Java、Python、PHP、Go等)
VS Code提供非常强大的插件库,大大提高了开发效率
注意事项:
作为一名软件开发工程师,建议以后安装所有与开发相关的软件,尽量安装在一个没有中文,不带空格的目录下。
html相关笔记详情可见:
1、Web前端笔记记录
2、web前端笔记(2)
3、Web前端笔记(三)
4、Web前端笔记记录(四)
JavaScript
闲聊部分:
JavaScript(简称:JS)是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能使网页可交互
JavaScript和Java是完全不同的语言,不论是概念还是设计。到那时基础语法类似。
JavaScript在1995由Brendan Eich发明,并在1997年成为ECMA标准
ECMAScript6(ES6)是最新的JavaScript版本(发布于2015年)。
ECMA:ECMA国际(前身为欧洲计算机制造商协会),制定了标准化的脚本程序设计语言ECMAScript,这种语言得到广泛应用。而JavaScript是遵守ECMAScript的标准的。
js引入方式
第一种方式:内部脚本,将js代码定义在HTML页面中
JavaScript代码必须位于
<script></script>
标签之中
在HTML文档中,可以在任意地方,放置任意数量的<script>
(就是看起来有点不符合规范)
一般会把脚本置于<body>
元素的底部,可改善显示速度
<script>
alert("Hello JavaScript")
</script>
第二种方式:外部脚本,将js代码定义在外部JS文件中,然后引入到HTML页面中(用的很多,也最常见)
外部js文件中,只包含JS代码,不包含
<script>
标签
<script>
标签不能自闭合(不能自闭合就是后面的</script>
不能不写)
<script src="js/demo.js"></script>
//在外部js文件中
alert("Hello JavaScript")
书写语法
- 区分大小写:与Java一样,变量名、函数名以及其他一切东西都是区分大小写的
- 每行结尾的分号可有可无(但是最好还是有,没有是因为它会自动给你加上,当然你肉眼看不见,是他在编译的时候加的)
- 注释://和/**/(和c++一样)
- 大括号表示代码块
输出语句:
window.alert()
警告框document.write()
HTML输出console.log
控制台输出(有很多网站的控制台输出的地方会有招人的信息)
<script>
window.alert("Hello JavaScript");//浏览器弹出警告框
document.write("Hello JavaScript");//写入HTML,在浏览器展示
console.log("Hello JavaScript");//写入浏览器控制台
</scropt>
变量
- JavaScript中用var关键字(variable的缩写)来声明变量。
- JavaScript是一门弱类型语言,变量可以存放不同类型的值。
- 变量名需要遵循的规则:由字母,数字,特殊符号组成;不能以数字开头;建议使用驼峰命名(在js取名字是件很苦恼的事情)
奇怪的js变量:
- js变量没有全局和局部变量之分,都是全局变量。
- 可以重复定义,后定义覆盖(正常逻辑)
ES6新增了let关键字来定义变量,它的用法类似于var,但是锁声明的变量,只在let关键字所在的代码块内有效(像其他编程语言起来了,简称正常起来了),且不允许重复声明。
ES6新增了const关键字,用来声明一个只读的常量,一旦声明,常量的值就不允许改变。(参照c++)
数据类型
很奇怪的玩意,明明不区分,但是还是有的,就像有嘴巴但是不用嘴巴吃饭一样
JavaScript中分为原始类型和引用类型
- number:数字(整数、小数、NaN(指的是这玩意不是一个数,但是它是一个数))
- string:字符串,单双引号都可以
- boolean:布尔逻辑。t,f
- null:空对象,是空的对象不是对象是空
- undefined:当声明的变量未初始化时,该变量的默认值是undefined,未定义
虽然有嘴巴但是不用嘴巴吃饭,但是还是给了辨别是不是嘴巴的方法;
- typeof,可以获取数据类型
运算符
- 算数运算符:+,-,*,/,%,++,–
- 赋值运算符:=,+=,-=,*=,/=。%=
- 比较运算符:>,<,>=,<=,!=,==,
===
- 逻辑运算符:&&,||,!
- 三元运算符:条件表达式?true_value:false_value
==会进行类型转换(隐式类型转换),然后比较大小
===不会类型转换,直接比较类型和大小
about类型转换
- 字符串类型转为数字:如果字面值不是数字,就转为NaN
- Number转布尔:0和NaN为false,其他都为true
- 字符串转布尔:空字符串为false,其他均为true
- Null和undefined:均转为false
流程控制
- if…else if … else …
- switch
- for
- while
- do … while
js函数
函数是被设计为执行特定任务的代码块
function fun(参数1,参数2,...){
//要执行的代码
}
//或者
var fun = function(参数1,参数2,...){
//要执行的代码
}
- 形式参数不需要类型。因为js是弱类型语言
- 返回值也不需要定义类型,可以在函数内部直接使用return返回即可
- 函数调用可以传递任意个数的参数。
Array数组
顾名思义数组使用来定义数组的
//定义
var 变量名 = new Array(元素列表)
var 变量名 = [元素列表];
//访问
arr[索引] = 值;
奇怪的数组
- 这里的数组相当于java的集合,数组的长度是可变的,而js是弱类型,里面可以存储任意类型的数据。
about数组
- length:设置或返回数组中元素的数量。
- forEach():遍历数组中的每个有值的元素,并调用一次传入的函数
- push():将新元素添加到数组的末尾,并返回新的长度。
- splice():从数组中删除元素。
箭头函数(ES6):是用来简化函数定义语法的。具体格式为:
( ... ) => { ... }
,如果需要给箭头函数起名字:var xxx = ( ... ) => { ... }
String
//定义字符串对象
var 变量名 = new String("...");
var 变量名 = "...";
about字符串
- length:字符串的长度
- charAt():返回在指定位置的字符。
- indexOf():检索字符串。
- trim():去除字符串两边的空格
- substring():提取字符串两个指定的索引号之间的字符。
JSON
//定义格式
var 对象名 = {
属性名1:属性值1,
属性名2:属性值2,
...
函数名称:function(形参列表){}
};
//调用格式
对象名.属性名;
对象名.函数名();
闲聊时见到
JSON概念:JavaScript Object Notation,JavaScript对象标记法。
JSON是通过JavaScript对象标记法书写的文本。
由于其语法简单,层次结构鲜明,先多用于作为数据载体,在网络张总进行数据传输
JSON语法定义
var 变量名 = '{"key1" : value1, "key2":value2}';
value的数据类型为
- 数字(整数或者浮点数)
- 字符串(在双引号中)
- 逻辑值(true或false)
- 数组(在方括号)
- 对象(在花括号中)
- null
JSON字符串转为JS对象
var jsobject = JSON,parse(userStr);
JS对象转为JSON字符串
var jsonStr = JSON.stringify(jsobject);
BOM
BOM:Browser Object Model浏览器对象模型,允许JavaScript与浏览器对话,JavaScript将浏览器的各个组成部分分装为对象。
- Window:浏览器窗口对象
- Navigator:浏览器对象
- Screen:屏幕对象
- History:历史记录对象
- Location:地址栏对象
Window
浏览器窗口对象
直接使用window,其中window.可以忽略
- history:对History对象的只读引用。
- location:用于窗口或框架的Location对象
- navigator:对Navigator对象的只读引用
- alert():显示嗲有一段消息和一个确认按钮的警告框。
- comfirm():显示带有一段消息以及确认按钮和取消按钮的对话框
- setInterval():按照指定的周期(以毫秒计)来调用函数或计算表达式。
- setTimeout():在指定的毫秒数后调用或计算表达式。
Location
地址栏对象
使用window.location获取,其中的window.可以省略
window.location.属性;
,location.属性;
- herf:设置或返回完整的URL
DOM
概念:Document Object Model,文档对象模型。
将标记语言的各个组成部分封装为对应的对象:
- Document:整个文档对象
- Element:元素对象
- Attribute:属性对象
- Text:文本对象
- Comment:注释对象
JavaScript通过DOM,就能够对HTML进行操作:
- 改变HTML元素的内容
- 改变HTML元素的样式
- 对HTML DOM事件作出反应
- 添加和删除HTML元素
DOM是W3C(万维网联盟)的标准,定义了访问HTML和XML文档的标准,分为3个不同的部分:
1、Core DOM - 所有文档类型的标准模型
- Document:整个文档对象
- Element:元素对象
- Attribute:属性对象
- Text:文本对象
- Comment:注释对象
2、XML DOM - XML 文档的标准模型
3、HTML DOM - HTML 文档的标准模型 - Image:
<img>
- Button:
<input type='button'>
HTML中的Element对象可以通过Document对象获取,而Document对象是通过window对象获取的
Document对象中提供了一下获取Element元素对象的函数:
1、根据id属性值获取,返回单个Element对象
var h1 = document.getElementById('h1');
2、根据标签名称获取,返回Element对象数组
var divs = document.getElementsByTagName('div');
3、根据name属性值获取,返回Element对象数组
var hobbys = document.getElementByName('hobby');
4、根据class属性值获取,返回Element对象数组
var clss = document.getElementByClassName('cls');
事件监听
事件:HTML事件是发生在HTML元素上的“事情”。比如:
- 按钮被点击
- 鼠标移动到元素上
- 按下键盘按键
事件监听:JavaScript可以在事件被侦测到时执行代码
事件绑定
1、通过HTML标签中的事件属性进行绑定
<input type="button" onclick="on()" value="按钮1">
<script>
function on(){
alert('我被点击了!');
}
</script>
2、通过DOM元素属性绑定
<input type="button" id="btn" value="按钮2">
<script>
document.getElementById( ' btn ' ).onclick=function(){
alert('我被点击了!');
}
</script>
常见事件
- onclick:鼠标单击事件
- onblur:元素失去焦点
- onfocus:元素获得焦点
- onload:某个页面或图像被完成加载
- onsubmit:当表单提交时触发该事件
- onkeydown:某个键盘的键被按下
- onmouseover:鼠标被移到某元素之上
- onmouseout:鼠标从某元素移开
Vue
Vue是一套前端框架,免除原生JavaScript中的DOM操作,简化书写
基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点都放在数据上。
官网:官网
框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。基于框架进行开发,更加快捷、更加高效。
新建HTML页面,引入Vue.js文件
<script src="js/vue.js"></script>
在JS代码区域,创建Vue核心对象,定义数据模型
<script>
new Vue({
el: "#app",
data: {
message: "Hello Vue ! "
}
})
</script>
编写视图
<div id="app">
<input type="text" v-model="message">
{{ message }}
</div>
常用指令
HTML标签上带有v-
前缀二点特殊属性,不同指令具有不同含义。例如:v-if
,v-for
…
常用指令:
- v-bind:为HTML标签绑定属性值,如设置hLef , css样式等
- v-model:在表单元素上创建双向数据绑定
- v-on:为HTML标签绑定事件
- v-if
- v-else-if:条件性的渲染某元素,判定为true时渲染,否则不渲染
- v-else
- v-show:根据条件展示某元素,区别在于切换的是display属性的值
- v-for:列表渲染,遍历容器的元素或者对象的属性
通过v-bind或者v-model绑定的变量,必须在数据模型中声明。
生命周期
生命周期:指一个对象从创建到销毁的整个过程。
生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法(钩子)
- beforeCreate:创建前
- created:创建后
- beforeMount:挂载前
- mounted:挂载完成
- beforeUpdate:更新前
- updated:更新后
- beforeDestroy:销毁前
- destroyed:销毁后
new vue ( {
el: "#app", // vue接管区域
data : {
},
methods : {
} ,
mounted (){
alert ( "vue挂载完成,发送请求到服务端")
}
})
mounted:挂载完成,Vue初始化成功,HTML页面渲染成功。(发送请求到服务端,加载数据)
Ajax
Asynchronous JavaScript And XML,异步的JavaScript
作用:
- 数据交换:通过Ajax可以给服务器发送请求,并获取服务器相应的数据。
- 异步交互:可以不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用的校验等等。
Axios
Axios对原生的Ajax进行了封装,简化书写,快速开发
官网:https://www.axios-http.cn/
1.引入Axios的js文件
<script src="js/axios-0.18.0.js"></script>
2.使用Axios发送请求,并获取响应结果
axios({
method: "get",
url: "http://yapi.smartxwork.cn/mock/169327/emp/list"
}).then((result)=>{
console.log(result.data);
});
axios(i
method: "post",
url: "http:/lyapi.smartxwork.cn/mock/169327/emp/deleteByld" ,
data: "id=1"
}).then((result)=> {
console.log(result.data);
});
请求方式别名
axios.get(url [, config])
axios.delete(url [, Eonfig])
axios.post(url [, data[, config]])
axios.put(url [, data[, config]l)
- 发送GET请求
axios.get("http://yapi.smartxwork.cn/mock/169327/emp/list").then((result)=>{
console.log(result.data);
});
- 发送POST请求
axios.post("http://yapi.smartxwork.cn/mock/169327/emp/deleteByld" "id=1").then((result)=>{
console.log(result.data);
});
YApi
YApi是高效、易用、功能强大的api管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务
http://yapi.smart-xwork.cn/
前端工程化
前端工程化是指在企业级的前端项目开发中,把前端开发所需要的工具、技术、流程、经验等进行规范化、标准化。
环境准备
Vue-cil是Vue官方提供的一个脚手架,用于快速生成一个Vue的项目模板
Vue-cil的功能
- 统一的目录结构
- 本地调试
- 热部署
- 单元测试
- 集成打包上线
依赖环境:NodeJS
vue目录结构
Vue的组件文件以.vue结尾,每个组件由三个部分组成:<template>
, <script>
,<style>
。
Element
Element:是饿了么团队研发的,一套为开发者、设计师和产品经理准备的基于Vue 2.0的桌面端组件库。
组件:组成网页的部件,例如超链接、按钮、图片、表格、表单、分页条等等。
官网: https://element.eleme.cn/#/zh-CNListener
安装ElementUI组件库(在当前工程的目录下),在命令行执行指令:
npm install [email protected]
引入ElementUI组件库
import ElementUI from 'element-ui ' ;
import 'element-ui/lib/theme-chalk/index.css ';
Vue.use(ElementUI);
Vue路由
介绍:Vue Router是Vue的官方路由
组成:
- VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件
<router-link>
:请求链接组件,浏览器会解析成<a>
<router-view>
:动态视图组件,用来渲染展示与路由路径相对应的组件
部署
Nginx
介绍:Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少,并发能力强,在各大型互联网公司都有非常广泛的使用。
maven
maven是apache旗下的一个开源项目,是一款用于管理和构建java项目的工具
Apache软件基金会,成立于1999年7月、是目前世界上最大的最受欢迎的开源软件基金会,也是一个专门为支持开源项目而生的非盈利性组织。
开源项目:https://www.apache.org/index.html#projects-list
Apache Maven是一个项目管理和构建工具,它基于项目对象模型(POM)的概念,通过一小段描述信息来管理项目的构建
maven的作用
- 依赖管理:方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题
- 统一项目结构:提供标准、统一的项目结构
- 项目构建:标准跨平台(Linux、Windows、MacOS)的自动化项目构建方式
全是洋文
maven模型↓
仓库:用于存储资源,管理各种jar包
- 本地仓库:自己计算机上的一个目录
- 中央仓库:由maven团队维护的全球唯一的。仓库地址:https://repo1.maven.org/maven21
- 远程仓库(私服):一般由公司团队搭建的私有仓库。
安装
- 安装步骤
1.解压apache-maven-3.6.1-bin.zip 。
2.配置本地仓库:修改conf/settings.xml中的为一个指定目录。
<localRepository>E:\developlapache-maven-3.6.1\mvn_repo</localRepository>
3.配置阿里云私服:修改conf/settings.xml中的标签,为其添加如下子标签;
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</urb>
<mirrorOf>central</mirrorOf>
</mirror>
4.配置环境变量:MAVEN_HOME 为maven的解压目录,并将其bin目录加入PATH环境变量。
maven坐标
什么是坐标?
- Maven中的坐标是资源的唯一标识,通过该坐标可以唯一定位资源位置。
- 使用坐标来定义项目或引入项目中需要的依赖。
Maven坐标主要组成 - groupld:定义当前Maven项目隶属组织名称(通常是域名反写,例如:com.itheima1)
- artifactld:定义当前Maven项目名称(通常是模块名称,例如order-service、goods-service)
- version:定义当前项目版本号
依赖配置
依赖:指当前项目运行所需要的jar包,一个项目中可以引入多个依赖。
配置
- 在pom.xml中编写
<dependencies>
标签 - 在
<dependencies>
标签中使用<dependency>
引入坐标 - 定义坐标的groupld,artifsctld,version
- 点击刷新按钮,引入最新加入的坐标
如果引入的依赖,在本地仓库不存在,将会链接远程仓库/中央仓库,然后下载依赖。(这个过程会比较耗时,耐心等待)
如果不知道依赖的坐标信息,可以到https://mvnrepository.com/中搜索
依赖传递
依赖具有传递性
- 直接依赖:在当前项目中通过依赖配置建立的依赖关系
- 简介依赖:被依赖的资源如果依赖其他资源,其他项目间接依赖其他资源
乱七八糟的依赖一大堆,那么我们可以排除依赖
排除依赖指主动断开的资源,被排除的资源无需指定版本。
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
依赖范围
依赖的jar包,默认情况下,可以在任何地方使用。可以通过<scope>..</scope>
设置其作用范围
作用范围
- 主程序范围有效(main文件夹范围内)
- 测试程序范围有效(test文件夹范围内)
- 是否参与打包运行(package指令范围内)
scope值
- compile(默认):主程序,测试程序,打包运行
- test:测试程序
- provided:主程序,测试程序
- runtime:测试程序,打包运行
生命周期
Maven的生命周期就是为了对所有的maven项目构建进行抽象和统一。
Maven中有三套相互独立的生命周期
- clean:清理工作。关注其中的clean
- default:核心工作,如:编译,测试,打包,安装,部署等。关注其中的compile、test、package、install
- site:生成报告、发布站点等。没啥要关注的
每套生命周期包含一些阶段(phase),阶段是有顺序的,后面的阶段依赖于前面的阶段。
- clean:移除上一次构建生成的文件
- compile:编译项目源代码
- test:使用合适的单元测试框架运行测试(junit)
- package:将编译后的文件打包,如:jar、war等
- install:安装项目到本地仓库
执行指定生命周期的两种方式:
- 在idea中,右侧的maven工具栏,选中对应的生命周期,双击执行。
- 在命令行中,通过命令执行。
Spring
官网:spring.io
Spring发展到今天已经形成了一种开发生态圈,Spring提供了若干个子项目,每个项目用于完成特定的功能。
Sprint Boot可以帮助我们非常快速的构建应用程序、简化开发、提高效率
快速入门
1、创建springboot工程,并勾选web开发相关依赖。
2、定义Hellocontroller类,添加方法hello,并添加注解。
3、运行测试。
这玩意的创建可以直接去官网上找和用,我的idea没有创建spring的模块。从官网上搞好下载,用idea打开就能用
HTTP协议
概述
概念: Hyper Text Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。
http的特点
1、基于TCP协议:面向连接,安全(三次握手四次挥手)
2、基于请求-响应模型的:一次请求对应一次相应
3、HTPP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的。
- 缺点:多次请求间不能共享数据
- 优点:速度快
请求协议
- 请求行:请求数据的第一行(请求方式、资源路径、协议)
请求头:第二行开始,格式:key:value
- Host:请求的主机名
- User-Agent:浏览器版本,例如Chrome浏览器的标识类似Mozilla/5.0…Chrome/79,IE浏览器的标识类似Mozilla/5.0(WIndows NT …)like Gecko
- Accept:标识浏览器能接受的资源类型,如
text/*
,image/*
或*/*
表示所有 - Accept-Language:表示浏览器偏好的语言,服务器可以据此返回不同语言的网页
- Accept-Encoding:表示浏览器可以支持的压缩类型,例如gzip,deflate等
- Content-Type:请求主体的数据类型
- Content-Length:请求主体的大小(单位:字节)
请求体:POST请求,存放请求参数(最后一个部分)
请求方式-GET:请求参数在请求行中,没有请求体,如/brand/findAll?name=OPPO&status=1。Get请求大小是有限制的。
请求方式-POST:请求参数在请求体中,POST请求大小是没有限制的。
响应协议
- 响应行:相应数据第一行(协议,状态码,描述)
- 响应头:第二行开始,格式:key:value
- 响应体:最后一部分,存放响应数据
响应状态码
- 1XX:响应中-临时状态码,表示请求已经接受成功,告诉客户端应该继续请求或者如果它已经完成则忽略它。
- 2XX:成功-表示请求已经被成功接受,处理已完成
- 3XX:重定向-重定向到其他地方:客户端再发起一次请求以完成整个处理。
- 4XX:客户端错误-处理发生错误,责任在客户端。如:请求了不存在的资源,客户端未被授权,禁止访问等。
- 5XX:服务器错误-处理发生错误,责任在服务端。如:程序抛出异常等。
状态码大全: https://cloud.tencent.com/developer/chapter/13553
响应头:
- Content-Type:表示该响应内容的类型,例如text/html,application/json。
- Content-Length:表示该响应内容的长度(字节数)。
- Content-Encoding:表示该响应压缩算法,例如gzip。
- Cache-Control:指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒。
- Set-Cookie:告诉浏览器为当前页面所在的域设置cookie。
Tomcat
Web服务器是一个软件程序,对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作,让Web开发更加便捷。主要功能是“提供网上信息浏览服务”。
简介
- 概念:Tomcat是Apache软件基金会一个核心项目,是一个开源免费的轻量级Web服务器,支持ServletJSP少量JavaEE规范。
- JavaEE: Java Enterprise Edition,Java企业版。指Java企业级开发的技术规范总和。包含13项技术规范:JDBC、JNDI、E)B、RMI、JSP、Servlet、XML、JMS、Java lDL、JTS、JTA、JavaMail、JAF
- Tomcat也被称为web容器、Servlet容器。Servlet程序需要依赖于Tomcat才能运行
- 官网: https://tomcat.apache.orgl
基本使用
-
下载:官网下载,地址https://tomcat.apache.org/download-90.cgi
-
安装:绿色版,直接解压即可
-
卸载:直接删除目录即可
-
启动:双击: bin\startup.bat
-
- 控制台中文乱码:修改conf/ logging.properties
- 控制台中文乱码:修改conf/ logging.properties
-
关闭:
-
- 直接x掉运行窗口︰强制关闭
-
- bin\shutdown.bat :正常关闭
-
- Ctrl+C:正常关闭
常见问题
- 启动窗口一闪而过:检查JAVA_HOME环境变量是否正确配置
- 端口号冲突:找到对应程序,将其关闭掉
配置Tomcat端口号(conf/server.xml)
<Connector port="8080" protocol="HTTP/1.1"
connerctionTimeout="20000"
redirectPort="8443" />
注意事项
HTTP协议默认端口号为80,如果将Tomcat端口号改为80,则将来访问Tomcat时,将不用输入端口号。
请求响应
- 请求(HttpServletRequest):获取请求数据
- 响应(HttpServletResponse):设置响应数据
- BS架构:Browser/Server。浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。(维护方便,但体验一般)
- CS架构:Client/Server,客户端/服务器架构模式。(开发、维护麻烦,但是体验不错)
请求
Postman
Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。
作用:常用于进行接口测试
简单参数
-
原始参数
在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取 -
SprintBoot方式
简单参数:
1、参数名与形参变量名相同,定义形参即可接受参数。
2、如果方法形参名称与请求参数名称不匹配,可以使用@RequestParam完成映射
@RequestParam中的required属性默认为true,代表该请求参数必须传递,如果不传递将报错。如果该参数是可选的,可以将required属性设置为false
数组集合参数
数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数
集合参数:请求参数名与形参集合名称相同且请求参数为多个,@RequestParam
绑定参数关系
日期参数
日期参数:使用@DateTimeFormat注解完成日期参数格式转换
但是日期格式五花八门,所以在传递的时候需要规范格式
Json参数
JSON参数:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接受参数,需要使用@RequestBody
标识
路径参数
路径参数:通过请求URL直接传递参数,使用{…}来标识该路径参数,需要使用@PathVariable
获取路径参数
小总结
1、简单参数
- 定义方法形参,请求参数名与形参变量名一致
- 如果不一致,通过@RequestParam手动映射
2、实体参数
- 请求参数名,与实体对象的属性名一致,会自动接受封装
3、数组集合参数
- 数组:请求参数名与数组名一致,直接封装
- 集合:请求参数名与集合名一致,@RequestParam绑定关系
4、日期参数
- @DateTimeFormat
5、JSON参数
- @RequestBody
6、路径参数
- @PathVariable
响应
@ResponsBody
- 类型:方法注解、类注解
- 位置:Controller方法上/类上
- 作用:将方法返回值直接响应,如果返回值类型是实体对象/集合,将会转换成JSON格式响应
- 说明:@RestController = @Controller + @ResponseBody
需要设置一个统一的响应结果,不然返回的数据过于随意,难以管理,不便维护
分层解耦
三层架构
controller:控制层,接受前端发送的请求,对请求进行处理,并响应数据。
service:业务逻辑层,处理具体的业务逻辑。
dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查。
单一职责原则
分层耦合
-
内聚:软件中各个功能模块内部的功能联系。
-
耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
-
软件设计原则:高内聚低耦合。
-
控制反转:Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转
-
依赖注入:Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入
-
Bean对象:IOC容器中创建、管理的对象,称之为bean
IOC&DI入门
1、Service层及Dao层的实现类,交给IOC容器管理
2、为Controller及Service注入运行时,依赖的对象
3、运行测试
IOC&DI
Bean的声明
要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一:
- @Component:声明bean的基础注解:不属于以下三类时,用此注解
- @Controller:@Component的衍生注解:标注在控制器类上
- @Service:@Component的衍生注解:标注在业务类上
- @Repository:@Component的衍生注解:标注在数据访问类上(由于与mybatis整合,用的少)
声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写。
使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller。
Bean组件扫描
- 前面声明bean的四大注解,要想生效,还需要被组件扫描注解@ComponentScan扫描。
- @ComponentScan注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SpringBootApplication中,默认扫描的范围是启动类所在包及其子包。
Bean注入
- @Autowired注解,默认是按照类型进行,如果存在多个相同类型的bean,将会报出如下错误:
- 通过以下几种方案来解决:
-
- @Primary
-
- @Qualifier
-
- @Resource
MyBatis
闲聊时刻
- MyBatis是一款优秀的持久层框架,用于简化JDBC的开发
- MyBatis本是Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis
- 官网:https://mybatis.org/mybatis-3/zh/index.html
传说中的快速入门
how to use MyBatis to 查询所有用户数据
1、准备工作(创建springboot工程、数据库表user、实体类User)
2、引入MyBatis的相关依赖,配置MyBatis
3、编写SQL语句(注解/XML)
八嘎配置,日他老母
JDBC
JDBC:(Java Data Connectivity),就是使用Java语言操作关系型数据库的一套API
- 这个sucker玩意是sucker公司官方定义的一套操作所有关系型数据库的规范,即接口
- 各个自讨苦吃的数据库厂商要去实现这套接口,提供数据库驱动jar包
- 而苦逼的我们就要用这套接口编程,编写的代码执行是驱动jar包中的实现类
基础操作
环境配置
准备数据库表emp
创建一个新的springboot工程,选择引入对应的起步依赖(mybatis、mysql驱动、lombok)application.properties中引入数据库连接信息
创建对应的实体类Emp(实体类属性采用驼峰命名)准备Mapper接口EmpMapper
删除
SQL语句:
delete from emp where id =17;
接口方法:
@Delete("delete from emp where id = #[id}7)
public void delete(integer id);
删除(预编译)
我们只知道了mysql数据库中删除了,但不知道他在干什么
可以通过mysql的日志信息查看
- 可以在application.properties中,打开mybatis的日志,并指定输出到控制台。
#指定mybatis输出日志的位置,输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutimpl
预编译SQL的优势
- 性能更高
- 更安全(防止SQL注入)
SQL注入式通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。
参数占位符
#{…}
- 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
- 使用时机:参数传递,都使用#{…}
${…}
- 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
- 使用时机:如果对表名、列表进行动态设置时使用
新增
- SQL语句:
insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)
values ('songyuanqiao' '宋远桥',1,'1.jpg',2,2012-10-09',2,2022-10-0110:00:00', 2022-10-0110:00:00');
- 接口方法:
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)"+
"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{dept_id},#{create_time},#{update_time})")
public void insert(Emp emp);
只打了
@Insert(“巴拉巴拉”)
爆红,错误显示“此处不允许注解”不要慌,继续往下打,爆红会消失的,实在不行项目刷新一下,重新打一遍
新增(主键返回)
描述:在数据添加成功后,需要获取插入数据库的主键。
如:添加套餐数据时,还需要维护套餐菜品关系表数据。
- 实现
@Options(keyProperty = "id", useGeneratedKeys = true)
@Insert("insert into emp(username, name, gender, image , job, entrydate, dept_id, create_time, update_time)"+
"values(#(username), #(name), #(gender), #(image), #[iob), #(entrydate}, #(deptld),#(createTime}),#(updateTime)")
public void insert(Emp emp);
更新
- SQL语句(根据ID更新员工信息)
update emp set username = 'songdaxia', name = '宋大侠', gender = 1 , image = '1.jpg' , job=2, entrydate = '2012-01-01', dept_id = 2, update_time = '2022-10-0112:12:12' where id = 19;
- 接口方法
@Update("update emp set username=#(username),name=#(name), gender=#(gender), image=#[image), job=#iob),entrydate=#{entrydate), dept_id=#{deptld}, update_time=#(updateTime} where id=#(id}")
public void update(Emp emp);
根据ID查询
- SQL
select * from emp where id = 19;
- 接口方法
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);
数据封装
- 实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装
- 如果实体类属性名和数据库查询返回的字段名不一致,不能自动封装
- 起别名:在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样
@sefec&(seletid,usemame, password, name,gender,image,job,entrydate, dept id deptld, create_time createTime, update_timeupdateTime from emp where id = #{id} ")
public Emp getByld(Integer id);
- 手动结果映射:通过@Results及@Result进行手动结果映射。
@Select("select * from emp where id = #{id}")
@Results({
@Result(column = "dept_id" , property = "deptld"),
@Result(column = "create_time" , property = "createTime"),
@Result(column = "update_time", property = "updateTime"))
public Emp getByld(Integer id);
- 开启驼峰命名:如果字段名和属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射。
#开启驼峰命名自动映射,即从数据库字段名a_column映射到Java属性名aColumn。
mybatis.configuration.map-underscore-to-camel-case=true
查询之条件查询
- SQL语句
select * from emp where name like '%张%' and gender=1 and entrydate between '2010-01-01' and '2020-01-01 ' order by update_time desc;
- 接口方法
@Select( "select * from emp where name like '%${name}%' and gender =#{gender} and entrydate between #{begin} and #{end} order byupdate_time desc")
public List<Emp> list(String name, Short gender , LocalDate begin , LocalDate end);
可是上面这种性能低、不安全、存在SQL注入问题,下面是优化版本
@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 , LocalDate begin , LocalDate end);
XML映射
规范
- XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同名同包)。
- XML映射文件的namespace属性为Mapper接口全限定名一致
- XML映射文件中sql语句的id与Mapper接口的方法名一致,并保持返回类型一致。
使用Mybatis的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句
官方说明:https://mybatis.net.cn/getting-started.html
动态SQL
随着用户的输入或外部条件的变化而变化的SQL语句,我们称为动态SQL。
<if>
<if>
用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL
<where>
<where>
:where元素只会在子元素有内容的情况下才插入where子句。而且会自动取出子句的开头的AND或OR
<set>
<set>
:动态地在行首插入SET关键字,并会删掉额外的逗号。(用在update语句中)
<foreach>
- collection:集合名称
- item:集合遍历出来的元素/项
- separator:每一次遍历使用的分隔符
- open:遍历开始前拼接的片段
- close:遍历结束后拼接的片段
<sql>
、<include>
<sql>
:定义可重用的SQL片段<include>
:通过属性refid,指定包含的sql片段
事务管理
事务是一组操作的集合,他是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败。
操作:
- 开启事务(一组操作开始前,开启事务):
start transaction / begin ;
- 提交事务(这组操作全部成功后,提交事务):
commit ;
- 回滚事务(中间任何一个操作出现异常,回滚事务):
rollback ;
Spring事务管理
- 注解:@Transactional
- 位置:业务(service)层的方法上,类上,接口上
- 作用:将当前方法交给spring进行实物管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务
rollbackFor
- 默认情况下,只有出现RuntimeException才回滚异常。rollbackfor属性用于控制出现何种异常类型,回滚事务。
@Transactional(rollbackFor = Exception.class)
//这样就可以所有的异常都能回滚了
propagation
- 事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。
属性值:含义
- REQUIRED:【默认值】需要事务,有则加入,无则创建新事务
- REQUIRES_NEW:需要新事务,无论有无,总是创建新事务
- SUPPORTS:支持事务,有则加入,无则在无事务状态中运行
- NOT_SUPPORTED:不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
- MANDATORY:必须有事务,否则抛异常
- NEVER:必须没事务,否则抛异常
AOP
基础
- AOP:面向切面编程、面向方面编程,其实就是面向特定方法编程
- 实现:动态代理是面向切脉你编程最主流的实现。而SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,主要通过底层的动态代理机制,对特定的方法进行编程。
核心概念
- 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
- 通知:Advice,指那些重复的逻辑,也就是共性功能(最终体现为一个方法)
- 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用
- 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
通知类型
1、@Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
2、@Before:前置通知,此注解标注的通知方法在木匾方法前被执行
3、@After:后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
4、@AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
5、@AfterThrowing:异常后通知,此注解标注的通知方法发生异常后执行
注意事项:
@Around环绕通知需要自己调用ProceedingJoinPoint.proceed()来让原始方法执行,其他通知不需要考虑目标方法执行。
@Around环绕通知方法的返回值,必须指定为Object,来接 受原始方法的返回值。
- @PointCut
- 该注解的作用是将公共的切点表达式抽取出来,需要用到时引用该切点表达式即可。
通知顺序
当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行
1、不同切面类中,默认按照切面类的类名字母排序
- 目标方法前的通知方法:字母排名靠前的先执行
- 目标方法后的通知方法:字母排名靠前的后执行
有点像栈区先入后出
2、用@Order(数字)加在切面类上来控制顺序
- 目标方法前的通知方法:数字小的先执行
- 目标方法后的通知方法:数字小的后执行
切入点表达式
- 切入点表达式:描述切入点方法的一种表达方式
- 作用:主要用来决定项目中的哪些方法需要加入通知
- 常见形式:
- 1、execution(…):根据方法的签名来匹配
- 2、@annotation(…):根据注解匹配
execution
execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:
execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)
- 其中带?的表示可以省略的部分
- 访问修饰符:可省略(比如:public、protected)
- 包名.类名:可省略,但是不建议省略,省略掉的话匹配范围过大,影响匹配效率
- throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)
- 可以使用通配符描述切入点
*
:单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的那一部分execution(* com.*.service.*.update*(*))
. .
:多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数execution(* com.itheima..DeptService.*(..))
根据业务需求,可以使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式。
书写建议:
- 所有业务方法名在命名时尽量规范,方便切入点表达式快速匹配。如:查询类方法都是find开头,更新类方法都是update开头。
- 描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性。
- 在满足业务需求的前提下,精良缩小切入点的匹配范围。如:包名匹配尽量不使用…,使用*匹配单个包。
@annotation
@annotation切入点表达式,用于匹配标识有特定注解的方法。
@annotation(com.itheima.anno.Log)
@Before("@annotation(com.itheima.anno.Log)")
public void before(){
log.info("before ...");
}
连接点
- 在Spring中用
JoinPoint
抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。 -
- 对于@Around通知,获取连接点信息只能使用
ProceedingJoinPoint
- 对于@Around通知,获取连接点信息只能使用
-
- 对于其他四种通知,获取连接点信息只能使用
JoinPoint
,它是ProceedingJoinPoint
的父类型
- 对于其他四种通知,获取连接点信息只能使用
Springboot原理
配置优先级
注意事项:
虽然springboot支支持多种格式配置文件,但是在项目开发时,推荐使用一种格式的配置(yml是主流)
Springbot除了支持配置文件属性配置,还支持Java系统属性和命令行参数的方式进行属性配置。
- Java系统属性
-
-Dserver.port=9000
- 命令行函数
-
- - server.port=10010
如果项目已经打包上线了,该如何设置
注意事项:
Springboot项目进行打包时,需要引入插件spring-boot-maven-plugin
(基于官网骨架创建项目,会自动添加该插件)
Bean管理
获取bean
默认情况下,Spring项目启动时,会把bean都创建好放在IOC容器中,如果想要主动获取这些bean,可以通过如下方式:
- 根据name获取bean:
Object getBean(String name)
- 根据类型获取bean:
<T> T getBean(Class<T> requiredType)
- 根据name获取bean(带类型转换):
<T> T getBean(String name, Class<T> requiredType)
注意事项:
上述所说的【spring项目启动时,会把其他的bean都创建好】还会收到作用域及延迟初始化影响,这里主要针对于默认的单例非延迟加载地bean而言。
bean作用域
spring支持五种作用域,后三种在web环境才生效:
第三方bean
@Bean
- 如果要管理的对象来自于第三方(不是自定义的),是无法用@Commpoent及衍生注解声明bean的,就需要用到@Bean注解。
@SpringBootApplication
public class SpringbootwebConfig2Application {
@Beanl/将方法返回值交给IOc容器管理,成为IOc容器的bean对象
public SAXReader saxReader(){
return new SAXReader();
}
}
启动类↑,不建议
@configuration
public class commonconfig {
@Bean
public SAXReader saxReader(){
return new SAXReader();
}
}
注意事项:
通过@Bean注解的name/value属性指定bean名称,如果未指定,默认是方法名
如果第三方bean需要依赖其他bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配
@Component及衍生注解与@Bean注解使用场景?
- 项目中自定义的,使用@Component及其衍生注解
- 项目中引入第三方的,使用@Bean注解
自动配置
- SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。
自动配置原理
依赖和bean引入了但并不能直接就能用上了,当让IOC组件扫描到。
- 方案一:@ComponentScan组件扫描
@componentScan(i"com.example" , "com.itheima"})
@SpringBootApplication
public class Springbootwebconfig2Application {}
使用繁琐,性能低,↑
- 方案二:@Import导入。使用@Import导入的类会被Spring加载到IOC容器中,导入形式主要有以下几种:
-
- 导入 普通类
-
- 导入 配置类
-
- 导入 ImportSelector 接口实现类
-
- @EnableXxxxx注解,封装@Import注解
- 该注解标识再SpringBoot工程引导类上,是SpringBoot中最最重要的注解。该注解由三个部分组成:
-
@SpringBootConfiguration
:该注解与@Configuration注解作用相同,用来声明当前也是一个配置类。
-
@ComponentScan
:组件扫描,默认扫描当前引导类所在包及其子包。
-
@EnableAutoConfiguration
:SpringBoot实现自动化配置的核心注解。
@Conditional
- 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring IOC容器中。
- 位置:方法、类
- @Conditional本身是一个父注解,派生出大量的自注解:
-
- @ConditionalOnClass:判断环境中是否有对应字节码文件,才注册bean到IOC容器。
-
- @ConditionalOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器。
-
- @ConditionalOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器。
web后端开发小总结