无锡企业网站seo,wordpress 置顶文章加图标,建团购网站,企业网站建设哪家好文章目录 WEB开发一、HTML1.html介绍 二、CSS1.CSS介绍2.CSS导入方式3.CSS选择器4.CSS属性 三、JavaScript1.介绍2.浏览器3.js的三种输出方式4.js定义变量5.js数据类型6.js运算符7.全局函数8.函数定义9.js数组对象10.js正则对象11.字符串对象12.自定义对象13.BOM浏览器对象模型… 文章目录 WEB开发一、HTML1.html介绍 二、CSS1.CSS介绍2.CSS导入方式3.CSS选择器4.CSS属性 三、JavaScript1.介绍2.浏览器3.js的三种输出方式4.js定义变量5.js数据类型6.js运算符7.全局函数8.函数定义9.js数组对象10.js正则对象11.字符串对象12.自定义对象13.BOM浏览器对象模型14.DOM对象 四、AJAX1.es62.Asynchronous JavaScript and XML3.交互模型4.axios5.JSON(1)JSON语法 五、VUE1.基础入门2.vue常用指令v-htmlv-bindv-ifv-showv-forv-onv-model 3.vue声明周期 六、ElementVue脚手架1.Element UI(1)lement介绍(2)快速入门(3)基础布局(4)容器布局(5)表单组件(6)表格组件(7)导航栏组件小结 2.Node.js3.nodejs的包管理器npm(1)使用npm进行初始化(2)使用npm在本地即当前模块下安装软件(3)全局安装(4)淘宝NPM镜像【建议使用】 4.webpack【1】什么是webpack【2】Webpack安装【3】快速入门(1)作用(2)webpack打包应用(3)基于npm方式打包(4)webpack-dev-server开发服务器(5)小结 5.vue-cli脚手架掌握(1)常见命令(2)vue脚手架入门 6.vue-cli脚手架练习(1)模拟网易云音乐(2)将Element-UI组件库添加到vue脚手架中 7.vue脚手架综合案例(1)环境搭建 七、web1.内容介绍2.软件架构模式3.B/S和C/S通信模式特点4.web资源5.URL请求路径6.服务器 八.tomcat1.目录结构2.启动和关闭以及访问tomcat3.解决启动tomcat失败的问题4.使用tomcat发布web项目5.使用在idea中创建的web项目发布资源 九、Servlet1.Servlet介绍2.Servlet作用3.Servlet快速入门4.Servlet的执行原理5.Servlet生命周期6.服务器启动立刻加载Servlet对象总结 7.Servlet实现方式1实现Servlet方式二_自定义类继承GenericServlet2实现Servlet方式三_自定义类继承HttpServlet3实现servlet方式三_继承HttpServlet的执行流程4实现servlet的三种方式总结 8.编写servlet常见的问题1遇到500错误2遇到404错误3遇到405错误 9.Servlet映射路径理解10.Servlet映射路径配置规范1完全路径匹配2目录匹配/user/*3后缀名匹配*.do *.action4缺省路径 / 11.绝对路径12.相对路径13.Servlet3.0注解开发14.修改idea创建注解的servlet模板15.关于servlet3.0注解开发的疑问配置路径省略了属性urlPatterns 十.HTTP协议1.HTTP协议介绍2.浏览器抓包观察请求报文协议 十一.Request Response1.Request和Response的概述2.Request对象(1)Request继承体系(2)Request获取请求数据(3)解决post请求乱码问题(4)Request请求转发(5)request的生命周期 3.HTTP响应详解1使用抓包查看响应报文协议内容2HTTP响应报文协议介绍 4.Response对象1Response设置响应数据功能介绍(2)Responses请求重定向3路径问题4Response响应字符数据5Response响应字节数据 十二.Cookie1.基本使用1概念2Cookie工作流程3Cookie的基本使用3.1发送Cookie3.2获取Cookie 2.Cookie的原理分析3.Cookie的使用细节1Cookie的存活时间2关于cookie中存储特殊字符问题内容小结 十三.Session1.基本使用2.Session的原理分析3.Session的使用细节【1】浏览器关闭后session持久化方案【2】Session钝化和活化【3】Session销毁 Cookie和Session小结 十四.Filter1.概述2.入门案例3.关于入门案例的补充4.注解开发5.在idea中配置filter的模板6.Filter的生命周期 掌握7.拦截路径(重点)8.过滤器链 掌握9.Filter案例1解决全站乱码问题2过滤器案例--登录权限校验 十五.ServletContext(1)ServletContext对象介绍 十六.Listener1.说明2.监听器的接口分类3.快速入门简单案例① xml版本② 注解版本 4.模拟spring框架 十七.git1.git概述2.git作用3.git下载与安装4.git本地操作5.git本地操作-add与commit6.git本地操作-差异比较7.git本地操作-版本回退8.git本地操作-修改撤销9.分支操作1分支的创建与切换2分支合并与删除 10.git远程仓库介绍与码云仓库的注册创建常用的远程仓库 11.Git远程仓库操作1关联2拉取3推送4克隆 12.IDEA中使用Git13.IDEA中使用Git-基本操作14.IDEA中使用Git远程仓库 WEB开发
一、HTML
1.html介绍
html超文本标记语言 超文本超越了文本的限制比普通文本更强大。除了文字信息还可以定义图片、音频、视频等内容。标记语言由标签构成的语言 网站和网页的区别 网站网页后端java数据库网页显示给用户 HTML运行在浏览器上HTML标签由浏览器来解析不需要编译。HTML标签都是预定义好的。例如使用 展示图片在任何地方都可以创建html文件文件后缀名是.html或者.htmW3C标准 结构HTML表现CSS行为JavaScript HTML结构标签
标签描述HTML定义HTML文档head定义关于文档的信息title定义文档的标题body定义文档的主体
HTML基础标签
标签描述h1 - h6定义标题h1最大h6最小font定义文本的字体(face)、字体尺寸(size)、字体颜色(color)b定义粗体文本i定义斜体文本u定义文本下划线center定义文本居中p定义段落br定义换行hr定义水平线img定义图片audio定义音频video定义视频ol定义有序列表ul定义无序列表li定义列表项table定义表格border规定表格边框的宽度width规定表格的宽度cellspacing规定单元格之间的空白tr定义行 align:定义表格的内容对齐方式td定义单元格rowspan规定单元格可横跨的行数colspan规定单元格可横跨的列数div定义HTML文档中的一个区域部分经常与CSS一起使用用来布局网页span用于组合行内元素form定义表单input定义表单项通过type属性控制输入形式label为表单项定义标注select定义下拉列表option定义下拉列表的列表项textarea定义文本域inputtypetext、password、radio、checkbox、file、hidden、submit、reset、button
form表单
常见属性
action表示将收集的数据提交到具体后台服务器的地址
method提交数据到后台的方式请求方式
gethttp://www.jd.com?usernamezhangpassword123(默认)
不安全有大小限制只能传输字符数据
posthttp://www.jd.com
安全有大小限制可以传输任意数据
二、CSS
1.CSS介绍
CSSCascading Style Sheet层叠样式表是一门语言用于控制网页表现
2.CSS导入方式
内联样式在标签内部使用style属性属性值是css属性键值对
div stylecolor:redHello CSS/div内部样式定义
style typetext/cssdiv{color:red;}
/style外部样式定义link标签引入外部的css文件
link relstylesheet hrefdemo.css3.CSS选择器
元素选择器
!--元素名称{color:red;}--
div{color:red;}id选择器
!--#id属性值{color:red;}--
#name{color:red;}
div idnamehello css/div类选择器
!--.class属性值{color:red;}--.cls{color:red;}
div classclshelo css/div4.CSS属性
https://www.w3school.com.cn/cssref/index.asp三、JavaScript
1.介绍
JavaScript是一门跨平台、面向对象的脚本语言来控制网页行为的它能使网页可交互JavaScript和Java是完全不同的语言不论是概念还是设计。但是基础语法类似JavaScript插入HTML页面后可由所有的现代化浏览器执行。JavaScript语言不需要编译直接由各大浏览器解析运行。学习JavaScript语言不需要单独安装软件只需要浏览器即可。
2.浏览器
浏览器分成两部分渲染引擎和JS引擎
渲染引擎用来解析HTML和CSS俗称内核例如chrome浏览器的blinkJS引擎也成为JS解释器。用来读取网页中的JS代码对其处理后运行例如chrome浏览器的V8
3.js的三种输出方式
使用 window.alert() 写入警告框使用 document.write() 写入HTML输出使用 console.log 写入浏览器控制台
4.js定义变量
定义变量 let 变量名 值定义常量 const 常量名 值不能改变
var i 10
let xhaha;
let y 3.14;
//定义常量不能改变
const PI3.145.js数据类型
number数字整数、小数、NaNstring字符、字符串、单双引皆可boolean布尔true、falsenull对象为空undefined当声明的变量未初始化时该变量的默认值是undefined引用数据类型date、Object
6.js运算符
一元运算符–算术运算符-*/%赋值运算符-关系运算符,,,,!, ,
非严格比较具有强制类型转换功能如果两侧的数据类型不一致转换一样的类型然后比较数值是否相等
严格比较如果运算符两侧类型不一致返回false如果类型一致在比较数值是否相等
逻辑运算符、||、三元运算符条件表达式true_value : false_value
在js中有六种假false0空字 符’、“”NaN、null、undefined
7.全局函数
其他类型转为数字 string将字符串字面值转为数字。如果字面值不是数字则转为NaN一般使用parseInt()方法进行转换booleantrue转为1false转为0一般使用Number()方法进行转换 其他类型转为boolean使用Boolean(value)函数 number0和NaN转为false其他的数字转为truestring空字符串转为false其他字符串转为truenull转为falseundefined转为false
8.函数定义
格式一
function add(a,b){console.log(a---b)//返回return ab
}//调用
let sum add(10,20)
console.log(sum)格式二
let add function(a,b){return a b;
}//调用
let result add(1,2);注意事项 匿名函数还可以作为另一个函数的参数传递在js中没有函数重载概念如果存在函数名一样的函数后出现的函数就会覆盖之前的函数名在js中调用无参函数可以传递实参数据没有丢失会放到js的一个内置数组对象中 arguments调用有参函数可以不传递值
9.js数组对象
数组定义方式一 采用方式一定义数值时如果只给一个number类型的值那么此时数值表示数组长度数组中的数据都是empty采用方式一定义数值时如果只给一个number类型的值那么此时数值表示数组长度要求不能给小数数组长度不能是小数采用方式一定义数值时如果只给一个非number类型的值那么此时数值表示数组的元素js中的数组长度是可变的 数组定义方式二 let arr [10] 表示数组元素为10长度为1
//定义
let 变量名 new Array(元素列表); //方式一
let arr new Array(1,2,3);let 变量名 [元素列表]; //方式二
let arr [1,2,3];//访问arr[索引] 值;arr[0] 1 数组对象属性和函数 length返回数组中元素的个数即数组长度push()向数组中末尾添加一个或多个元素返回新的长度splice(index,n)从数组中删除元素index表示从哪个索引删除n表示删除数据个数
10.js正则对象
概念正则表达式定义了字符串组成的规则定义
//1.直接量注意不要加引号
// var reg /^正则表达式符号$///2.创建RegExp对象
var reg new RegExp(^正则表达式符号$);方法test(str)判断指定字符串是否符合规则返回true或false语法
符合含义^表示开始$表示结束[]代表某个范围内的单个字符比如[0-9]单个数字字符.代表任意单个字符除了换行和行结束符\w代表单词字符字母、数字、下划线(_),相当于[A-Za-z0-9]\d代表数字字符相当于[0-9]至少一个*零个或多个?零个或一个{x}x个{m,}至少m个{m,n}至少m个至多n个
11.字符串对象
定义
//方式一: let 变量名 new String(s);
let str new String(hello);//方式二let 变量名 s;
let str hello;
let str hello;属性 length字符串的长度 方法 charAt() :返回在指定位置的字符IndexOf() :检索字符串查找字符串在指定字符串中存在的索引如果不存在返回-1
12.自定义对象
let 对象名称 {属性名称1属性值1属性名称2属性值2...函数名称function(形参列表){} ...
};//例
let person {name:zhangsan,age:23,eat:function(){alert(干饭);}
};let person{//属性名属性值name:liuyan,address:hunan,age:18,eat:function(){//TODO:如果在自定义对象中使用当前自定义对象中的其他属性或者函数格式//this.属性名或this.函数名(实参);//this表示当前对象即personconsole.log(ganfanrenganfanhunthis.address); //柳岩//this表示当前对象即personconsole.log(person.age); //18//调用函数 对象名.函数名(实参);person.eat();}
}13.BOM浏览器对象模型
组成windows浏览器窗口对象Navigator浏览器对象Screen屏幕对象History历史记录对象Location地址栏对象
windows浏览器窗口对象
直接使用window调用window对象中的属性和函数其中window.可以省略
window.alert(“abc”)
属性和方法解释history对History对象的只读引用Navigator对Navigator对象的只读引用Screen对Screen对象的只读引用location用于窗口或框架的Location对象alert()显示带有一段消息和一个确认按钮的警告框confirm()显示带有一段消息以及确认按钮和取消按钮的对话框setInterval()按照指定的周期(以毫秒计)来调用函数或计算表达式setTimeout()在指定的毫秒数后调用函数或计算表达式只会执行一次
14.DOM对象 1Document Object Model文档对象模型
2将标记语言的各个组成部分封装为对象
img标签 Image对象Document整个文档对象Element元素对象Attribute属性对象Text文本对象所有标签的父对象是Element
3JavaScript通过DOM就能够对HTML进行操作
改变HTML元素内容改变HTML元素的样式CSS对HTML DOM事件作出反应添加和删除HTML元素
4Element元素对象
获取使用Document对象的方法来获取 getElementById根据id属性值获取返回一个Element对象getElementsByTagName根据标签名获取返回Element对象数组getElementsByName根据name属性值获取返回Element对象数组getElementsByClassName根据class属性值获取返回Element对象数组
5事件绑定
方式一通过HTML标签中的事件属性进行绑定
input typebutton onclickon()function on(){alert(我被点了);
}方式二通过DOM元素属性绑定
input typebuton id btn//只有是标签对象才可以绑定事件如果是数组不能直接绑定需要遍历数组取出//每个标签对象在绑定事件document.getElementId(btn).onclick function (){alert(我被点了);
}6常见事件
事件名说明onclick鼠标单击事件onblur元素失去焦点onfocus元素获得焦点onload某个页面或图形被完成加载onsubmit当表单提交时触发该事件onkeydown某个键盘的键被按下onmouseover鼠标被移到某元素之上onmouseout鼠标从某元素移开
四、AJAX
1.es6
es6.ruanyifeng.com
变量声明 let常量声明 const模板字符串
let usernameRose;
//es5
console.log(姓名是username);//es6,使用反引号可以直接打印变量的值表达式类似于java的el表达式
console.log(姓名是${username});函数的参数默认值
在js中如果定义的函数有参数调用的时候可以不传递实参那么形参变量名就是undefined为了解决这个问题es6后引入函数参数默认值。如果调用函数时不传递实参那么使用默认值如果传递实参那么使用实参。
//es6前
function show(username){console.log(username);
}
show(); //undefined//es6
function show(usernameJack){ //默认值Jackconsole.log(username);
}
show();
箭头函数
//es5
let add function(a,b){return ab;
}//es6
let add2(a,b) {retturn ab;
}
//如果函数只有一句话可以省略大括号和return
var add3(a,b) ab;
//如果只有一个参数 省略小括号
var add4 a a10; 2.Asynchronous JavaScript and XML
1异步的JavaScript和XML
2ajax就是一项通过js技术发送异步请求的技术。异步请求局部更新不是整个网页更新可以完成前端和后台服务器的数据交互。
说明
异步就是不同步。例如我们向后台发送请求同步的方式是后台必须返回响应数据才可以在浏览器上进行下一步操作而异步方式可以在不需要等待后台服务器响应数据之间可以进行其他操作。
Ajax不是新的编程语言而是一种使用现有标准的新方法Ajax是与服务器交换数据并更新部分网页的技术在不重新加载整个页面的情况下。
3同步请求存在的问题
阻塞请求发出后必须得等到响应结束后才能操作页面信息。全部更新整个页面更新。
4异步请求好处
非阻塞请求发出后不用等到响应结束才能操作页面信息。随时可以操作。局部更新页面的局部位置更新
3.交互模型
传统交互模型
浏览器客户端向服务器直接发送请求数据然后后台服务器接收到请求处理请求数据期间浏览器客户端只能等待服务器处理数据并响应数据最后服务器将响应数据响应给浏览器客户端浏览器接收到响应之后才可以继续下一步操作。
AJAX的交互模型
浏览器内部多了一个ajax引擎浏览器客户端向服务器发送请求的数据都是先由浏览器将请求数据交给ajax引擎注意ajax引擎位于浏览器内部是由js编写的一个软件。然后接下来都是由ajax引擎和服务器进行交互此时用户可以在浏览器上进行其他操作如果再次向服务器发送请求那么依然是交给ajax引擎处理并且服务器响应的数据也是交给ajax引擎处理由ajax引擎来分配浏览器的操作。
注意ajax引擎内部具有一个核心对象XMLHttpResquest。都是由该对象进行异步请求交互数据的。new XMLHttpRequest() 启用ajax引擎。
4.axios
说明网站https://www.kancloud.cn/yunye/axios/234845
原生ajax请求的代码编写太过繁琐我们可以使用axios这个库来简化操作使用步骤
1.引入axios核心js文件
!--TODO:引入axios核心js文件
--
script srcjs/axios-0.18.0.js/script2.使用axios对象调用方法来发起异步请求。
3.使用axios对象调用方法来处理响应的数据。
axios常用方法
方法名作用get请求的资源路径与请求的参数发起GET方式请求post请求的资源路径请求的参数发起POST方式请求thenresponse请求成功后的回调函数通过response获取响应的数据catcherror请求失败后的回调函数通过error获取错误信息
**回调函数回过头来调用的函数回调函数都是我们负责书写不负责调用都是底层帮助我们调用。**例 setInterval(function(){},1000);
//备注: then函数的参数response是一个json对象,
//我们重点只需要了解response.data即可
{// data 由服务器提供的响应 (重要!) response.datadata: {},// status 来自服务器响应的 HTTP 状态码 response.statusstatus: 200,// statusText 来自服务器响应的 HTTP 状态信息statusText: OK,// headers 服务器响应的头headers: {},// config 是为请求提供的配置信息config: {}
}
代码实现 get请求 axios使用说明 /** # axios的api介绍* 1. get(参数) 建立和服务器的连接* get参数 : 是请求地址请求参数 ---url?keyvaluekeyvalue...* 2. then(fn) 处理服务器响应* fn(response) : 响应成功的回调函数* response.data : 响应体数据** 3. catch(fn)* fn(error) : 响应失败的的回调函数* error : 错误信息** 4. finally(fn)* fn : 响应结束的回调函数(无论响应成功与否,都会执行)* */
整体代码,链式编程
// /AjaxServlet 表示后台服务器地址 url
// namezsage18 表示向后台提交的数据get请求数据位于url后面携带数据格式url?keyvaluekeyvalue
axios.get(/AjaxServlet?namezsage18).then(function (response) {// 回调函数的函数体,处理后台服务器的响应的代码所有的数据都放到response对象中了注意response只是一个对象标识符名字随便定义,我们只负责编写匿名函数体代码}).catch(function (error) {// 回调函数的函数体如果后台服务器出现异常就在这里处理所有的错误信息放到error对象中};).finally(function () {// 回调函数的函数体必须执行的代码};);使用es6的箭头函数简(){}
axios.get(/AjaxServlet?namezsage18).then(response{// 回调函数的函数体,处理后台服务器的响应的代码所有的数据都放到response对象中了注意response只是一个对象标识符名字随便定义,我们只负责编写匿名函数体代码}).catch(error{// 回调函数的函数体如果后台服务器出现异常就在这里处理所有的错误信息放到error对象中};).finally(() {// 回调函数的函数体必须执行的代码};);
代码实现
步骤
1.导入axios的js库到当前项目webapp文件夹下
2.创建html页面
3.在html页面中导入axios的js库
4.在html页面向后台发送axios的ajax异步请求
5.创建Servlet接收请求数据处理业务逻辑和响应数据
6.在html页面中处理服务器的响应数据
!DOCTYPE html
html langen
headmeta charsetUTF-8title使用axios发送异步请求/title
/head
body
!-- 不能在文本中书写js代码--
script typetext/javascript srcjs/axios-0.18.0.js/script
script typetext/javascript//1.使用axios对象调用函数向后台服务器发送ajax异步请求/*整体 axios.get().then().catch().finally();1get()函数表示两后台服务器发送get请求格式get(url?keyvaluekeyvalue...);axios.get(/axiosDemo01Servlet?username锁哥password1234)2)then() 处理后台服务器响应的格式then(function(接收响应数据的对象名){处理响应的代码});then(function (resp){console.log(resp);})后台响应数据resp{data: axios实现ajax异步get请求,username锁哥,status: 200,statusText: ,headers: {…},config: {…},}resp.data就可以获取 数据 axios实现ajax异步get请求,username锁哥3)catch() :处理异常catch(function (error) {console.log(error);})let person {username:锁哥,age:18}小结1.get函数建立和服务器的连接在参数中书写连接服务器的url和请求参数2.then函数书写处理响应数据的在该函数的参数位置书写回调函数3.catch函数书写处理响应错误信息数据的在该函数的参数位置书写回调函数4.finally函数无论响应成功还是失败都要执行的代码在该函数的参数位置书写回调函数*/axios.get(http://localhost:8080/axiosDemo01Servlet?username锁哥password1234).then(function (response) {//处理响应数据的回调函数体代码response表示接受服务器响应数据的对象该对象中具有重要属性是dataconsole.log(response);console.log(response.data);}).catch(function (error) {//书写处理响应错误信息数据的在该函数的参数位置书写回调函数console.log(error);}).finally(function () {//无论响应成功还是失败都要执行的代码在该函数的参数位置书写回调函数console.log(我是必须执行的...);});
/script
/body
/htmlaxios发送异步的请求步骤
【1】导入库
script typetext/javascript srcjs/axios-0.18.0.js/script【2】书写异步请求代码
axios.get(后台服务器地址?参数名参数值参数名参数值).then(resp{//后台响应成功执行这里接收后台的数据resp.data}).catch(error{//后台有异常}).finally((){//必须执行的});axios.post(后台服务器地址,参数名参数值参数名参数值).then().catch().finally();5.JSON
JavaScript对象文本表示形式JavaScript Object Notation : js对象简写
json是js对象json是目前 前后端交互的主要格式之一
(1)JSON语法
//json的语法主要有两种:1. 对象 { }2. 数组 [ ]1. 对象类型{name:value,name:value,....}2. 数组类型[{name:value,name:value}, {name:value,name:value},{name:value,name:value}]3. 复杂对象{name:value,wives:[{name:value},{},{}],son:{name:value}}
//注意: 1. 其中name必须是string类型json在js中,name的双引号可以省略,建议加双引号2. value必须是以下数据类型之一字符串数字对象JSON 对象数组布尔Null3. JSON 中的字符串必须用双引号包围。(单引号不行!主要是涉及到后期在后端java代码中操作) 五、VUE
1.基础入门
导入vue.js
script srcjs/vue.js/script视图
body!--TODO: vue第一部分视图-- div idapp!--在vue中有个插值表达式简称插值可以获取数据模型中的数据并显示到页面中{{数据模型中的冒号左边的标识}}--{{msg}}/div
/bodyjs代码存放数据
script//TODO:vue第二部分脚本js代码用来存放数据的new Vue({//1.作用的视图//TODO:el是element元素的简写//通过视图即html标签的id属性值进行关联这里的app是上述视图中div//标签的id属性值el:#app,//2.存放的数据/*数据模型1)data:{name:value,name:value......}*/data:{msg:vue基础入门}methods:{show:function(){}}});
/script2.vue常用指令
(1)vue指令介绍
在vue中指令是作用在视图中的即html标签可以在视图中增加一些指令来设置html的标签的某些属性和文本。
指令都是以带有v-前缀的特殊属性。
(2)使用vue指令
使用指令时通常编写在标签的属性上值可以使用JS表达式。
(3)常见的vue指令
指令作用v-html把文本解析为HTML代码v-bind为HTML标签绑定属性值v-if条件性的渲染某元素判定为true时渲染否则不渲染v-elsev-else-ifv-show根据条件展示元素区别在于切换的是display属性的值v-for列表渲染遍历容器的元素或者对象的属性v-on为HTML标签绑定事件v-model在表单元素上创建双向数据绑定
v-html
需求使用文本插值v-html和插值表达式**{{}}**获取vue中data数据
标签名 v-htmlvue中data的key/标签名
说明文本插值v-html通过data的key获取value显示标签的文本中!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title文本插值/title
/head
body
!--视图--
div iddivdiv{{msg}}/div!--使用文本插值指令v-html--div v-htmlmsg/divdiv v-textmsg/div
/div
/body
script srcjs/vue.js/script
script//脚本new Vue({el:#div,data:{msg:h1Hello Vue/h1}});
/script
/htmlv-bind
需求给html标签绑定属性
完整写法
标签名 v-bind:属性名data中key/标签名
简写常用 *****
标签名 :属性名data中key/标签名!DOCTYPE html
html langen xmlns:v-bindhttp://www.w3.org/1999/xhtml xmlns:v-onhttp://www.w3.org/1999/xhtml
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title绑定属性/titlestyle.my{border: 1px solid red;}/style
/headbodydiv iddiv!--插件表达式不能写在属性中--a href{{url}}百度一下/abr!--v-bind为 HTML 标签绑定属性值--a v-bind:hrefurl百度一下/abr!--v-bind 可以省略不写--a :hrefurl百度一下/abr!--也可以绑定其他属性给当前div标签绑定一个class属性属性值通过data中的keycls获取到my这里相当于div classmy我是div/div--div :classcls我是div/div/div
/body
script srcjs/vue.js/script
scriptnew Vue({el:#div,data:{url:http://www.baidu.com,cls:my}});
/script
/htmlv-if
需求判断vue中data的某个变量的值对3取余余数为0显示div1余数为1显示div2否则显示div3
标签名 v-if条件表达式满足条件显示的内容/标签名
标签名 v-else-if条件表达式满足条件显示的内容/标签名
.......
标签名 v-else上述条件都不满足执行的内容/标签名!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title条件渲染/title
/head
bodydiv iddiv!-- 判断num的值对3取余余数为0显示div1余数为1显示div2余数为2显示div3 --div v-ifnum % 3 0div1/divdiv v-else-ifnum % 3 1div2/div!--注意如果不满足上述条件则执行v-else这里不用书写判断条件--div v-elsediv3/div/div
/body
script srcjs/vue.js/script
scriptnew Vue({el:#div,data:{num:2,flag:true}});
/script
/htmlv-show
需求获取Vue中data的布尔类型数据并显示
标签名 v-showdata中的key文本/标签名
说明
1.如果data中的key的值是true则显示标签文本内容如果是false则不显示标签文本内容!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title条件渲染/title
/head
body
div iddiv!--v-show指令--div v-showflagdiv4/div!--v-if v-show 他们俩虽然都是控制元素是否显示但是底层的原理不一样v-if 如果条件为false页面中根本没有这个元素v-show如果条件为false页面中有这个元素只不过它的display属性值为none--
/div
/body
script srcjs/vue.js/script
scriptnew Vue({el: #div,data: {num: 2,flag: false}});
/script
/htmlv-show和v-if区别
1.v-if如果条件不满足那么在页面中没有任何标签内容直接删除
2.v-show:如果条件不满足是通过设置css样式的属性display设置属性值为none来隐藏标签标签还在页面中只是我们看不见
v-for
遍历数组或者对象
增强for循环掌握
for(int x : arr){}
标签名 v-forx in 数组或者对象名或者集合名{{x}} 使用插值表达式获取元素
/标签名普通for循环了解
标签名 v-for(x,index) in 数组或者对象名元素:{{x}},索引:{{index}}
/标签名
说明x和index属于标识符li v-for(元素,索引) in 容器名或者对象名{{元素}}
/li
如果遍历的是对象那么会将对象中的key作为索引返回。!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title列表渲染/title
/head
bodydiv iddivul!--类似于增强for循环1. element是遍历得到的每一个元素(变量名可以自定义)有一个作用域,它的作用于在当前的这个循环中2. names 是被遍历的数组或对象3.我们在标签文本中使用插值表达式根据遍历数组的每个元素的变量element获取对应数据--!--需求遍历names数组--li v-forelement in names{{element}}/li!--需求遍历对象student--!--1.stu 表示对象中的每组数据 :张三 232.student表示遍历的对象名--li v-forstu in student{{stu}}/li!--类似于普通for循环(了解)--!--需求遍历names数组--!--1.element表示数组的元素2.index表示数组中的索引--li v-for(element,index) in names元素:{{element}},索引:{{index}}/li!--需求遍历对象student--!--结果元素:张三,索引:name元素:23,索引:age注意在vue中使用v-for遍历对象时使用普通for循环遍历索引是对象中的key或者变量--li v-for(element,index) in student元素:{{element}},索引:{{index}}/li/ul/div
/body
script srcjs/vue.js/script
scriptnew Vue({el:#div,data:{//数组names:[张三,李四,王五],//对象student:{name:张三,age:23}}});
/script
/htmlv-on
给视图绑定事件
标签名 v-on:事件名调用的是vue中的js函数/标签名
简写掌握
标签名 事件名调用的是vue中的js函数/标签名
说明
1.在vue中绑定的事件名都是将原生js的事件名去掉on:click blur...!DOCTYPE html
html langen xmlns:v-onhttp://www.w3.org/1999/xhtml
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title事件绑定/title
/headbodydiv iddivdiv{{name}}/div!--v-on为 HTML 标签绑定事件--button onclickfn();以前方式_单击_改变div的内容/button!--1.v-on:clickchange(); 给当前标签即视图绑定一个单击事件在事件的属性值中直接调用vue中的函数change()--button v-on:clickchange();单击_改变div的内容/buttonbutton v-on:dblclickchange();双击_改变div的内容/buttonbutton clickchange();简写_改变div的内容/button/div
/body
script srcjs/vue.js/script
scriptlet ve new Vue({el:#div,data:{name:黑马程序员},methods:{change(){this.name 传智播客;}}});//定义原生js函数function fn() {//调用vue中的函数changeve.change();}
/script
/htmlv-model
可以实现双向数据绑定
vue中的data数据更改然后视图中的显示内容也会随着改变视图中的内容改变vue中的data数据也会随着改变
单向数据绑定
vue中的data数据更改然后视图中的显示内容也会随着改变
!DOCTYPE html
html langen xmlns:v-bindhttp://www.w3.org/1999/xhtml
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title表单绑定/title
/head
bodydiv iddivform autocompleteoff!--单向绑定--!--:valueusername 表示给当前input标签绑定value属性username是vue中data的key--姓名_单向绑定input typetext nameusername :valueusernamebr!--双向绑定1.v-modelusername:表示给当前input标签进行双向数据绑定显示到输入框中直接根据key即username获取value--姓名_双向绑定input typetext nameusername v-modelusernamebr年龄input typenumber nameage v-modelage性别:input typetext namegender v-modelgender/form{{username}}hr/div
/body
script srcjs/vue.js/script
scriptnew Vue({el:#div,data:{username:张三,age:23,gender:男}});
/script
/htmlv-model表单绑定实现双向数据绑定的原理
MVVM模型(Model,View,ViewModel)是MVC模式的改进版 在前端页面中JS对象表示Model页面表示View两者做到了最大限度的分离。 将Model和View关联起来的就是ViewModel它是桥梁。 ViewModel负责把Model的数据同步到View显示出来还负责把View修改的数据同步回Model。 3.vue声明周期 !DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title生命周期/titlescript srcjs/vue.js/script
/head
body
div idapp{{message}}
/div
/body
scriptlet vm new Vue({el: #app,data: {message: Vue的生命周期},//vue对象创建前所有内容都是未定义类型beforeCreate: function () {console.group(------beforeCreate创建前状态------);console.log(%c%s, color:red, el : this.$el); //undefinedconsole.log(%c%s, color:red, data : this.$data); //undefinedconsole.log(%c%s, color:red, message: this.message);//undefined},//表示vue对象创建完毕//我们可以在该生命周期中先准备好数据然后视图此时还没准备好created: function () {console.group(------created创建完毕状态------);//el的值是undefined说明视图还没有准备好console.log(%c%s, color:red, el : this.$el); //undefined//说明在该生命周期中数据已经准备好了console.log(%c%s, color:red, data : this.$data); //已被初始化console.log(%c%s, color:red, message: this.message); //已被初始化},//就是vue挂载视图前还没有将数据挂载到视图中beforeMount: function () {console.group(------beforeMount挂载前状态------);console.log(%c%s, color:red, el : (this.$el)); //已被初始化console.log(this.$el);console.log(%c%s, color:red, data : this.$data); //已被初始化console.log(%c%s, color:red, message: this.message); //已被初始化},//就是vue挂载视图后vue中的data数据已经挂载到视图中了mounted: function () {console.group(------mounted 挂载结束状态------);console.log(%c%s, color:red, el : this.$el); //已被初始化console.log(this.$el);console.log(%c%s, color:red, data : this.$data); //已被初始化console.log(%c%s, color:red, message: this.message); //已被初始化},//表示更新前 必须有数据的更新才会执行该生命周期beforeUpdate: function () {console.group(beforeUpdate 更新前状态》);let dom document.getElementById(app).innerHTML;console.log(dom);console.log(%c%s, color:red, el : this.$el);console.log(this.$el);console.log(%c%s, color:red, data : this.$data);console.log(%c%s, color:red, message: this.message);},//更新完成updated: function () {console.group(updated 更新完成状态》);let dom document.getElementById(app).innerHTML;console.log(dom);console.log(%c%s, color:red, el : this.$el);console.log(this.$el);console.log(%c%s, color:red, data : this.$data);console.log(%c%s, color:red, message: this.message);},//销毁前//必须执行销毁方法才可以执行该生命周期beforeDestroy: function () {console.group(beforeDestroy 销毁前状态》);console.log(%c%s, color:red, el : this.$el);console.log(this.$el);console.log(%c%s, color:red, data : this.$data);console.log(%c%s, color:red, message: this.message);},//销毁后destroyed: function () {console.group(destroyed 销毁完成状态》);console.log(%c%s, color:red, el : this.$el);console.log(this.$el);console.log(%c%s, color:red, data : this.$data);console.log(%c%s, color:red, message: this.message);}});// 更新data中message数据值vm.message hehe;// 销毁Vue对象vm.$destroy();vm.message hehe;// 销毁后 Vue 实例会解绑所有内容,更新无效
/script
/html六、ElementVue脚手架
1.Element UI
(1)lement介绍
Element网站快速成型工具。是饿了么公司前端开发团队提供的一套基于Vue的网站组件库使用Element前必须要有Vue组件组成网页的部件例如超链接、按钮、图片、表格等Element官网https://element.eleme.cn/#/zh-CN
(2)快速入门
下载element组件库在当前前端项目中引入组件库创建页面在页面中引入组件库和样式 !-- 引入样式 --link relstylesheet href../element-ui/lib/theme-chalk/index.css!-- 引入VUE --script src../js/vue.js/script!-- 引入组件库 --script src../element-ui/lib/index.js/script(3)基础布局 将页面分成最多 24 个部分自由切换。并且支持响应式布局。 (4)容器布局 注意el-container外层容器。当子元素中包含 el-header 或 el-footer 时全部子元素会垂直上下排列否则会水平左右排列。
(5)表单组件 由输入框、下拉列表、单选框、多选框等控件组成用以收集、校验、提交数据。
在 Form 组件中每一个表单域由一个 Form-Item 组件构成表单域中可以放置各种类型的 表单控件包括 Input、Select、Checkbox、Radio、Switch、DatePicker、TimePicker。
(6)表格组件
用于展示多条结构类似的数据可对数据进行编辑、删除或其他自定义操作。
(7)导航栏组件
导航菜单默认为垂直模式(就是不写)通过mode属性可以使导航菜单变更为水平模式。另外在菜单中通过submenu组件可以生成二级菜单。Menu 还提供了background-color(菜单的背景色)、text-color(菜单的文字颜色)和active-text-color(当前激活菜单的文字颜色).
小结
使用步骤
1.下载Element核心库。 2.引入Element样式文件。 3.引入Vue核心js文件。 4.引入Element核心js文件。 5.借助常用组件编写网页。
常用组件
网页基本组成部分布局、按钮、表格、表单等等~~~ 常用组件不需要记住只需要在Element官网中复制并学会修改使用即可。
2.Node.js
学习
官网https://nodejs.org/zh-cn/
中文学习网http://nodejs.cn/learn
介绍
1.Node.js是一个基于Chrome V8引擎的JavaScript运行环境。Node.js使用了一个
事件驱动、非阻塞式I/O模型使其轻量又高效。
2.前端的底层htmlcss和js这些都不需要编译由浏览器解释运行解释型语言
3.Node.js的包管理器npm是全球最大的开源库生态系统
安装
下载对应你系统的Node.js版本:[https://nodejs.org/en/download/](https://nodejs.org/en/download/)历史版本https://nodejs.org/zh-cn/download/releases/
测试
测试在命令提示符下输入命令 node -v会显示当前node的版本3.nodejs的包管理器npm
(1)使用npm进行初始化
npm init (2)使用npm在本地即当前模块下安装软件 npm install 安装的技术
(3)全局安装
【1】查看你的电脑存放依赖的全局位置
npm root -g
【2】向全局位置安装依赖
npm install 安装的技术 -g g:global全局的意思
举例向全局位置安装vue
npm install vue -g
(4)淘宝NPM镜像【建议使用】
【1】下载步骤
1.更换成淘宝的源
npm config set registry https://registry.npm.taobao.org
2.降低版本
npm install cnpm7.1.0 -g
【2】验证是否安装成 【3】使用cnpm安装软件
cnpm install -g axios
【4】使用npm下载淘宝镜像报错问题
参考 4.webpack
【1】什么是webpack
webpack 是一个现代 javascript 应用程序的 静态模块打包器 (module bundler)
待会要学的 vue-cli 脚手架环境, 集成了 webpack, 所以才能对各类文件进行打包处理。 webpack是一个 静态模块 打包器,可以做以下的这些工作
语法转换(主要是浏览器兼容) less/sass转换成cssES6转换成ES5… html/css/js 代码压缩合并 (打包)webpack可以在开发期间提供一个开发服务器
【2】Webpack安装
全局安装
cnpm install webpack4.41.5 -g
cnpm install webpack-cli3.3.12 -g
安装后查看版本号
webpack -v
webpack-cli -v
【3】快速入门
方式一webpack原始方式
1新建文件夹 work3在创建src文件夹创建 bar.js
exports.infofunction(str){document.write(str);
}2src下创建logic.js
exports.addfunction(a,b){return ab;
}3src下创建main.js
var bar require(./bar);
var logic require(./logic);
bar.info( Hello world! logic.add(100,200));说明上述具有多个js文件那么我们在实际开发中使用的时候会导入过多的js文件使用起来不方便那么我们可以将上述多个js文件打包成一个js文件。
4创建配置文件webpack.config.js 该文件与src处于同级目录
var path require(path); // 导入 node.js 中专门操作路径的模块固定写法
//执行webpack命令的时候会读取到module.exports中的内容
module.exports {//执行webpack命令的时候,读取入口main.js由于main.js关联bar.js和logic.js所以会将这三个js文件合并到一个js文件中entry: ./src/main.js, // 打包入口文件的路径//输出文件位置output: {//__dirname表示当前工程目录path: path.resolve(__dirname, ./dist), // 输出文件的存放路径filename: bundle.js // 输出文件的名称}
};以上代码的意思是读取当前目录下src文件夹中的main.js入口文件内容把对应的js文件打包打包后的文件放入当前目录的dist文件夹下打包后的js文件名为bundle.js webpack 的 4.x 版本中默认约定 打包的入口文件为 src - main.js打包的输出文件为 dist - index.js 5执行编译命令
webpack
执行后查看bundle.js 会发现里面包含了上面两个js文件的内容
6创建index.html ,引用bundle.js
!doctype html
htmlhead /headbody script srcdist/bundle.js/script/body
/html创建完毕,完整目录如下 测试调用index.html会发现有内容输出Hello world!300
方式二基于NPM方式 新建项目空白目录并运行npm init –y 命令初始化包管理配置文件package.json -y 可以直接跳过配置 新建 src 源代码目录,并且把 bar.js 和 logic.js 和 main.js 文件复制到 src目录 创建index.html ,引用bundle.js !doctype html
htmlhead /headbody script srcdist/bundle.js/script/body
/html运行 npm install webpack webpack-cli 命令安装webpack相关的包 如果全局安装过webpack 和 webpack-cli工具, 此步骤可跳过 在项目根目录中创建名为webpack.config.js 的 webpack配置文件同上 var path require(path);
module.exports {mode: development, // mode 用来指定构建模式development、productionentry: ./src/main.js,output: {path: path.resolve(__dirname, ./dist),filename: bundle.js}
};mode: ‘development’ //mode 用来指定构建模式、production生产模式压缩 在 package.json 配置文件中的scripts节点下新增dev脚本如下 {name: work4,version: 1.0.0,description: ,main: index.js,scripts: {test: echo \Error: no test specified\ exit 1,dev: webpack //script 节点下的脚本可以通过 npm run 执行},keywords: [],author: ,license: ISC
} 完整代码结构 在终端中运行 npm run dev 命令启动webpack进行项目打包。 注意是在package.json 包下运行该命令
点击index.html文件查看结果, 会发现有内容输出Hello world!300
说明使用npm命令运行的原因是后期使用webpack命令的时候命令会很多不仅仅只有webpack几个字母不好记而使用npm run dev命令执行无论webpack命令有多少都会执行。
(1)作用
**将前端的文件进行打包。**可以将打包后的文件发布到前端服务器上
(2)webpack打包应用 webpack.config.js
var path require(path); // 导入 node.js 中专门操作路径的模块固定写法
//执行webpack命令的时候会读取到module.exports中的内容
module.exports {//执行webpack命令的时候,读取入口main.js由于main.js关联bar.js和logic.js//所以会将这三个js文件合并到一个js文件中entry: ./src/main.js, // 打包入口文件的路径//输出文件位置output: {//__dirname表示当前工程目录path: path.resolve(__dirname, ./dist), // 输出文件的存放路径filename: bundle.js // 输出文件的名称}
};在终端执行webpack命令
(3)基于npm方式打包 记住命令
npm run dev 启动项目
(4)webpack-dev-server开发服务器
作用当更改打包的源码的js文件时会自动更新 资源热更新。
介绍
修改main.js代码如下 需要每次在修改源码之前需要重新打包 每次修改代码, 都需要重新打包, 才能看到最新的效果, 且实际工作中, 打包非常费时 (30s - 60s) 之间
为什么费时?
构建依赖读取对应的文件, 才能加载用对应的 loader 进行处理将处理完的内容, 写入到 dist 目录
简而言之就是我们希望修改源码完毕之后不用再每次重新打包运行的结果直接是修改后的结果。
解决方案我们可以开启一个开发服务器webpack-dev-server, 在电脑内存中打包, 缓存一些已经打包过的内容, 只重新打包修改的文件 (热更新)
使用
如果模块(work3)下没有package.json 文件那么需要在模块下初始化命令npm init即可 修改 package.json - scripts 中的 dev, dependencies, devDependencies如下 devDependencies这是开发时依赖, 上线不依赖
{name: work4,version: 1.0.0,description: ,main: index.js,scripts: {test: echo \Error: no test specified\ exit 1,dev: webpack-dev-server},keywords: [],author: ,license: ISC,dependencies: {webpack: ^4.41.5,webpack-cli: ^3.3.12},devDependencies: { webpack-dev-server: ^3.11.2}
}
然后运行 cnpm install 指令,安装webpack,webpack-cli 和 webpack-dev-server
修改 webpack.config.js 文件,添加 devServer
var path require(path);
module.exports {mode: development, // mode 用来指定构建模式development、productionentry: ./src/main.js,devServer: {port: 8099,// 服务器占用8099端口open: true // 自动打开浏览器},output: {path: path.resolve(__dirname, ./dist),filename: bundle.js}
};删除之前的dist目录 将 index.html 中script 脚本的引用路径 !doctype html
htmlhead /headbody !-- 内存中读取 --script src/bundle.js/script/body
/html运行 npm run dev 命令 在浏览器中访问 http://localhost:8099地址查看自动打包效果 webpack-dev-server 会启动一个实时打包的 http 服务器 webpack-dev-server 打包生成的输出文件默认放到了项目根目录中基于内存 (5)小结
vue脚手架之前安装的软件
安装node.js安装淘宝镜像 cnpm安装打包器webpack
5.vue-cli脚手架掌握
(1)常见命令
# 1.启动项目
npm run dev
# 2.安装当前项目所有的依赖
cnpm i(2)vue脚手架入门
安装脚手架到全局位置
cnpm install vue-cli -g使用脚手架命令初始化工程开发中都是前端工程师做的
cnpm install vue-cli -g //只需安装一次可以使用cnpm安装通过//Windows使用 ‘vue init’ 的运行效果将会跟 ‘vue-cli2.x’ 相同
// work5 是模块名字
vue init webpack work5vue-cli脚手架常见的目录结构 #1.main.js :表示入口文件
#2.App.vue :表示根组件在脚手架中只要以.vue结尾的都是组件template书写html标签的只能书写一个根标签div/div/templatescript书写js代码的/scriptstyle书写css样式/style例如templatediv idapp!-- 脚手架的logo图片 --!-- img src./assets/logo.png --!-- 组件输出位置欢迎页面输出的文字是由下面的标签输出的 --!-- router-view/ --h1{{msg}}/h1/div/templatescriptexport default {data(){return {msg:vue架手架挺难的}}}/scriptstyle/* #app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;} *//style#3.index.html后期不会修改路由
【1】概念在vue脚手架中路由表示浏览器地址栏输入的路径和组件的映射关系。
脚手架总结
【1】config/index.js 【2】main.js 【3】根组件 【4】路由 注意前端工程师会在src下面创建一个文件夹:views。存放自己创建的组件即以.vue结尾
6.vue-cli脚手架练习
(1)模拟网易云音乐
【1】在根组件App.vue添加超链接
templatediv idapp!-- 脚手架的logo图片 --img src./assets/logo.png!-- 访问vue ,必须加#--a href#/访问vue/aa href#/friend访问好友/a!-- 组件输出位置欢迎页面输出的文字是由下面的标签输出的 --router-view/!-- h1{{msg}}/h1 --/div/templatescript
export default {// data(){// return {// msg:vue架手架挺难的// }// }
}
/scriptstyle
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
/style
【2】在路由中配置访问的路径和组件的关系 import Vue from vue
import Router from vue-router
import HelloWorld from /components/HelloWorld
// 表示src目录 src/views/friend.vue
//http://localhost:8080/#/friend path: /friend component: friendimport friend fromsrc/views/friend.vue
import friend from /views/friendVue.use(Router)export default new Router({routes: [{path: /,name: HelloWorld,component: HelloWorld},{path: /friend,name: haha,component: friend}]
})
【3】创建组件 templatediv idapp{{username}}/div
/templatescript
export default {data(){return{username:柳岩}}
}
/scriptstyle/style(2)将Element-UI组件库添加到vue脚手架中
【1】安装
1.在当前工程下安装element
cnpm i element-ui -S2.在main.js文件中引入element内容 // The Vue build version to load with the import command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from vue
//导入element
import ElementUI from element-ui;
// 导入element的css样式
import element-ui/lib/theme-chalk/index.css;
// 导入App.vue根组件
import App from ./App
// 导入路由
import router from ./router
// 让vue对象使用ElementUI
Vue.use(ElementUI);
Vue.config.productionTip false/* eslint-disable no-new */
new Vue({el: #app,router,components: { App },template: App/
})
【2】代码实现
1.在App.vue根组件中书写超链接
templatediv idapp!-- 脚手架的logo图片 --img src./assets/logo.png!-- 访问vue ,必须加#--a href#/访问vue/aa href#/friend访问好友/aa href#/element访问element/a!-- 组件输出位置欢迎页面输出的文字是由下面的标签输出的 --router-view/!-- h1{{msg}}/h1 --/div/templatescript
export default {// data(){// return {// msg:vue架手架挺难的// }// }
}
/scriptstyle
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
/style
2.在路由中配置路径和组件的关系
import Vue from vue
import Router from vue-router
import HelloWorld from /components/HelloWorld
// 表示src目录 src/views/friend.vue
import friend from /views/friend
import element from /views/elementVue.use(Router)export default new Router({routes: [{path: /,name: HelloWorld,component: HelloWorld},{path: /friend,name: haha,component: friend},{path: /element,name: element,component: element}]
})
3.创建组件 templateel-table:datatableDatastylewidth: 100%el-table-columnpropdatelabel日期width180/el-table-columnel-table-columnpropnamelabel姓名width180/el-table-columnel-table-columnpropaddresslabel地址/el-table-column/el-table/templatescriptexport default {data() {return {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 弄}]}}}/scriptstyle/style7.vue脚手架综合案例
(1)环境搭建
【1】后端环境day04
执行sql语句
CREATE DATABASE dbvue2;USE dbvue2;-- 创建学生表
CREATE TABLE student(number VARCHAR(10) UNIQUE, -- 学号NAME VARCHAR(10), -- 姓名birthday DATE, -- 生日address VARCHAR(200) -- 地址
);
INSERT INTO student VALUES (hm001,张三,1995-05-05,北京市昌平区);
INSERT INTO student VALUES (hm002,李四,1996-06-06,北京市海淀区);
INSERT INTO student VALUES (hm003,王五,1997-07-07,北京市朝阳区);
INSERT INTO student VALUES (hm004,赵六,1998-08-08,北京市丰台区);
INSERT INTO student VALUES (hm005,周七,1999-09-09,北京市顺义区);
INSERT INTO student VALUES (hm006,孙悟空,2000-01-01,花果山水帘洞);
INSERT INTO student VALUES (hm007,猪八戒,2001-02-02,高老庄翠兰家);
INSERT INTO student VALUES (hm008,沙和尚,2002-03-03,流沙河河底);
INSERT INTO student VALUES (hm009,唐玄奘,2003-04-04,东土大唐);修改连接数据库的参数启动后端项目
【2】前端环境
将work8.zip前端项目放到vscode的工作空间然后解压
安装依赖cnpm i 启动项目 npm run dev
七、web
1.内容介绍
WebWorld Wide Web即全球广域网也称万维网。它是一种基于超文本和HTTP的、全球性的、动态交互的、跨平台的分布式图像信息系统。是建立在Internet上的一种网络服务为浏览者在Internet上查找和浏览信息提供了图形化的、易于访问的直观界面其中的文档及超级链接将Internet上的信息节点组织成一个互为关联的网状结构。
简而言之就是我们平时上网浏览的网页玩的网页游戏上网下载资源。对于程序员而言就是前段知识、web服务器知识和数据库知识的结合就是web。
web发展历程
web1.0
1994年在中国第一个web网站是中国黄页由马云。属于静态网页。只能看不能交互。发布租赁信息。
web2.0
动态网站。网站数据是时时更新的。数据来自于数据库的。登录网站显示用户名天气预报微博头条。
可以实现前后台数据的交互
注意
网站前端知识、web服务器知识和数据库知识。包括网页
网页前端页面html页面2.软件架构模式
BSbrowser server 浏览器服务器 优点 只需要服务器用户下载浏览器维护方便减少用户的磁盘空间 缺点 给服务器造成压力用户观看体验不友好 CSclient server 客户端 服务器 优点 具有客户端和服务器端减轻服务器的压力用户观看体验友好 缺点 维护成本大版本升级麻烦占用户磁盘空间 3.B/S和C/S通信模式特点
先有请求后有响应请求和响应是成对出现的 4.web资源
资源
计算机中数据文件 分类 静态资源 html、css、js。只能书写静态网站静态网站的数据永远不会发生改变。 动态资源 使用一些语言(JAVAEE)可以实现数据的变化例如java语言。
5.URL请求路径
【1】作用通过资源路径可以访问到具体的服务器。
【2】URL Uniform Resource Locator 统一资源定位符是对互联网上资源位置的一种表示互联网上的每个文件都有一个唯一的URL。
【3】格式
协议://服务器的ip地址:服务器的端口号/项目名/资源路径 jdbc:mysql://localhost:3306/数据库名https://www.jd.com/
说明1协议是一种规范。类似于我们之前讲解的TCP UDP(传输层)这里讲解的是应用层(http https协议)2服务器的ip地址就是访问的服务器的地址。同一个网段中服务器ip地址是唯一的。说明如果我们在自己电脑上进行练习ip地址书写127.0.0.1或者localhost3服务器的端口号访问服务器端的进程号属于唯一标识。4)/项目名/资源路径【4】浏览器通过url访问服务器的过程
https://www.baidu.com/s?ieUTF-8wdjava 6.服务器
【1】服务器是提供计算服务的设备。由于服务器需要请求响应并进行处理因此一般来说服务器应具备承担服务并且保障服务的能力。
【2】分类
硬件服务器
服务器的构成包括处理器、硬盘、内存、系统总线等和通用的计算机架构类似但是由于需要提供高可靠的服务因此在处理能力、稳定性、可靠性、安全性、可扩展性、可管理性等方面要求较高。
软件服务器:
服务器软件本质上是一个应用程序由代码编写而成运行在服务器设备上。能够接收请求并根据请求给客户端响应数据发布资源(静态和动态)。数据库服务器、邮件服务器(易邮)、网页服务器tomcat nginx发布网页等
【3】常见的web服务器 * Tomcat: Apache软件基金开源免费的web服务器,支持JavaEE规范Servlet/Jsp.* Jetty:Apache组织开源免费的小型web服务器,支持JavaEE规范.
* JBoss: RedHat红帽公司的开源免费的web服务器,支持JavaEE规范.
* Glass Fish:Sun公司开源免费的web服务器,支持JavaEE规范.---------------------------------------------------------------------* WebLogic: Oracle公司收费的web服务器,支持JavaEE规范.
* WebSphere:IBM公司收费的web服务器,支持JavaEE规范.八.tomcat
1.目录结构 2.启动和关闭以及访问tomcat 启动 访问
在浏览器地址栏上输入localhost:8080 关闭 3.解决启动tomcat失败的问题
【1】端口号冲突
打开命令行输入netstat -nao找到端口号为8080对应的PID 打开任务管理器—详细信息找到对应的PID然后结束对应的任务。 【2】jdk环境变量
打开命令行输入java -version查看是否出现版本号如果没有请检查java_home是否有问题。 【3】删除环境变量中TOMCAT_HOME
右击此电脑—属性—高级系统设置----环境变量
4.使用tomcat发布web项目
【1】在tomcat的安装目录webapps下发布web资源
(1)在webapps下创建一个文件夹作为项目名
(2)在该文件夹下创建一个静态资源html页面 !DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
bodyitcast
/body
/html(3)到bin目录启动tomcat----双击startup.bat文件
(4)在浏览器中访问 【2】在idea中创建web项目
(1)
(2) (3)删除一些内容
pom.xml留下的内容
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.itheima.sh.heima153/groupIdartifactIdday15_web02/artifactIdversion1.0-SNAPSHOT/versionnameday15_web02/name!--TODO:web工程的打包方式。普通java工程打包方式是jar,也是默认的。不能删除--packagingwar/packagingproperties!--TODO:jdk编译版本--maven.compiler.target1.8/maven.compiler.targetmaven.compiler.source1.8/maven.compiler.source/propertiesdependencies!--TODO:不要删除--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion4.0.1/versionscopeprovided/scope/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-war-plugin/artifactIdversion3.3.1/version/plugin/plugins/build
/project5.使用在idea中创建的web项目发布资源 九、Servlet
之前我们使用浏览器访问的是静态资源即html。web资源除了静态资源还有动态资源即数据可以实现变化并且前端浏览器通过动态资源可以实现数据的交互。那么如果想客观客户端访问服务器的动态资源需要我们在后端中定义类直接或者间接实现Servlet接口。
1.Servlet介绍 Servlet是一个接口即规范定义的实现类必须实现接口中的所有抽象方法Servlet全称Server Applet服务器端的程序是sun公司提供一套规范用来处理客户端请求、响应给浏览器的动态web资源。其实servlet的实质就是java代码通过java的API动态的向客户端输出内容并且从客户端接收数据。一个类要想通过浏览器被访问到那么这个类就必须直接或间接的实现Servlet接口
2.Servlet作用
1.接收客户端的请求2.处理业务逻辑3.将响应数据给浏览器3.Servlet快速入门 【1】步骤
创建web项目导入servlet依赖 !--导入依赖--dependencies!--导入servlet依赖--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.0.1/version/dependency/dependencies在创建的web项目中自定义类实现Servlet接口在自定义类中实现Servlet接口中所有的抽象方法在实现Servlet接口的service方法体中书写代码处理业务逻辑
void service(ServletRequest req, ServletResponse res) 在web项目的核心配置文件web.xml中配置访问servlet的路径。 说明这样配置是告知tomcat有具体的Servlet类需要被访问。 启动tomcat在浏览器中访问servlet类
【2】实现
创建maven的web项目导入servlet的依赖 !--servlet--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.0.1/version!--编译 测试需要运行时不需要--scopeprovided/scope/dependency在创建的web项目中自定义类实现Servlet接口在自定义类中实现Servlet接口中的所有的抽象方法在实现Servlet接口的service方法体中书写代码处理业务逻辑
package com.itheima.sh.a_demo_01;import javax.servlet.*;
import java.io.IOException;/*2.在创建的web项目中自定义类实现Servlet接口*/
public class HelloWorldServlet implements Servlet{//3.在自定义类中实现Servlet接口中的所有的抽象方法//4.在实现Servlet接口的service方法体中书写代码处理业务逻辑Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println(service....);}Overridepublic void init(ServletConfig servletConfig) throws ServletException {}Overridepublic ServletConfig getServletConfig() {return null;}Overridepublic String getServletInfo() {return null;}Overridepublic void destroy() {}}
在web项目的核心配置文件web.xml中配置servlet的路径
?xml version1.0 encodingUTF-8?
web-app xmlnshttp://java.sun.com/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_1.xsdversion3.1!--5.在web项目的核心配置文件web.xml中配置访问servlet的路径。说明这样配置是告知tomcat有具体的Servlet类需要被访问。--!--1.servlet 表示将当前Servlet类注册到tomcat中告知tomcat有一个类要被访问--servlet!--表示当前要被访问类的标识在当前web.xml中要唯一helloWorldServlet属于标识符--servlet-namehelloWorldServlet/servlet-name!--配置要访问 的servlet类必须是类的全路径包名.类名。说明tomcat底层通过获取这里的类全路径使用反射技术调用当前类的无参构造方法创建对象--servlet-classcom.itheima.sh.a_demo_01.HelloWorldServlet/servlet-class/servlet!--配置要访问的servlet类的映射路径--servlet-mapping!--这里要和上面的servlet-name文本值一致这里找到上面的servlet-name--servlet-namehelloWorldServlet/servlet-name!--浏览器上地址栏上输入的映射路径及访问路径这里必须加/--url-pattern/hello/url-pattern/servlet-mapping
/web-app
启动tomcat 在浏览器中访问servlet类 4.Servlet的执行原理
【1】执行流程 【2】原理
说明
1.当我们点击run运行的时候tomcat之所以会启动是因为程序入口(main方法)在tomcat中
2.tomcat开始运行会加载web项目里面的配置文件web.xml(xml解析读取数据)
主要是根据url-pattern 找到对应的servlet-class
3.然后tomcat进入等待状态(永不停止除非手动关闭)
4.当用户在浏览器中输入地址http://localhost:8080/hello就会定位到tomcat的访问的项目下面的某个servlet中
5.tomcat会根据 /hello 的servlet的虚拟路径 找到HelloServlet的全限定名
6.tomcat底层通过反射创建HelloServlet的对象并调用HelloServlet的service方法
Class clazz Class.forName(全限定名);
Servlet servlet clazz.newInstance();//实际上HelloServlet对象向上转型
servlet.service();5.Servlet生命周期
【1】生命周期
指的是一个对象从生创建到死销毁的一个过程。
【2】生命周期的api
// 1. servlet对象创建完毕使用对象调用此方法初始化方法
//只有在第一次访问的时候执行一次
public void init(ServletConfig servletConfig);
// 2. 用户访问servlet时调用此方法 (每次访问都会调用一次)
public void service(ServletRequest servletRequest, ServletResponse servletResponse);
// 3. servlet对象销毁时调用此方法
public void destroy();【3】Servlet生命周期的api执行时机图解 * 创建1默认情况下用户第一次访问时创建servlet执行init方法* 运行提供服务用户每次访问时都执行service方法* 销毁服务器正常关闭时销毁servlet执行destroy方法【4】代码实现
package com.itheima.sh.a_servlet_01;import javax.servlet.*;
import java.io.IOException;public class Life01Servlet implements Servlet {/*反射调用无参构造方法创建对象*/public Life01Servlet() {System.out.println(无参构造。。。。);}Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println(init。。。。);}Overridepublic ServletConfig getServletConfig() {return null;}Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println(service。。。。);}Overridepublic String getServletInfo() {return null;}Overridepublic void destroy() {System.out.println(destroy。。。。);}
}
【5】结果 1.何时创建servlet
第一次访问servlet的时候创建
2.谁创建的
tomcat服务器创建的
3.创建对象时做了什么
调用无参构造方法创建对象然后立刻调用init初始化方法
4.每次访问servlet执行哪个方法
service方法
5.何时销毁servlet
关闭tomcat服务器调用destroy方法
6.服务器启动立刻加载Servlet对象
【1】问题发现init默认第一次被访问的时候才调用适合用来初始化项目数据
如果项目数据很多加载就需要一定的时间这样就会给用户的体验不好因为要等比较久的时间
【2】解决服务器一启动就执行init方法
【3】实现在web.xml核心配置文件中对应的servlet标签按照如下配置
注意 1.使用标签进行配置表示标记容器是否应该在启动的时候加载这个servlet(实例化并调用其init()方法) 2.它的文本值必须是一个整数表示servlet应该被载入的顺序 3.如果文本值是负数默认值是-1 【用户第一次访问时创建】 4.当值大于等于0时表示容器在应用启动时就加载并初始化这个servlet 5.正数的值越小该servlet的优先级越高应用启动时就越先加载。 6.当值相同时容器就会自己选择顺序来加载 servletservlet-namelife01Servlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.Life01Servlet/servlet-class!--load-on-startup 标签可以让tomcat服务器启动就创建对应的servlet。标签文本值必须是整数数字越小创建servlet的优先级越高--load-on-startup2/load-on-startup/servletservlet-mappingservlet-namelife01Servlet/servlet-nameurl-pattern/life01/url-pattern/servlet-mapping总结
1.load-on-startup标签可以让tomcat服务器启动就创建对应的servlet。标签文本值必须是整数
数字越小创建servlet的优先级越高建议是大于等于0的整数
load-on-startup2/load-on-startup2.配置load-on-startup标签后servlet生命周期如下 7.Servlet实现方式
一共有三种
快捷键
1.ctrl alt u 查看一个类的继承结构图
2.ctrl h 这个类的简化版继承结构1实现Servlet方式二_自定义类继承GenericServlet
编写Servlet实现类只要重写service方法
【1】描述问题
Servlet中使用频率最高最重要的方法是service方法大部分场景
但是我们每次编写Servlet实现类都是直接实现Servlet接口重写5个抽象方法(太冗余)【2】解决问题
我们可以自定义类继承GenericServlet抽象类只在子类中重写service即可。
不用重写所有的抽象方法。【3】步骤
1.自定义类继承GenericServlet类
2.在子类中重写service方法处理业务逻辑
3.在web.xml中进行映射路径的配置
4.在浏览器客户端访问servlet类
【4】代码实现
package com.itheima.sh.a_servlet_01;import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;/*
1.自定义类继承GenericServlet类*/
public class Demo01Servlet extends GenericServlet {// 2.在子类中重写service方法处理业务逻辑Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println(service....);}
}
?xml version1.0 encodingUTF-8?
web-app xmlnshttp://java.sun.com/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_1.xsdversion3.1!--3.在web.xml中进行映射路径的配置--servletservlet-namedemo01Servlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.Demo01Servlet/servlet-class/servletservlet-mappingservlet-namedemo01Servlet/servlet-nameurl-pattern/demo01/url-pattern/servlet-mapping/web-app
小结方式二的好处是只需要重写service方法在方法体内部处理业务逻辑即可。
2实现Servlet方式三_自定义类继承HttpServlet
根据页面不同的请求方式执行具体的请求方法
【1】问题
我们在前端的form表单中method属性学习过有两种常用的请求方式get/post我们现在的service方法是这样的
用户发送请求无论是什么请求方式都会统一的执行service方法我们无法很好的区别是哪一种
请求方式【2】解决问题
我们可以自定义类继承HttpServlet就可以根据不同的请求做不同的处理get post 【3】步骤
1.自定义类继承HttpServlet
2.在子类中根据不同的请求方式重写请求方式的方法get请求---重写doGet方法post请求---重写doPost方法
3.在方法体中书写业务逻辑的代码
4.在web.xml中进行配置
5.浏览器客户端访问servlet【4】实现
package com.itheima.sh.a_servlet_01;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*1.自定义类继承HttpServlet*/
public class Demo02Servlet extends HttpServlet {/*2.在子类中根据不同的请求方式重写请求方式的方法get请求---重写doGet方法post请求---重写doPost方法*/// 3.在方法体中书写处理业务逻辑的代码Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(get....);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(post....);}
}!--4.在web.xml中进行配置--servletservlet-namedemo02Servlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.Demo02Servlet/servlet-class/servletservlet-mappingservlet-namedemo02Servlet/servlet-nameurl-pattern/demo02/url-pattern/servlet-mapping小结
1.实现servlet方式三的好处
可以根据不同的请求执行对应的方法处理满足http协议的请求和响应
2.对ServletRequest和HttpServletRequest接口的说明
这个对象封装了浏览器发送的所有请求数据兼容大部分协议。HttpServletRequest是子接口可以匹配http协议下的所有请求。
3实现servlet方式三_继承HttpServlet的执行流程
疑问就是正常浏览器访问tomcat服务器需要访问servlet接口中的service方法但是方式三在子类中没有重写servlet中的service方法只重写了doGet和doPost方法那么底层是如果执行呢 小结
当我们访问自定义类的servlet的时候先访问HttpServlet类实现Servlet接口中的service方法在service方法体中调用了重载的service方法在该方法体内部获取请求方式根据不同的请求方式执行对应的方法。
get请求---doGet方法
post请求---doPost()方法注意查看某个类的成员结构快捷键alt7
4实现servlet的三种方式总结
1.自定义类实现Servlet接口重写所有的抽象方法不能处理满足http协议的请求和响应
2.自定义类继承GenericService抽象类该抽象类是Servlet接口的子类这种方式只重写service方法即可但是不能处理满足http协议的请求和响应同时不能根据具体的请求方式执行具体的方法
3.自定义类继承HttpServlet抽象类该抽象类是GenericServlet的子类根据不同的请求方式执行对应方法掌握get---doGetpost---doPost可以处理满足http协议的请求和响应8.编写servlet常见的问题
1遇到500错误
表示服务器内部异常 2遇到404错误
浏览器客户端访问服务器的资源不存在 注意报404的根本原因是用户操作不当导致的。
3遇到405错误
服务器servlet没有重写doGet或者doPost方法。 package com.itheima.sh.d_servlet_04;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*TODO:编写Servlet常见异常1.服务器内部出现异常在浏览器中显示的是500:HTTP Status 500 – Internal Server Error解决方案找出异常位置修改代码2.浏览器出现404就是用户问题用户操作不当访问的资源在服务器中不存在基本都是路径有问题。HTTP Status 404 – Not Found解决方案1查看你在地址栏上输入的地址路径和服务器中的资源路径是否匹配2当前项目配置了虚拟路径但是你访问的时候没有加虚拟路径3) 访问的路径在当前项目中存在但是在当前项目中的target位置不存在执行maven生命周期命令clean清除target重启启动tomcat即可3.浏览器出现405子类Servlet没有重写父类HttpServlet类中的doGet和doPost方法导致调用了父类HttpServlet中doGet和doPost方法 HTTP Status 405 – Method Not Allowed解决方案子类重写HttpServlet的doGet和doPost方法并且在子类方法体中不能调用父类中的doGet和doPost方法不能书写super.doGet(req, resp);*/
public class ExceptionDemo01Servlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(哈哈呵呵嘿嘿);//调用父类HttpServlet类中doGet(req, resp)那么就会报错HTTP Status 405 – Method Not Allowed}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}
小结
1.500错误服务器异常
2.404错误找不到资源
3.405错误
如果我们不重写doGet/doPost方法那么父类的doGet/doPost方法会执行继承给浏览器响应一个错误状态码405http1.1。
9.Servlet映射路径理解
能够配置一个Servlet映射单个和多个url
【1】一个Servlet映射单个url 【2】一个Servlet映射多个url 注解版本 10.Servlet映射路径配置规范
servlet映射路径一共有四种
1完全路径匹配
就是访问什么在web.xml中配置什么路径。 /hello /user package com.itheima.sh.a_servlet_01;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;public class PathOneServlet extends GenericServlet {Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println(PathOneServlet....);}} servletservlet-namepathOneServlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.PathOneServlet/servlet-class/servletservlet-mappingservlet-namepathOneServlet/servlet-name!--完全路径匹配--url-pattern/user/one/url-pattern/servlet-mapping2目录匹配/user/* package com.itheima.sh.a_servlet_01;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;public class PathTwoServlet extends GenericServlet {Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println(PathTwoServlet....);}} servletservlet-namepathTwoServlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.PathTwoServlet/servlet-class/servletservlet-mappingservlet-namepathTwoServlet/servlet-name!--目录匹配--url-pattern/user/*/url-pattern/servlet-mapping3后缀名匹配*.do *.action
注意这里不能书写 / 访问以.do或者.action结尾的资源路径后缀名都属于标识符 package com.itheima.sh.a_servlet_01;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;public class PathThrServlet extends GenericServlet {Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println(PathThrServlet....);}} servletservlet-namepathThrServlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.PathThrServlet/servlet-class/servletservlet-mappingservlet-namepathThrServlet/servlet-name!--后缀名匹配前面不能加/--url-pattern*.do/url-pattern/servlet-mapping4缺省路径 /
如果上述三种路径都不满足就访问缺省路径。 package com.itheima.sh.a_servlet_01;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;public class PathFourServlet extends GenericServlet {Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println(PathFourServlet....);}} servletservlet-namepathFourServlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.PathFourServlet/servlet-class/servletservlet-mappingservlet-namepathFourServlet/servlet-name!--缺省路径匹配--url-pattern//url-pattern/servlet-mapping小结完全路径匹配 目录匹配 后缀名匹配 缺省路径
11.绝对路径
【1】绝对路径有两种写法
1.带网络三要素http://ip地址端口号/资源路径
2.不带网络三要素/资源路径 这里的 / 不能省略要求访问的资源必须在同一个服务器上【2】代码实现
html
a hrefhttp://127.0.0.1:8080/pathAbso带网络三要素的绝对路径/abr
a href/pathAbso不带网络三要素的绝对路径/abrServlet
package com.itheima.sh.b_servlet_02;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class PathAbso01Servlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(get....);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(post....);}
}web.xml servletservlet-namepathAbso01Servlet/servlet-nameservlet-classcom.itheima.sh.a_servlet_01.PathAbso01Servlet/servlet-class/servletservlet-mappingservlet-namepathAbso01Servlet/servlet-nameurl-pattern/pathAbso/url-pattern/servlet-mapping12.相对路径
【1】相对路径不是相对当前项目而是针对当前浏览器地址栏上的url而言。
【2】案例一 #假设我们在浏览器地址栏访问的页面路径 http://localhost:8080/demo01.html#而在demo01.html页面想使用相对路径访问servlet #http://localhost:8080/pathAbso说明如果在http://localhost:8080/demo01.html 页面中访问 http://localhost:8080/pathAbso 该servlet我们通过url观察发现只有最后一级目录不一样所以在demo01.html页面中相对的路径的写法是./pathAbso 这里的./表示当前路径 可以省略不写即直接写 pathAbso
demo01.html a href./pathAbso相对路径/abra hrefpathAbso相对路径/abr【3】案例二 # 如果在http://localhost:8080/aaa/demo02.html # 页面中访问 http://localhost:8080/pathAbso 该servlet我们通过url观察发现在demo02.html也面中书写访问的servlet即pathAbso和当前页面的父目录aaa是同等目录所以我这里先找该页面的父目录然后在找该servlet即pathAbso../pathAbso ../表示上一级目录或者父目录找到父目录之后再找servlet即pathAbsodemo02.html
a href../pathAbso相对路径/abr13.Servlet3.0注解开发
【1】问题
说明之前我们都是使用web.xml进行servlet映射路径的配置。
这样配置的弊端web.xml中具有非常多个配置信息显得非常臃肿并且容易出错。
【2】解决问题
使用web.xml配置映射路径的方式属于servlet2.5的技术。从servlet3.0开始引入注解配置访问servlet取代了web.xml配置。 !-- TODO:想使用注解开发导入的Servlet依赖必须是3.0以上的 --dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion4.0.1/versionscopeprovided/scope/dependency【3】配置步骤
1.在包上右键---new---servletcreate new Servlet
2.输入类名
3.在方法体内输入逻辑代码
4.在浏览器地址栏中输入访问的路径【4】实现
1.在包上右键—new—servletcreate new Servlet 2.输入类名 3.在方法体内输入逻辑代码
package com.itheima.sh.c_servlet_anno_03;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/annoDemo01Servlet)
public class AnnoDemo01Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(注解开发);}
}
4.在浏览器地址栏中输入访问的路径 14.修改idea创建注解的servlet模板
1File—Settings 2找到servlet的模板按照如下修改 #if (${PACKAGE_NAME} ${PACKAGE_NAME} ! )package ${PACKAGE_NAME};#end
#parse(File Header.java)
javax.servlet.annotation.WebServlet(/${Entity_Name})
public class ${Class_Name} extends javax.servlet.http.HttpServlet {protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {doGet(request,response);
}protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {}
}
15.关于servlet3.0注解开发的疑问配置路径省略了属性urlPatterns
正常我们在WebServlet注解中配置的路径赋值给属性urlPatterns但是urlPatterns不能省略的在一个注解中如果含有多个属性并且每个属性都有默认值此时给value赋值可以省略value属性。 注意在WebServlet注解中value等同于urlPatterns属性。 十.HTTP协议
1.HTTP协议介绍
【1】概念
全称超文本传输协议HTTPHyperText Transfer Protocol是互联网上应用最为广泛的一种网络协议。
简而言之浏览器和服务器数据交换固定的格式。
【2】版本
HTTP协议版本如下
http1.01996每次请求都有一个新的连接开销大比较慢http1.11999长连接多个请求共用一个连接开销小一些比较快传输的数据都是文本比较慢
【3】分类
请求报文协议浏览器发送给服务器的数据1)请求行 2)请求头 3)请求体响应报文协议服务器发送给浏览器的数据1)响应行 2)响应头 3)响应体
【4】特点
先有请求再有响应一个请求对应一个响应
2.浏览器抓包观察请求报文协议
【1】步骤
1.创建html页面
2.在html页面书写html代码
3.创建servlet
4.在servlet中书写java代码
5.启动服务器
6.打开浏览器在浏览器访问页面然后按f12 点击网络 network
7.抓包结果分析【2】实现
1.创建html页面
2.在html页面书写html代码
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
bodyh2GET请求/h2
form action/getServlet methodget用户名input typetext nameusername valuezhangsan /br密码input typetext namepwd value123 /brinput typesubmit value提交/
/formh2POST请求/h2
form action/postServlet methodpost用户名input typetext nameusername valuezhangsan/br密码input typetext namepwd value123/brinput typesubmit value提交/
/form/body
/html3.创建servlet
4.在servlet中书写java代码
package com.itheima.sh.d_http_04;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/getServlet)
public class GetServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(get....);}
}package com.itheima.sh.d_http_04;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/postServlet)
public class PostServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(post....);}
}5.启动服务器
6.打开浏览器在浏览器访问页面然后按f12 点击网络 7.抓包结果分析 请求报文协议的get请求和post请求区别
1.GET请求1请求行直接传递请求参数.将请求参数追加在URL后面不安全。例如form.html?usernamejackusername1234补充但是get请求可以作为商品的分享。2URL长度限制(不同浏览器限制大小不一致)GET请求方式的数据大小不可以传输数据量较大或者非文本数据。例如图片或者视频。3请求体里面没有内容。2.POST请求1请求参数以请求体形式发送给服务器数据传输安全。2请求数据可以为非文本数据可以传输数据量较大的数据。3只有表单设置为method”post”才是post请求.或者axios.post()也属于post请求其他的都是get请求。常见GET请求地址栏直接访问、a href””、img src”” location.href 、axios.get()等十一.Request Response
1.Request和Response的概述
# 重点1.service方法的两个参数request和response是由tomcat创建的void serviceServletRequest varl,ServletResponse var22.request 表示请求数据tomcat将浏览器发送过来的请求数据解析并封装到request对象中servlet开发者可以通过request对象获得请求数据3.response 表示响应数据服务器发送给浏览器的数据servlet开发者可以通过response对象设置响应数据 Request是请求对象Response是响应对象。这两个对象在我们使用Servlet的时候有看到 此时我们就需要思考一个问题request和response这两个参数的作用是什么 request获取请求数据 浏览器会发送HTTP请求到后台服务器[Tomcat]HTTP的请求中会包含很多请求数据[请求行请求头请求体]后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中所存入的对象即为request对象所以我们可以从request对象中获取请求的相关参数获取到数据后就可以继续后续的业务不如获取用户名和密码就可以实现登录操作的相关业务 response设置响应数据 业务处理完后后台就需要给前端返回业务处理的结果即响应数据把响应数据封装到response对象中后台服务器[Tomcat]会解析response对象按照[响应行响应头响应体]格式拼接结果浏览器最终解析结果把内容展示在浏览器给用户浏览
案例
WebServlet(/demo3)
public class ServletDemo3 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//使用request对象 获取请求数据String name request.getParameter(name);//url?namezhangsan//使用response对象 设置响应数据response.setHeader(content-type,text/html;charsetutf-8);response.getWriter().write(h1name,欢迎您/h1);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(Post...);}
}启动成功后就可以通过浏览器来访问并且根据传入参数的不同就可以在页面上展示不同的内容 2.Request对象
(1)Request继承体系
当我们的Servlet类实现的是Servlet接口的时候service方法中的参数是ServletRequest和ServletResponse当我们的Servlet类继承的是HttpServlet类的时候doGet和doPost方法中的参数就变成HttpServletRequest和HttpServletResponse
那么
ServletRequest和HttpServletRequest的关系是什么request对象是由谁来创建的request提供了哪些API这些API从哪里查
首先我们先看下Request的继承体系 ServletRequest request new RequestFacade();
从上图中可以看出ServletRquest和HttpServletRequest都是java提供的所以我们可以打开JavaEE提供的API文档[参考资料中的JavaEE7-api.chm]打开后可以看到 所以ServletRequest和HttpServletRequest是继承关系并且两个都是接口接口是无法创建对象这个时候就引发 下面这个问题 这个时候我们就需要用到Request继承体系中的RequestFacade
该类实现了HttpServletRequest接口也间接实现了ServletRequest接口。Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用的所以Tomcat提供了方法参数接口的具体实现类并完成了对象的创建要想了解RequestFacade中都提供了哪些方法我们可以直接查看JavaEE的API文档中关于ServletRequest和HttpServletRequest的接口文档因为RequestFacade实现了其接口就需要重写接口中的方法
对于上述结论要想验证可以编写一个Servlet在方法中把request对象打印下就能看到最终的对象是不是RequestFacade
WebServlet(/demo2)
public class ServletDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(request);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}启动服务器运行访问http://localhost:8080/request-demo/demo2,得到运行结果: (2)Request获取请求数据
HTTP请求数据总共分为三部分内容分别是请求行、请求头、请求体对于这三部分内容的数据分别该如何获取首先我们先来学习请求行数据如何获取?
【1】获取请求行数据
请求行包含三块内容分别是请求资源路径、请求方式、HTTP协议及版本 对于这个三部分内容request对象都提供了对于的API方法来获取具体如下
获取请求方式GET
String getMethod()获取虚拟目录项目访问路径/request-demo
String getContextPath()获取URL统一资源定位符 http://localhost:8080/request-demo/req1
StringBuffer getRequestURL()获取URI统一资源标识符 /request-demo/req1
String getRequestURI()获取请求参数(GET方式): usernamezhangsanpassword123
String getQueryString()案例
/*** request 获取请求数据*/
WebServlet(/req1)
public class RequestDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// String getMethod()获取请求方式 GETString method req.getMethod();System.out.println(method);//GET// String getContextPath()获取虚拟目录(项目访问路径)/request-demoString contextPath req.getContextPath();System.out.println(contextPath);// StringBuffer getRequestURL(): 获取URL(统一资源定位符)http://localhost:8080/request-demo/req1StringBuffer url req.getRequestURL();System.out.println(url.toString());// String getRequestURI()获取URI(统一资源标识符) /request-demo/req1String uri req.getRequestURI();System.out.println(uri);// String getQueryString()获取请求参数GET方式 usernamezhangsanString queryString req.getQueryString();System.out.println(queryString);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}启动服务器访问http://localhost:8080/request-demo/req1?usernamezhangsanpasswrod123获取的结果如下: 【2】获取请求头数据
对于请求头的数据格式为 keyvalue如下 所以根据请求头名称获取对应值的方法为
String getHeader(String name)
参数name书写的是请求头冒号左边的内容例如User-AgentUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
接下来在代码中如果想要获取客户端浏览器的版本信息则可以使用
/*** request 获取请求数据*/
WebServlet(/req1)
public class RequestDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求头: user-agent: 浏览器的版本信息String agent req.getHeader(user-agent);System.out.println(agent);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}
重新启动服务器后http://localhost:8080/request-demo/req1?usernamezhangsanpasswrod123获取的结果如下: 【3】获取请求体数据
浏览器在发送GET请求的时候是没有请求体的所以需要把请求方式变为POST请求体中的数据格式如下 对于请求体中的数据Request对象提供了如下两种方式来获取其中的数据分别是:
获取字节输入流如果前端发送的是字节数据比如传递的是文件数据则使用该方法
ServletInputStream getInputStream()
该方法可以获取字节和字符数据
获取字符输入流如果前端发送的是纯文本数据则使用该方法
BufferedReader getReader()接下来大家需要思考要想获取到请求体的内容该如何实现? 具体实现的步骤如下: 1.准备一个页面在页面中添加form表单,用来发送post请求 2.在Servlet的doPost方法中获取请求体数据 3.在doPost方法中使用request的getReader()或者getInputStream()来获取 4.访问测试 在项目的webapp目录下添加一个html页面名称为req.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
!-- action:form表单提交的请求地址method:请求方式指定为post
--
form action/request-demo/req1 methodpostinput typetext nameusernameinput typepassword namepasswordinput typesubmit
/form
/body
/html在Servlet的doPost方法中获取数据
/*** request 获取请求数据*/
WebServlet(/req1)
public class RequestDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//在此处获取请求体中的数据}
}调用getReader()或者getInputStream()方法因为目前前端传递的是纯文本数据所以我们采用getReader()方法来获取
/*** request 获取请求数据*/
WebServlet(/req1)
public class RequestDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取post 请求体请求参数//1. 获取字符输入流BufferedReader br req.getReader();//2. 读取数据String line br.readLine();System.out.println(line);}
}注意
BufferedReader流是通过request对象来获取的当请求完成后request对象就会被销毁request对象被销毁后BufferedReader流就会自动关闭所以此处就不需要手动关闭流了。
4.启动服务器通过浏览器访问http://localhost:8080/request-demo/req.html 点击提交按钮后就可以在控制台看到前端所发送的请求数据 【4】获取请求参数的通用方式
1.什么是请求参数?
为了能更好的回答上述两个问题我们拿用户登录的例子来说明
1.1 想要登录网址需要进入登录页面
1.2 在登录页面输入用户名和密码
1.3 将用户名和密码提交到后台
1.4 后台校验用户名和密码是否正确
1.5 如果正确则正常登录如果不正确则提示用户名或密码错误
上述例子中用户名和密码其实就是我们所说的请求参数。
get请求请求参数位于url后面。
post请求请求参数位于请求体中。
2.什么是请求数据?
请求数据则是包含请求行、请求头和请求体的所有数据
3.请求参数和请求数据的关系是什么?
3.1 请求参数是请求数据中的部分内容
3.2 如果是GET请求请求参数在请求行中
3.3 如果是POST请求请求参数一般在请求体中
对于请求参数的获取,常用的有以下两种:
GET方式:
String getQueryString()
POST方式:
BufferedReader getReader();
有了上述的知识储备我们来实现一个案例需求:
1发送一个GET请求并携带用户名后台接收后打印到控制台
2发送一个POST请求并携带用户名后台接收后打印到控制台
此处大家需要注意的是GET请求和POST请求接收参数的方式不一样具体实现的代码如下:
WebServlet(/req1)
public class RequestDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String result req.getQueryString();System.out.println(result);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {BufferedReader br req.getReader();String result br.readLine();System.out.println(result);}
}GET请求和POST请求获取请求参数的方式不一样在获取请求参数这块该如何实现呢?
要想实现我们就需要思考:
GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样是否可以提供一种统一获取请求参数的方式从而统一doGet和doPost方法内的代码?
解决方案一:
WebServlet(/req1)
public class RequestDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取请求方式String method req.getMethod();//获取请求参数String params ;if(GET.equals(method)){params req.getQueryString();}else if(POST.equals(method)){BufferedReader reader req.getReader();params reader.readLine();}//将请求参数进行打印控制台System.out.println(params);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req,resp);}
}使用request的getMethod()来获取请求方式根据请求方式的不同分别获取请求参数值这样就可以解决上述问题但是以后每个Servlet都需要这样写代码实现起来比较麻烦这种方案我们不采用
解决方案二:
request对象已经将上述获取请求参数的方法进行了封装并且request提供的方法实现的功能更强大以后只需要调用request提供的方法即可在request的方法中都实现了哪些操作
(1)根据不同的请求方式获取请求参数获取的内容如下 (2)把获取到的内容进行分割内容如下 (3)把分割后端数据存入到一个Map集合 注意因为参数的值可能是一个也可能有多个所以Map的值的类型为String数组。
基于上述理论request对象为我们提供了如下方法
获取所有参数Map集合
MapString,String[] getParameterMap()根据名称获取参数值数组
String[] getParameterValues(String name)
参数name是前端提交请求参数的等号左边的key(name)usernamezhangsan
想获取zhangsangetParameterValues(username);
根据名称获取参数值单个值
String getParameter(String name)
注意如果参数的name有多个值谁在前面先获取谁
接下来我们通过案例来吧上述的三个方法进行实例演示
1.修改req.html页面添加爱好选项爱好可以同时选多个
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
form action/request-demo/req2 methodgetinput typetext nameusernamebrinput typepassword namepasswordbrinput typecheckbox namehobby value1 游泳input typecheckbox namehobby value2 爬山 brinput typesubmit/form
/body
/html2.在Servlet代码中获取页面传递GET请求的参数值
2.1获取GET方式的所有请求参数
/*** request 通用方式获取请求参数*/
WebServlet(/req2)
public class RequestDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//GET请求逻辑System.out.println(get....);//1. 获取所有参数的Map集合MapString, String[] map req.getParameterMap();for (String key : map.keySet()) {// username:zhangsan lisiSystem.out.print(key:);//获取值String[] values map.get(key);for (String value : values) {System.out.print(value );}System.out.println();}}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}获取的结果为 2.2获取GET请求参数中的爱好结果是数组值
/*** request 通用方式获取请求参数*/
WebServlet(/req2)
public class RequestDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//GET请求逻辑//...System.out.println(------------);String[] hobbies req.getParameterValues(hobby);for (String hobby : hobbies) {System.out.println(hobby);}}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}获取的结果为 2.3获取GET请求参数中的用户名和密码结果是单个值
/*** request 通用方式获取请求参数*/
WebServlet(/req2)
public class RequestDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//GET请求逻辑//...String username req.getParameter(username);String password req.getParameter(password);System.out.println(username);System.out.println(password);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}获取的结果为 3.在Servlet代码中获取页面传递POST请求的参数值
3.1将req.html页面form表单的提交方式改成post
3.2将doGet方法中的内容复制到doPost方法中即可
(3)解决post请求乱码问题
html页面
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
form action/httpServletRequestDemo04Servlet methodpostinput typetext nameusernamebr input typesubmit
/form
/body
/html【1】从tomcat8开始以后对于get请求乱码tomcat已经解决。对于post请求中文乱码没有解决需要我们自己处理。
【2】post请求乱码产生的原因和解决思路 说明 1)页面使用的编码表是UTF-8编码tomcat使用的是默认编码表ISO-8859-1进行解码编码和解码使用的编码表不一致导致乱码。 2)解决思路先按照ISO-8859-1编码在按照UTF-8进行重新解码 【3】解决方案
解决方案有三种
方案一
使用URLEncoder类进行编码static String encode (String s,String enc)参数 s编码的字符串enc使用编码表
使用URLDecoder进行解码static Sring decode(String s,String enc)参数s:解码的字符串enc使用编码表方案二
使用String类中的方法进行编码byte[] getBytes(String charsetName)参数表示指定的编码表返回值表示编码后的字
使用String类中的构造方法进行解码String(byte[] bytes,String charsetName)参数bytes字节数组charsetName:表示指定的编码表返回值解码后的字符串
方案三 如果是get请求tomcat8底层已经帮助我们解决完了我们只需要解决post乱码即可但是上述两种方式对于post请求可以解决乱码对于get请求本身获取到的已经是正确的数据处理后又乱码了。我们的想法是get请求不用我们自己书写代码处理乱码只需要我们书写代码处理post乱码。我们接下来学习第三种解决方案只解决来自于请求体数据的乱码。而get请求体没有数据post请求体含有数据所以我们可以理解为第三种处理方案 只是用来解决post乱码的。使用的api是ServletRequest接口中的void setCharacterEncoding(String env)参数指定的编码表注意该方式的代码必须书写在获取请求数据之前【4】代码实现
package com.itheima.sh.web;import com.itheima.sh.pojo.User;
import com.itheima.sh.service.UserServcie;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;WebServlet(/httpServletRequestDemo04Servlet)
public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取浏览器的请求数据
// String username request.getParameter(username);/*解决post乱码问题有三种方式【1】方式一使用URLEncoder类进行编码:static String encode(String s, String enc)参数s:编码的字符串enc:使用编码表使用URLDecoder进行解码static String decode(String s, String enc)参数s:解码的字符串enc:使用编码表*///1)编码 使用URLEncoder类进行编码:static String encode(String s, String enc)
// String encodeUsername URLEncoder.encode(username, ISO-8859-1);
// //2)解码使用URLDecoder进行解码static String decode(String s, String enc)
// username URLDecoder.decode(encodeUsername, UTF-8);/*解决post乱码问题有三种方式【2】方式二使用String类中的方法进行编码 byte[] getBytes(String charsetName)参数表示指定的编码表返回值表示编码后的字节数组使用String类中的构造方法进行解码String(byte[] bytes, String charsetName)参数bytes字节数组charsetName表示指定的编码表返回值解码后的字符串*///1)编码 使用String类中的方法进行编码 byte[] getBytes(String charsetName)
// byte[] bytes username.getBytes(ISO-8859-1);
// //2)解码使用String类中的构造方法进行解码String(byte[] bytes, String charsetName)
// username new String(bytes, UTF-8);//username new String(username.getBytes(ISO-8859-1), UTF-8);/*解决post乱码问题有三种方式【3】方式三如果是get请求tomcat8底层已经帮助我们解决完了我们只需要解决post乱码即可但是上述两种方式对于post请求可以解决乱码对于get请求本身获取到的已经是正确的数据处理后又乱码了。我们的想法是get请求不用我们自己书写代码处理乱码只需要我们书写代码处理post乱码。我们接下来学习第三种解决方案只解决来自于请求体数据的乱码。而get请求体没有数据post请求体含有数据所以我们可以理解为第三种处理方案只是用来解决post乱码的。使用的api是ServletRequest接口中的void setCharacterEncoding(String env)参数指定的编码表注意该方式的代码必须书写在获取请求数据之前*/request.setCharacterEncoding(utf-8);//告知tomcat使用UTF-8解码页面请求数据// 1.获取浏览器的请求数据String username request.getParameter(username);System.out.println(username username);}
}(4)Request请求转发
前后端分离后使用较少面试考
1.请求转发forward一种在服务器内部的资源跳转方法。 (1)浏览器发送请求给服务器服务器中对应的资源A接收到请求
(2)资源A处理完请求后将请求发给资源B
(3)资源B处理完后将结果响应给浏览器
(4)请求从资源A到资源B的过程就叫请求转发
2.请求转发的实现方式
req.getRequestDispatcher(资源B路径).forward(req,resp);
说明1)获取转发器RequestDispatcher dispatcher req.getRequestDispatcher(资源B路径)2)转发RequestDispatcher 表示转发器该接口中有一个方法:forwardrequest,response具体如何来使用我们先来看下需求 针对上述需求具体的实现步骤为
1.创建一个RequestDemo5类接收/req5的请求在doGet方法中打印demo5
2.创建一个RequestDemo6类接收/req6的请求在doGet方法中打印demo6
3.在RequestDemo5的方法中使用req.getRequestDispatcher(/req6).forward(req,resp)进行请求转发4.启动测试(1)创建RequestDemo5类
/*** 请求转发*/
WebServlet(/req5)
public class RequestDemo5 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(demo5...);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(2)创建RequestDemo6类
/*** 请求转发*/
WebServlet(/req6)
public class RequestDemo6 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(demo6...);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(3)在RequestDemo5的doGet方法中进行请求转发
/*** 请求转发*/
WebServlet(/req5)
public class RequestDemo5 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(demo5...);//请求转发request.getRequestDispatcher(/req6).forward(request,response);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(4)启动测试
访问http://localhost:8080/request-demo/req5,就可以在控制台看到如下内容: 说明请求已经转发到了/req6
3.请求转发资源间共享数据使用Request域对象
此处主要解决的问题是把请求从/req5转发到/req6的时候如何传递给/req6
需要使用request对象提供的三个方法
存储数据到request域[范围数据是存储在request对象]中
void setAttribute(String name,Object o);根据key获取值
Object getAttribute(String name);根据key删除该键值对
void removeAttribute(String name);接着上个需求来 1.在RequestDemo5的doGet方法中转发请求之前将数据存入request域对象中2.在RequestDemo6的doGet方法从request域对象中获取数据并将数据打印到控制台3.启动访问测试
(1)修改RequestDemo5中的方法
WebServlet(/req5)
public class RequestDemo5 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(demo5...);//存储数据request.setAttribute(msg,hello);//请求转发request.getRequestDispatcher(/req6).forward(request,response);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(2)修改RequestDemo6中的方法
/*** 请求转发*/
WebServlet(/req6)
public class RequestDemo6 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(demo6...);//获取数据Object msg request.getAttribute(msg);System.out.println(msg);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(3)启动测试
访问http://localhost:8080/request-demo/req5,就可以在控制台看到如下内容: 此时就可以实现在转发多个资源之间共享数据。
4.请求转发的特点 浏览器地址栏路径不发生变化 虽然后台从/req5转发到/req6,但是浏览器的地址一直是/req5,未发生变化 只能转发到当前服务器的内部资源 不能从一个服务器通过转发访问另一台服务器 一次请求可以在转发资源间使用request共享数据 虽然后台从/req5转发到/req6但是这个只有一次请求 问题request.getParameter()
request.getParameter(String name)和request.getAttribute(String name);
区别
1.request.getParameter(String name):获取来自于浏览器的数据 input typetext nameusername value锁哥/request.getParameter(username); 获取的是锁哥2.request.getAttribute(String name)获取的是服务器中的代码request.setAttibute(String name,Object obj);的数据request.setAttribute(msg,黑马程序员);
String msg (String) request.getAttribute(msg);
(5)request的生命周期
1.何时创建
浏览器第一次访问tomcat服务器的时候
2.谁创建
tomcat
3.创建对象做什么
浏览器第一次访问tomcat服务器的是tomcat创建request和response对象传递给servlet中的service方法然后我们可以在servlet中使用request对象调用方法获取请求数据(请求行 头 体)然后处理业务逻辑处理完毕然后tomcat将响应数据给浏览器浏览器接收到响应之后tomcat立刻销毁request和response对象。
3.HTTP响应详解
1使用抓包查看响应报文协议内容
http响应报文协议包括
1.响应行
2.响应头
3.响应体响应数据是服务器响应给浏览器
【1】步骤
1.创建html页面
2.创建servlet
【2】实现
1.创建html页面
!DOCTYPE html
html
headmeta charsetUTF-8titleInsert title here/title
/head
body
h2get请求/h2
form action/getServlet methodget用户名input typetext nameusername valuesuoge / br/密码input typetext namepassword value1234 / br/input typesubmit valueget提交 /
/form
h2post请求/h2
form action/postServlet methodpost用户名input typetext nameusername valuesuoge / br/密码input typetext namepassword value1234 / br/input typesubmit valuepost提交 /
/form
/body
/html2.创建servlet
package com.itheima.sh.a_http_01;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/getServlet)
public class GetServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//响应给浏览器数据response.getWriter().print(get....);}
}
package com.itheima.sh.a_http_01;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/postServlet)
public class PostServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//响应给浏览器数据response.getWriter().print(post....);}
}
【3】抓包结果 小结
1.由于浏览器的原因浏览器会把请求行和响应行信息放在一起
2.get和post请求的响应没有区别
2HTTP响应报文协议介绍
【1】响应行格式协议/版本 状态码
如HTTP/1.1 200
状态码状态码描述说明200OK请求已成功请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。302Move temporarily重定向请求的资源临时从不同的地址响应请求304Not Modified从浏览器缓存中读取数据不从服务器重新获取数据。例如用户第一次从浏览器访问服务器端图片资源以后再访问该图片资源的时候就不会在从服务器上加载而直接到浏览器缓存中加载这样效率更高。404Not Found请求资源不存在。通常是用户路径编写错误也可能是服务器资源已删除。403Forbidden服务器已经理解请求但是拒绝执行它405Method Not Allowed请求行中指定的请求方法不能被用于请求相应的资源500Internal Server Error服务器内部错误通常程序抛异常
【2】响应头
响应头也是用的键值对keyvalue服务器基于响应头通知浏览器的行为。 常见的响应头
响应头Key响应头valuelocation指定响应的路径需要与状态码302配合使用完成重定向content-Type响应正文的类型(MIME类型属于服务器里面的一种类型例如文件在window系统有自己的类型.txt .doc .jpg。文件在服务器中也有自己的类型)同时还可以解决乱码问题。例如text/html;charsetUTF-8content-disposition通过浏览器以附件形式解析正文例如attachmentfilename xx.ziprefresh页面刷新例如3urlwww.itcast.cn //三秒刷新页面到www.itcast.cn
常见的MIME类型就是文件在tomcat服务器中的文件类型 windows tomcat(MIME类型)
超文本标记语言文本 .html text/html ***
xml文档 .xml text/xml
XHTML文档 .xhtml application/xhtmlxml
普通文本 .txt text/plain ***
PDF文档 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG图像 .png image/png **
GIF图形 .gif image/gif
JPEG图形 .jpeg,.jpg image/jpeg **
......【3】响应体
服务器发送给浏览器的数据。当前浏览器向服务器请求的资源是hello.html所以服务器给浏览器响应的数据是一个html页面。
请求资源路径localhost:8080/hello.html
响应结果 如果请求是servlet,那么浏览器的响应体接收到的是servlet响应的数据 4.Response对象 Request使用request对象来获取请求数据Response使用response对象来设置响应数据
Reponse的继承体系和Request的继承体系也非常相似:
HttpServletResponse response new ResponseFacade();多态 1Response设置响应数据功能介绍
HTTP响应数据总共分为三部分内容分别是响应行、响应头、响应体对于这三部分内容的数据respone对象都提供了哪些方法来进行设置?
响应行 对于响应行比较常用的就是设置响应状态码:
void setStatus(int sc);
响应头 设置响应头键值对
void setHeader(String name,String value);
响应头name的值location 指定响应的路径 content-type:告诉浏览器文件格式告诉浏览器不要解析html文件(text/plain)解决中文乱码问题 ************refresh 定时刷新content-disposition 以附件形式展示图片等资源
3.响应体 对于响应体是通过字符、字节输出流的方式往浏览器写
获取字符输出流:
PrintWriter getWriter();
获取字节输出流
ServletOutputStream getOutputStream();
介绍完这些方法后后面我们会通过案例把这些方法都用一用首先先来完成下重定向的功能开发。
(2)Responses请求重定向
Response重定向redirect一种资源跳转方式服务器外部的。 1浏览器发送请求给服务器服务器中对应的资源A接收到请求
2资源A现在无法处理该请求就会给浏览器响应一个302的状态码location的一个访问资源B的路径
3浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B
4资源B接收到请求后进行处理并最终给浏览器响应结果这整个过程就叫重定向
重定向的实现方式
resp.setStatus(302);设置响应状态码是302
resp.setHeader(location,资源B的访问路径);
具体如何来使用我们先来看下需求: 1.创建一个ResponseDemo1类接收/resp1的请求在doGet方法中打印resp1.... 2.创建一个ResponseDemo2类接收/resp2的请求在doGet方法中打印resp2.... 3.在ResponseDemo1的方法中使用 response.setStatus(302); response.setHeader(“Location”,“/request-demo/resp2”) 来给前端响应结果数据 4.启动测试 (1)创建ResponseDemo1类
WebServlet(/resp1)
public class ResponseDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(resp1....);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(2)创建ResponseDemo2类
WebServlet(/resp2)
public class ResponseDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(resp2....);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(3)在ResponseDemo1的doGet方法中给前端响应数据
WebServlet(/resp1)
public class ResponseDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(resp1....);//重定向//1.设置响应状态码 302response.setStatus(302);//2. 设置响应头 Locationresponse.setHeader(Location,/request-demo/resp2);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(4)启动测试
访问http://localhost:8080/request-demo/resp1,就可以在控制台看到如下内容: 说明/resp1和/resp2都被访问到了。到这重定向就已经完成了。
虽然功能已经实现但是从设置重定向的两行代码来看会发现除了重定向的地址不一样其他的内容都是一模一样所以resposne对象给我们提供了简化的编写方式为:
resposne.sendRedirect(/request-demo/resp2)
所以第3步中的代码就可以简化为
WebServlet(/resp1)
public class ResponseDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(resp1....);//重定向resposne.sendRedirect(/request-demo/resp2)}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}重定向的特点: 浏览器地址栏路径发生变化当进行重定向访问的时候由于是由浏览器发送的两次请求所以地址会发生变化 可以重定向到任何位置的资源服务内部、外部均可 因为第一次响应结果中包含了浏览器下次要跳转的路径所以这个路径可以是任意位置资源。 两次请求不能在多个资源使用request共享数据 因为浏览器发送了两次请求是两个不同的request对象就无法通过request对象进行共享数据 以后到底用哪个还是需要根据具体的业务来决定。
# 如果需要在资源之间传递共享request数据,使用请求转发, 否则就用重定向3路径问题
问题1转发的时候路径上没有加/request-demo而重定向加了那么到底什么时候需要加什么时候不需要加呢?
其实判断的依据很简单只需要记住下面的规则即可:
浏览器使用:需要加虚拟目录(项目访问路径)服务端使用:不需要加虚拟目录
对于转发来说因为是在服务端进行的所以不需要加虚拟目录
对于重定向来说路径最终是由浏览器来发送请求就需要添加虚拟目录。
掌握了这个规则接下来就通过一些练习来强化下知识的学习:
a href路劲form action路径req.getRequestDispatcher(“路径”)resp.sendRedirect(“路径”)
答案:
1.超链接从浏览器发送需要加
2.表单从浏览器发送需要加
3.重定向是由浏览器进行跳转需要加。
4.转发是从服务器内部跳转不需要加
4Response响应字符数据
要想将字符数据写回到浏览器我们需要两个步骤:
通过Response对象获取字符输出流 PrintWriter writer resp.getWriter(); 由于获取打印字符流是根据response对象获取的所以向浏览器打印输出通过字符输出流写数据: writer.write(“aaa”);
接下来我们实现通过些案例把响应字符数据给实际应用下:
返回一个简单的字符串aaa
/*** 响应字符数据设置字符数据的响应体*/
WebServlet(/resp3)
public class ResponseDemo3 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType(text/html;charsetutf-8);//1. 获取字符输出流PrintWriter writer response.getWriter();writer.write(aaa);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}返回一串html字符串并且能被浏览器解析
PrintWriter writer response.getWriter();
//content-type告诉浏览器返回的数据类型是HTML类型数据这样浏览器才会解析HTML标签
response.setHeader(content-type,text/html);
writer.write(h1aaa/h1); 注意:一次请求响应结束后response对象就会被销毁掉所以不要手动关闭流。
返回一个中文的字符串你好需要注意设置响应数据的编码为utf-8
//设置响应的数据格式及数据的编码
response.setContentType(text/html;charsetutf-8);
writer.write(你好); 5Response响应字节数据
要想将字节数据写回到浏览器我们需要两个步骤 通过Response对象获取字节输出流 ServletOutputStream outputStream new resp.getOutputStream(); 通过字节输出流写数据outputStream.write(字节数据);
接下来我们实现通过这些案例把响应字节数据给实际应用
1.返回一个图片文件到浏览器
/*** 响应字节数据设置字节数据的响应体*/
WebServlet(/resp4)
public class ResponseDemo4 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 读取文件FileInputStream fis new FileInputStream(D:\\abc\\柳岩.jpg);//2. 获取response字节输出流ServletOutputStream os response.getOutputStream();//3. 完成流的copybyte[] buff new byte[1024];int len 0;while ((len fis.read(buff))! -1){os.write(buff,0,len);}fis.close();}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}上述代码中对于流的copy的代码还是比较复杂的所以我们可以使用别人提供好的方法来简化代码的开发具体步骤是
1pom.xml添加一列
dependencygroupIdcommons-io/groupIdartifactIdcommons-io/artifactIdversion2.6/version
/dependency2调用工具类方法
//fis输入流
//os输出流
IOUtils.copy(fis,os);
优化后的代码
/*** 响应字节数据设置字节数据的响应体*/
WebServlet(/resp4)
public class ResponseDemo4 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1. 读取文件FileInputStream fis new FileInputStream(d://a.jpg);//2. 获取response字节输出流ServletOutputStream os response.getOutputStream();//3. 完成流的copyIOUtils.copy(fis,os);fis.close();}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}十二.Cookie
1.基本使用
1概念
Cookie客户端会话技术将数据保存到客户端以后每次请求都携带Cookie数据进行访问。
2Cookie工作流程 服务端提供了两个Servlet分别是ServletA和ServletB浏览器发送HTTP请求1给服务端服务端ServletA接收请求并进行业务处理服务端ServletA在处理的过程中可以创建一个Cookie对象并将namezs的数据存入Cookie服务端ServletA在响应数据的时候会把Cookie对象响应给浏览器浏览器接收到响应数据会把Cookie对象中的数据存储在浏览器内存中此时浏览器和服务端就建立了一次会话在同一次会话中浏览器再次发送HTTP请求2给服务端ServletB浏览器会携带Cookie对象中的所有数据ServletB接收到请求和数据后就可以获取到存储在Cookie对象中的数据这样同一个会话中的多次请求之间就实现了数据共享**注意**cookie是创建在服务器端存在浏览器端好处减轻服务器压力但是不安全
3Cookie的基本使用
对于Cookie的使用我们更关注的应该是后台代码如何操作Cookie对于Cookie的操作主要分两大类分别是发送Cookie和获取Cookie对于上面这两块内容分别该如何实现呢
3.1发送Cookie
创建Cookie对象并设置数据
CookieString name,String value
Cookie cookie new Cookie(key,value);
发送Cookie到客户端使用response对象
response.addCookie(cookie);
介绍完发送Cookie对应的步骤后接下来通过一个案例来完成Cookie的发送具体实验步骤为
需求在Servlet中生成Cookie对象并存入数据然后将数据发送给浏览器
1.创建Maven项目项目名称为cookie-demo并在pom.xml添加依赖
2.编写Servlet类名称为AServlet
3.在AServlet中创建Cookie对象存入数据发送给前端
4.启动测试在浏览器查看Cookie对象中的值
(1)创建Maven项目cookie-demo并在pom.xml添加依赖
propertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target
/propertiesdependencies!--servlet--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependency
/dependencies(2)编写Servlet类名称为AServlet
WebServlet(/aServlet)
public class AServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(3)在Servlet中创建Cookie对象存入数据发送给前端
WebServlet(/aServlet)
public class AServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//发送Cookie//1. 创建Cookie对象Cookie cookie new Cookie(username,zs);//2. 发送Cookieresponseresponse.addCookie(cookie);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}4启动测试在浏览器查看Cookie对象中的值
访问http://localhost:8080/cookie-demo/aServlet
chrome浏览器查看Cookie的值有两种方式,分布式:
方式一 方式二选中打开开发者工具或者 使用快捷键F12或者 CtrlShiftI 3.2获取Cookie
获取客户端携带的所有Cookie使用request对象
Cookie[] cookies request.getCookies();
遍历数组获取每一个Cookie对象for使用Cookie对象方法获取数据Cookie(String name,String value)
cookie.getName(); 获取Cookie类构造方法的第一个参数 name
cookie.getValue(); 获取Cookie类构造方法的第二个参数 value
介绍完获取Cookie对应的步骤后接下来在通过一个案例来完成Cookie的获取具体实现步骤为
需求在Servlet中获取前一个案例存入在Cookie对象中的数据
1.编写一个新Servlet类名称为BServlet
2.在BServlet中使用request对象获取Cookie数组遍历数组
从数据中获取指定名称对应的值
3.启动测试在控制台打印出获取的值
(1)编写一个新Servlet类名称为BServlet
WebServlet(/bServlet)
public class BServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}2在BServlet中使用request对象获取Cookie数组遍历数组从数据中获取指定名称对应的值
WebServlet(/bServlet)
public class BServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取Cookie//1. 获取Cookie数组Cookie[] cookies request.getCookies();//2. 遍历数组for (Cookie cookie : cookies) {//3. 获取数据String name cookie.getName();if(username.equals(name)){String value cookie.getValue();System.out.println(name:value);break;}}}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}3启动测试在控制台打印出获取的值
访问http://localhost:8080/cookie-demo/bServlet 在IDEA控制台就能看到输出的结果 2.Cookie的原理分析
对于Cookie的实现原理是基于HTTP协议的其中涉及到HTTP协议中的两个头信息
响应头set-cookie请求头cookie 前面的案例中已经能够实现AServlet给前端发送CookieBServlet从request中获取Cookie的功能 对于AServlet响应数据的时候Tomcat服务器都是基于HTTP协议来响应数据 当Tomcat发现后端要返回的是一个Cookie对象之后Tomcat就会在响应头中添加一行数据 Set-Cookieusernamezs 浏览器获取到响应结果后从响应头中就可以获取到Set-Cookie对应值 usernameszs,并将数据存储在浏览器的内存中 浏览器再次发送请求给BServlet的时候浏览器会自动在请求头中添加Cookieusernameszs发送给服务端BServlet Request对象会把请求头中cookie对应的值封装成一个个Cookie对象最终形成一个数组 BServlet通过Request对象获取到Cookie[]后就可以从中获取自己需要的数据
接下来使用刚才的案例把上述结论验证下:
(1)访问AServlet对应的地址http://localhost:8080/cookie-demo/aServlet
使用Chrom浏览器打开开发者工具(F12或CrtlShiftI)进行查看响应头中的数据 2访问BServlet对应的地址http://localhost:8080/cookie-demo/bServlet
使用Chrom浏览器打开开发者工具(F12或CrtlShiftI)进行查看请求头中的数据 3.Cookie的使用细节
1Cookie的存活时间
cookie 有两种
1.会话级别的cookie会话结束那么cookie消失
2.持久化级别的cookie当前会话结束cookie并没有消失而是保存
下次访问同一个服务器cookie数据依然存在
问题在访问AServlet和BServlet的中间把关闭浏览器,重启浏览器后访问BServlet能否获取到Cookie中的数据? (1)浏览器发送请求给AServletAServlet会响应一个存有usernamezs的Cookie对象给浏览器
(2)浏览器接收到响应数据将cookie存入到浏览器内存中
(3)当浏览器再次发送请求BServletBServlet就可以使用Request对象获取到Cookie数据
(4)在发送请求到BServlet之前如果把浏览器关闭在打开进行访问BServlet能否获取到Cookie数据
针对上面这个问题通过演示会发现BServlet中无法在获取到Cookie数据这是为什么呢
默认情况下Cookie存储在浏览器内存中当浏览器关闭内存释放则Cookie被销毁
这个结论就印证了上面的演示效果但是如果使用这种默认情况下的Cookie有些需求就无法实现比如 上面这个网站的登录页面上有一个记住我的功能这个功能大家都比较熟悉
第一次输入用户名和密码并勾选记住我然后进行登录下次再登陆的时候用户名和密码就会被自动填充不需要再重新输入登录比如记住我这个功能需要记住用户名和密码一个星期那么使用默认情况下的Cookie就会出现问题因为默认情况浏览器一关Cookie就会从浏览器内存中删除对于记住我功能就无法实现
所以我们现在就遇到一个难题是如何将Cookie持久化存储?
Cookie其实已经为我们提供好了对应的API来完成这件事这个API就是setMaxAge,
设置Cookie存活时间
setMaxAge(int seconds)
参数值为
1.正数将Cookie写入浏览器所在电脑的硬盘持久化存储。到时间自动删除
2.负数默认值Cookie在当前浏览器内存中当浏览器关闭则Cookie被销毁
3.零删除对应Cookie
接下来咱们就在AServlet中设置Cookie的存活时间。
WebServlet(/aServlet)
public class AServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//发送Cookie//1. 创建Cookie对象Cookie cookie new Cookie(username,zs);//设置存活时间 1周 7天cookie.setMaxAge(60*60*24*7); //易阅读需程序计算//cookie.setMaxAge(604800); //不易阅读(可以使用注解弥补)程序少进行一次计算//2. 发送Cookieresponseresponse.addCookie(cookie);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}修改完代码后启动测试访问http://localhost:8080/cookie-demo/aServlet
访问一个AServlet后把浏览器关闭重启后再去访问http://localhost:8080/cookie-demo/bServet,能在控制台打印出username:zs,说明Cookie没有随着浏览器关闭而被销毁通过浏览器查看Cookie的内容会发现Cookie的相关信息 2关于cookie中存储特殊字符问题
如果直接向cookie中存储特殊字符例如空格分号( ; ) , 逗号(,)等特殊字符。那么就会出现问题。在向cookie中存储特殊字符之前必须要先进行编码处理然后从cookie中取出之后再进行解码处理
【1】向cookie中存储特殊字符问题演示
package com.itheima.sh.b_cookie_02;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/specialCookie01Servlet)
public class SpecialCookie01Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {/*向cookie中存储特殊字符问题演示*///1.创建Cookie类的对象Cookie cookie new Cookie(msg, 12 34);//2.将cookie存储到浏览器端response.addCookie(cookie);}
} 【2】解决向cookie中存储特殊字符的问题
方案在向cookie中存储特殊字符前进行编码然后取出之后需要解码。
【2】解决向cookie中存储特殊字符的问题
方案在向cookie中存储特殊字符前进行编码然后取出之后需要解码。
package com.itheima.sh.b_cookie_02;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;WebServlet(/specialCookie01Servlet)
public class SpecialCookie01Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {/*向cookie中存储特殊字符问题演示*///1.创建Cookie类的对象
// Cookie cookie new Cookie(msg, 12 34);报错String str 12 34;//编码String encode URLEncoder.encode(str, utf-8);Cookie cookie new Cookie(msg, encode);//2.将cookie存储到浏览器端response.addCookie(cookie);}
}
package com.itheima.sh.b_cookie_02;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;WebServlet(/specialCookie02Servlet)
public class SpecialCookie02Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取浏览器的cookieCookie[] cookies request.getCookies();//2.遍历cookie数组for (Cookie cookie : cookies) {//3.取出cookie的nameString cookieName cookie.getName();//4.判断cookieName的值是否是msgif(msg.equals(cookieName)){//5.取出valueString value cookie.getValue();//6.解码并输出String decode URLDecoder.decode(value, utf-8);System.out.println(decode);}}}
}
内容小结
1.cookie中不能直接存储特殊字符空格 分号等如果存储必须先编码在存储
String encode URLEncoder.encode(str,utf-8);2.在获取的时候需要解码
String decode URLDecoder.decode(value,utf-8);十三.Session
1.基本使用
【1】概念
Session:服务端会话跟踪技术将数据保存到服务端
Session是存储在服务端而Cookie是存储在客户端存储在客户端的数据容易被窃取和截获存在很多不安全因素存储在服务端的数据相比于客户端来说就更安全
【2】Session的工作流程 在服务端的AServlet获取一个Session对象把数据存入其中。在服务端的BServlet获取到相同的Session对象从中取出数据。就可以实现一次会话中多次请求之间的数据共享了现在最大的问题是如何保证AServlet和BServlet使用的是同一个Session对象在原理分析会讲解
【3】Session的基本使用
在JavaEE中提供了HttpSession接口来实现一次会话的多次请求之间数据共享功能。
具体的使用步骤为
获取Session对象使用的是request对象
//如果是第一次执行那么就是创建session对象如果不是第一次执行就是获取session
HttpSession session request.getSession();
///参数是true用法和无参用法一样的
//如果参数是false表示如果存在session就获取session不存在则返回null;
HttpSession getSession(boolean create) ; Session对象提供的功能session也是域对象使用范围比request大只要在一次会话过程中多次请求都可以共享session中的数据。 存储数据到session域中 void setAttribute(String name,Object o)根据key获取值 Object getAttribute(String name) 根据key删除该键值对 void removeAttribute(String name)介绍完Session相关的API后接下来通过一个案例来完成对Session的使用具体实现步骤为
需求在一个Servlet中往Session中存入数据在另一个Servlet中获取Session中
获取数据1.创建名为SessionDemo1的Servlet类
2.创建名为SessionDemo2的Servlet类
3.在SessionDemo1的方法中获取Session对象、存储数据
4.在SessionDemo2的方法中获取Session对象、获取数据
5.启动测试
(1)创建名为SessionDemo1的Servlet类
WebServlet(/demo1)
public class SessionDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(2)创建名为SessionDemo2的Servlet类
WebServlet(/demo2)
public class SessionDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(3)SessionDemo1:获取Session对象、存储数据
WebServlet(/demo1)
public class SessionDemo1 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//存储到Session中//1. 获取Session对象HttpSession session request.getSession();//2. 存储数据session.setAttribute(username,zs);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(4)SessionDemo2:获取Session对象、获取数据
WebServlet(/demo2)
public class SessionDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取数据从session中//1. 获取Session对象HttpSession session request.getSession();//2. 获取数据Object username session.getAttribute(username);System.out.println(username);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}(5)启动测试
先访问http://localhost:8080/cookie-demo/demo1,将数据存入Session在访问http://localhost:8080/cookie-demo/demo2,从Session中获取数据查看控制台
2.Session的原理分析 内容
用户第一次访问的时候tomcat会创建对应的session容器每个容器具有唯一的标识JSESSIONID然后tomcat底层创建会话界别的cookie存储唯一标识JSESSIONID存储到浏览器端。用户再次访问tomcat中取出session并从cookie中取出之前保存的唯一标识JSESSIONID进行比较查找自己的session容器。注意Session是基于Cookie来实现的session和浏览器没有任何关系存在服务器端的。
3.Session的使用细节
【1】浏览器关闭后session持久化方案
tomcat在创建cookie的时候属于会话级别的cookie关闭浏览器cookie消失下次打开浏览器不会携带之前的cookie即cookie中的JSESSIONID到tomcat服务器中那么这样会造成tomcat服务器中会有很多个不能使用的session容器。session依然还在只是找不到了。严重的话会造成服务宕机。
package com.itheima.sh.e_session_05;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;WebServlet(/sessionPersis01Servlet)
public class SessionPersis01Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取sessionHttpSession session request.getSession();System.out.println(session.getId());}
}
持久化session步骤
创建session获取session的JSESSIONID的值创建CookieCookie(“JSESSIONID”,值)使用cookie对象调用方法setMaxAge()进行cookie的持久化存活时间建议30min将cookie响应给浏览器
package com.itheima.sh.e_session_05;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;WebServlet(/sessionPersis01Servlet)
public class SessionPersis01Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.创建sessionHttpSession session request.getSession();//2.获取session的JSESSIOID的值String sessionId session.getId();System.out.println(sessionId);//3.创建Cookie ,Cookie(JSESSIOID,值)Cookie cookie new Cookie(JSESSIONID, sessionId);//4.使用cookie对象调用方法setMaxAge()进行cookie的持久化存活时间建议30mincookie.setMaxAge(60*30);//5.将cookie响应给浏览器response.addCookie(cookie);}
}【2】Session钝化和活化
由于钝化和活化的原理是序列化和反序列化所以要求存储在session容器中的对象所属类必须实现序列化接口Serializable
演示
代码
package com.itheima.sh.b_session_02;import java.io.Serializable;public class Product implements Serializable {//成员变量private String pname;private double price;public Product(String pname, double price) {this.pname pname;this.price price;}public String getPname() {return pname;}public void setPname(String pname) {this.pname pname;}public double getPrice() {return price;}public void setPrice(double price) {this.price price;}Overridepublic String toString() {return Product{ pname pname \ , price price };}
}
package com.itheima.sh.f_session_06;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;WebServlet(/setSessionServlet)
public class SetSessionServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType(text/html;charsetutf-8);//1.创建sessionHttpSession session request.getSession();//2.获取session的idString sessionId session.getId();//3.创建商品对象Product p new Product(笔记本, 9999);//4.将商品对象存储到session中session.setAttribute(p,p);//5.响应数据response.getWriter().print(setSessionServlet.....当前JSESSIONIDsessionId);}
}
package com.itheima.sh.f_session_06;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;WebServlet(/getSessionServlet)
public class GetSessionServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType(text/html;charsetutf-8);//1.获取sessionHttpSession session request.getSession();//2.获取session的idString sessionId session.getId();//3.从session中取出商品Product p (Product) session.getAttribute(p);//4.响应数据response.getWriter().print(getSessionServlet.....当前JSESSIONIDsessionId,pp.toString());}
}
打war包 将上述生成的war包复制到tomcat的webapps目录下 到tomcat的bin目录下启动tomcat 注意这儿启动一定将idea中的tomcat关闭
在浏览器中访问servlet 正常关闭tomcat:bin目录下面的shutdown.bat
在如下目录生成session的钝化文件 正常启动tomcat
钝化文件就会被加载到内存文件自动消失
【3】Session销毁
两种方式
默认情况下无操作30分钟自动销毁
对于这个失效时间是可以通过配置进行修改的
在项目的web.xml中配置
?xml version1.0 encodingUTF-8?
web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsdversion3.1session-configsession-timeout10/session-timeout/session-config
/web-app如果没有配置默认是30分钟默认值是在Tomcat的web.xml配置文件中写死的 调用Session对象的invalidate()进行销毁
在SessionDemo2类中添加session销毁的方法
WebServlet(/demo2)
public class SessionDemo2 extends HttpServlet {Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取数据从session中//1. 获取Session对象HttpSession session request.getSession();System.out.println(session);// 销毁session.invalidate();//2. 获取数据Object username session.getAttribute(username);System.out.println(username);}Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}启动访问测试先访问demo1将数据存入到session再次访问demo2从session中获取数据 Cookie和Session小结
相同都是完成一次会话内多次请求间数据共享的。区别 存储位置Cookie是将数据存储在客户端Session将数据存储在服务端安全性Cookie不安全Session安全数据大小Cookie最大3KBSession无大小限制存储时间Cookie可以通过setMaxAge()长期存储Session默认30分钟服务器性能Cookie不占服务器资源Session占用服务器资源
十四.Filter
1.概述
Filter表示过滤器属于javax.servlet.Filter接口类型过滤器可以对访问的静态和动态资源进行过滤既可以过滤请求也可以 过滤响应。 2.入门案例
1.定义类实现javax.servlet.Filter接口
2.在实现类中实现该接口中的所有抽象方法
3.在doFilter方法中书写过滤资源的代码
4.在web.xml中配置过滤器
5.访问
package com.itheima.sh.a_filter_01;import javax.servlet.*;
import java.io.IOException;//1.自定义过滤器类实现过滤器接口Filter
public class MyFilter implements Filter {//2.在自定义类中实现过滤器接口Filter中的所有抽象方法Overridepublic void init(FilterConfig filterConfig) throws ServletException {//不要调用父的方法否则报错
// Filter.super.init(filterConfig);}//3.在doFilter方法体中书写拦截资源的代码//每次访问被过滤的资源都要执行该方法Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println(doFilter。。。。);//放行 可以访问被过滤的资源chain.doFilter(request, response);}Overridepublic void destroy() {
// Filter.super.destroy();}
}
?xml version1.0 encodingUTF-8?
web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsdversion4.0!-- 4.配置过滤器 --filterfilter-nameMyFilter/filter-namefilter-classcom.itheima.sh.a_filter_01.MyFilter/filter-class/filterfilter-mappingfilter-nameMyFilter/filter-name!--配置的是当前过滤器过滤的资源路径,表示MyFilter过滤器过滤demo01.html的请求响应--url-pattern/demo01.html/url-pattern/filter-mapping
/web-app3.关于入门案例的补充
1.Filter接口中的doFilter方法的第三个参数
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println(doFilter。。。。);//放行 可以访问被过滤的资源chain.doFilter(request, response);}FilterChain是一个接口 抽象方法
void doFilter(ServletRequest request, ServletResponse response) 注意如果可以访问过滤资源则书写过滤器链对象.doFilter();
如果不可以访问过滤资源则不书写过滤器链对象.doFilter();
4.注解开发
作用简化代码开发
作用简化代码开发
package com.itheima.sh.a_filter_01;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;//1.自定义过滤器类实现过滤器接口Filter
/*TODO:1.String[] urlPatterns() default {}; 相当于 url-pattern/demo01.html/url-pattern2.String[] value() default {}; 等同于 urlPatterns属性诞生value属性的目的简化开发就是省略value属性*/
//WebFilter(urlPatterns {/demo01.html})
//WebFilter(urlPatterns /demo01.html)
//WebFilter(value /demo01.html)
WebFilter(/demo01.html)
public class MyFilter implements Filter {//2.在自定义类中实现过滤器接口Filter中的所有抽象方法Overridepublic void init(FilterConfig filterConfig) throws ServletException {//不要调用父的方法否则报错
// Filter.super.init(filterConfig);}//3.在doFilter方法体中书写拦截资源的代码//每次访问被过滤的资源都要执行该方法Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println(doFilter。。。。);//放行 可以访问被过滤的资源chain.doFilter(request, response);}Overridepublic void destroy() {
// Filter.super.destroy();}
}
5.在idea中配置filter的模板 package com.itheima.sh.a_filter_01;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebFilter(/demo01.html)
public class My2Filter implements Filter {Overridepublic void destroy() {}Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {HttpServletRequest request (HttpServletRequest) req;HttpServletResponse response (HttpServletResponse) resp;//your code....System.out.println(注解开发简单);chain.doFilter(request, response);}Overridepublic void init(FilterConfig config) throws ServletException {}}
6.Filter的生命周期 掌握
Filter过滤器的生命周期 1.当启动tomcat服务器的时候tomcat调用过滤器类的无参构造方法创建过滤器类的对象 2.然后使用过滤器类的对象调用init方法进行初始化 3.每次访问被过滤的资源都要执行doFilter方法 ******** 实际开发中我们在doFilter方法处理被过滤的资源逻辑 4.关闭tomcat服务器之前使用过滤器对象调用destroy方法
package com.itheima.sh.a_filter_01;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*TODO:Filter过滤器的生命周期1.当启动tomcat服务器的时候tomcat调用过滤器类的无参构造方法创建过滤器类的对象2.然后使用过滤器类的对象调用init方法进行初始化3.每次访问被过滤的资源都要执行doFilter方法 ******** 实际开发中我们在doFilter方法处理被过滤的资源逻辑4.关闭tomcat服务器之前使用过滤器对象调用destroy方法*/
WebFilter(/demo02.html)
public class LifeDemo01Filter implements Filter {//无参构造方法public LifeDemo01Filter() {System.out.println(无参构造方法。。。。。);}Overridepublic void destroy() {System.out.println(destroy。。。。。);}Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {HttpServletRequest request (HttpServletRequest) req;HttpServletResponse response (HttpServletResponse) resp;//your code....System.out.println(doFilter。。。。。);chain.doFilter(request, response);}Overridepublic void init(FilterConfig config) throws ServletException {System.out.println(init。。。。。);}}
7.拦截路径(重点)
过滤器的过滤资源路径 1.精确匹配 /demo03.html 这里必须加/ 2.目录匹配 /xx/* 只要浏览器访问的路径以xx开始就会执行当前过滤器 3.后缀名匹配.xx 只要浏览器访问的路径以xx结尾就会执行当前过滤器注意这里不能加/ 4.拦截所有 / 只要浏览器访问当前项目就会执行当前过滤器 ************* 注意在过滤器中如果多个过滤器过滤器同一个资源那么要执行所有的满足条件的过滤器
8.过滤器链 掌握
就是多个过滤器过滤器同一个资源形成的一条链子。
小结
1.前提条件多个过滤器在同一包下过滤器统一资源才有如下规律(注解开发)
执行顺序按照过滤器类的字母升序执行。
2.如果是xml配置方式多个过滤器过滤统一资源按照在xml中出现的顺序执行
9.Filter案例
1解决全站乱码问题
以前我们都是在每个servlet中书写处理请求和响应的乱码diam这样代码冗余。
以后我们将处理请求和响应的乱码的代码书写在过滤器中即可。
以后我们将处理请求和响应的乱码的代码书写在过滤器中即可。
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
form action/demo01Servlet methodpostinput typetext nameusernamebrinput typesubmit
/form
/body
/htmlpackage com.itheima.sh.c_filter_test_03;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// /* 表示拦截所有资源
WebFilter(/*)
public class EncodingFilter implements Filter {Overridepublic void destroy() {}Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {HttpServletRequest request (HttpServletRequest) req;HttpServletResponse response (HttpServletResponse) resp;//your code....//处理请求乱码request.setCharacterEncoding(utf-8);//处理响应乱码response.setContentType(text/html;charsetutf-8);chain.doFilter(request, response);}Overridepublic void init(FilterConfig config) throws ServletException {}}
package com.itheima.sh.c_filter_test_03;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/demo01Servlet)
public class Demo01Servlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取请求参数String username request.getParameter(username);System.out.println(username username);//2.响应给浏览器response.getWriter().print(黑马程序员);}
}
2过滤器案例–登录权限校验
hack.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
h1黑客。。/h1
a hrefjavascript:;下载黑客资源/a
/body
/htmllogin.html
!DOCTYPE html
html langen
headmeta charsetUTF-8title登录/title
/head
body
form action/loginServlet methodpost用户名input typetext namenamebr密码input typepassword namepasswordbrinput typesubmit value登录
/form
/body
/htmlLoginServlet
package com.itheima.sh.c_filter_test_03;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/loginServlet)
public class LoginServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//1.获取请求参数String name request.getParameter(name);String password request.getParameter(password);//2.创建User对象User user new User();//3.封装数据user.setName(name);user.setPassword(password);//TODO:实际开发中将user对象传递到业务层到数据库查询数据//4.这里假设输入的用户名和密码就是正确的将user对象放到sessionrequest.getSession().setAttribute(u,user);//5.跳转到hack.html页面response.sendRedirect(/hack.html);}
}
过滤器LoginFilter
package com.itheima.sh.c_filter_test_03;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// 当前过滤器过滤的是/hack.html
WebFilter(/hack.html)
public class LoginFilter implements Filter {Overridepublic void destroy() {}Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {HttpServletRequest request (HttpServletRequest) req;HttpServletResponse response (HttpServletResponse) resp;//your code....//1.从session中获User对象 request.getSession().setAttribute(u,user);User u (User) request.getSession().getAttribute(u);//2.判断u是否等于nullif(u null){//3.说明没有登录跳转到登录页面response.sendRedirect(/login.html);}else{//4.说明登录了放行可以访问被过滤的资源hack.html页面chain.doFilter(request, response);}}Overridepublic void init(FilterConfig config) throws ServletException {}}
十五.ServletContext
ServletContext表示上下文对象属于接口代表整个web项目可以使用方法获取当前web项目的所有文件的MIME类型
之前学习能够共享数据的对象
request只能在一次请求一次响应中进行数据的共享—》请求转发session只能在一次会话过程中可以有多次请求和响应servletContext只要项目存在就可以共享数据多次会话多次请求和响应都可以共享数据操作整个项目的配置文件
范围大小ServletContext session request
(1)ServletContext对象介绍
当tomcat服务器启动的时候会为每个web项目创建一个唯一的ServletContext对象该对象代表当前整个web应用项目。该对象不仅封装了当前web应用的所有信息而且实现了多个servlet的数据共享。在ServletContext中可以存放共享数据ServletContext对象是真正的一个全局对象凡是web容器中的Servlet都可以访问。
在每个项目中可以有多个Servlet程序每个Servlet程序都是独立的。当前这个项目的配置信息就必须使用描述这个项目的ServletContext对象获取。
方法名描述setAttribute(String name,Object object)向ServletContext中存数据getAttribute(String name)从ServletContext中取数据removeAttribute(name)从ServletContext中移除数据String getRealPath(String path)返回资源文件在服务器文件系统上的真实路径(文件的绝对路径)getMimeType(fileName)获取服务器中文件类型.txt text/plain .html text/html
ServletContext对象tomcat为每一个web项目单独创建一个上下文对象。有如下功能
1.可以在多个servlet之间共享数据
存放setAttribute()
获得getAttribute()
删除removeAttribute()
2.可以获得当前WEB项目中的指定资源文件
String path getRealPath( String string);
需求1如何获取上下文servletContext对象。
使用HttpServlet类的父类 GenericServlet 中的方法:getServletContext();代码如下
/*获取上下文ServletContext对象使用HttpServlet类的父类 GenericServlet 中的方法:getServletContext();*/
WebServlet(/servletContextDemoServlet)
public class ServletContextDemoServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取ServletContext类的对象ServletContext servletContext getServletContext();}
}需求2如何获取服务器中每个文件的路径。例如在当前项目下的web文件夹下放一个1.jpg的图片获取其真实路径(绝对路径)。
WebServlet(/servletContextDemoServlet)
public class ServletContextDemoServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ServletContext servletContext getServletContext();//如何获取服务器中每个文件的路径。// 例如在当前项目下的web文件夹下放一个1.jpg的图片获取其真实路径(绝对路径)。String realPath servletContext.getRealPath(/1.jpg);/*输出结果realPath F:\ideawork\jiuyeban2\heima60\heima03\out\artifacts\web_war_exploded\1.jpg说明我们的项目在发布的时候会被打成一个war包这个war包下的class文件会被放在tomcat下被运行。所以这里获取的真实路径是这个war包下的1.jpg所在的路径。*/System.out.println(realPath realPath);}
}说明
获取结果
realPath F:\ideawork\jiuyeban2\heima60\heima03\out\artifacts\web_war_exploded\1.jpg
说明我们的项目在发布的时候会被打成一个war包这个war包下的class文件会被放在tomcat下被运行。所以这里获取的真实路径是这个war包下的1.jpg所在的路径。需求3获取当前项目下的1.jpg在服务器中的文件类型。
/*需求3获取当前项目下的1.jpg在服务器中的文件类型。getMimeType(1.jpg);这里书写获取文件类型的文件名和后缀名即可*/String mimeType servletContext.getMimeType(1.jpg);System.out.println(mimeType mimeType);//mimeType image/jpeg注意对于方法 getMimeType(“1.jpg”);这里书写获取文件类型的文件名和后缀名即可
总结
1.ServletContext表示上下文对象代表整个web项目tomcat一启动就会创建该接口对象关闭tomcat就会消失。
2.ServletContext属于对象多次会话多次请求限制三个域对象范围ServletContext HttpSession HttpServletRequest
十六.Listener
1.说明
javaweb中的监听器是监听ServletContext、HttpSession、HttpServletRequest三个对象创建和销毁的同时监听是哪个对象中数据的变化就是监听属性的变化setAttribute、removeAttribute。
ServletContext 是在tomcat启动创建关闭tomcat销毁HttpSession 是在浏览器第一次访问执行request.getSession()创建销毁时间130min 2执行invalidate()HttpServletRequest是浏览器第一次访问创建浏览器接收到服务器的响应就销毁
2.监听器的接口分类
事件源监听器接口时机ServletContextServletContextListener上下文域创建和销毁ServletContextServletContextAttributeListener上下文域属性增删改的操作**HttpSession **HttpSessionListener会话域创建和销毁**HttpSession **HttpSessionAttributeListener会话域属性增删改的操作HttpServletRequestServletRequestListener请求域创建和销毁HttpServletRequestServletRequestAttributeListener请求域属性增删改的操作
3.快速入门简单案例
步骤
1. 创建一个普通类实现ServletContextListenner2. 重写方法监听ServletContext创建监听ServletContext销毁3. 配置web.xml注解 掌握① xml版本
package com.itheima04;import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;/*设置监听器的人: 开发者监听器 : MyListener监听器目标 : ServletContext 对象监听器的工作:1). 当ServletContext 对象创建的时候就会执行contextInitialized方法ServletContext是tomcat启动时就会创建 (早于Filter和Servlet)2). 当ServletContext 对象销毁的时候就会执行contextDestroyed方法ServletContext是tomcat关闭时销毁 (晚于Filter和Servlet)这两个方法是事件驱动*/
public class MyListener implements ServletContextListener {//tomcat一启动,此方法就会运行//运用场景: spring底层封装了一个ServletContextListener加载配置文件Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println(contextInitialized);}Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println(contextDestroyed);}
}
listenerlistener-classcom.itheima08.MyServletContextListener/listener-class/listener② 注解版本
WebListener
public class MyListener implements ServletContextListener {//tomcat一启动,此方法就会运行//运用场景: spring底层封装了一个ServletContextListener加载配置文件Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println(contextInitialized);}Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println(contextDestroyed);}
}
4.模拟spring框架
需求可以在项目启动时读取配置文件。获取配置文件的名字。
步骤
1.在web.xml进行配置文件的配置
2.创建自定义监听器类监听ServletContext的创建和销毁
3.在自定义监听器类中实现监听器的方法
4.实现的方法体中读取web.xml文件中关于当前项目配置文件的信息
5.输出结果
package com.itheima.sh.h_listener_08;import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;//2.创建自定义监听器类监听ServletContext的创建和销毁
//别忘记注册监听器
WebListener
public class SpringContextListener implements ServletContextListener{//3.在自定义监听器类中实现监听器的抽象方法Overridepublic void contextInitialized(ServletContextEvent servletContextEvent) {//4.实现的方法体中读取web.xml文件中关于当前项目配置文件的信息//4.1根据事件类对象servletContextEvent调用方法获取ServletContext上下文对象ServletContext servletContext servletContextEvent.getServletContext();//4.2使用上下文对象调用方法获取web.xml配置文件中的数据/*context-paramparam-namejdbc/param-nameparam-valuejdbc.properties/param-value/context-param*/String str servletContext.getInitParameter(jdbc);System.out.println(str str);}Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println(释放资源....销毁。。。。);}
} !--配置当前项目的配置文件信息--!--1.在web.xml进行配置文件的配置--context-paramparam-namejdbc/param-nameparam-valuejdbc.properties/param-value/context-param十七.git
1.git概述 工作区
平时存放项目代码的地方
一个文件夹通过git init设置成一个git可以管理的文件夹时这个文件夹里的内容除去.git文件夹就是工作区。 仓库区或版本库
安全存放数据的位置这里面有提交到所有版本的数据。其中HEAD指向指向最新放入仓库的版本。工作区有一个隐藏目录 .git它不算工作区而是Git的版本库 暂存区stage或index 用来暂时存放工作区中修改的内容可以理解为一个中转站。. 位置一般存放在 .git 目录下的 index 文件.git/index中所有我们把暂存区有时也叫做索引index。只是一个文件包含在版本库中为什么需要暂存区 如果没有暂存区想要提交文件就需要一个个修改然后提交比较麻烦但是有了暂存区就可以一次性将所需要的文件从暂存区直接修改后提交。如果没有暂存区修改的文件只可以立刻保存到版本库中但是这样很容易对别人的工作造成影响 Head指向最新放入仓库的版本 master 主分支当 git init 后并不会立刻产生分支而是添加了一个文件并git addgit commit 后才会看到master分支是本地仓库一部分。 objects 是git对象库用来存储各种创建的对象以及内容。 远程仓库 托管代码的服务器常用github、gitee、gitlab
2.git作用
代码共享
每位开发者可以使用Git将自己的代码上传到云服务器上同时使用Git还可以将其他人上传的代码下载到自己的电脑上。 回溯版本 追踪信息 【面试题】
Git与SVN的区别
Git是分布式的SVN不是Git把内容按元数据修饰数据的数据方式存储而SVN是按文件Git分支和SVN的分支不同Git没有一个全局的版本号而SVN有Git的内容完整性优于SVN
3.git下载与安装
下载地址https://git-scm.com/download 安装过程非常简单各种下一步各种Next。 点击Finish完成安装验证安装找一个桌面空白处右键出现下列窗口 点击后出现Git的控制台在控制台输入git可以看到相关的帮助信息 4.git本地操作
初始化工作区 命令:git init 初始化
在要被初始化工作区的目录右键选择Git Bash Here 在文件夹中机会出现一个隐藏文件.git如图 当我们在learn-Git文件夹中添加文件的时候那么这个文件就会被Git所管理
查看状态
我们在learn-git目录中创建一个readme.txt文件并使用vim命令进入编辑模式添加内容:第一行代码。可以通过命令来查看它的状态
命令:git status 查看状态 红色代表当前没有提交到缓存区
5.git本地操作-add与commit 工作区提交到暂存区
命令:git add readme.txt 这是完成了将文件由工作区提交暂存区
我们通过git status来查看状态 发现这时文件变成绿色可以提交到本地仓库
暂存取提交到本地仓库
命令:git commit -m 第一次提交
说明:-m 后面跟随的是为你提交的备注,m是单词message信息的首字母提交信息格式增删改查第几次提交注意如果第一次提交需要填写如下内容
命令:git config --global user.email 123456qq.com
说明:指定邮箱
命令:git config --global user.name suoge
说明:指定操作者扩展
添加多个文件 git add [file1] [file2] ...
添加指定目录到暂存区包括子目录 git add [dir]
添加当前目录下的所有文件到暂存区不包括被删除的文件 git add .
add 时一个个文件加比较麻烦
可以用下面的命令将所有变动的文件同步至暂存区新增、修改、删除
git add -A
下面的命令是将所有修改和删除的文件同步至暂存区不包括新增文件
git add -u6.git本地操作-差异比较
使用vim命令对readme.txt文件进行编辑添加我是第二行代码使用:wq退出 工作区、暂存区比较
命令:git diff readme.txt 工作区、本地库比较
命令:git diff HEAD readme.txt 暂存区、本地库比较
命令:git diff --cached readme.txt
这里缓存区和本地库没有不同所以没有内容
7.git本地操作-版本回退
当我们从暂存区提交到本地仓库时发现当前的提交的版本有问题希望回退到指定版本如何操作呢 使用vim命令编辑readme.txt,添加“我是第三行代码” 命令:git add readme.txt 提交到暂存区 命令:git commit -m ‘第三次提交’ 提交到本地仓库
我们可以通过git提供的查看日志命令来查看提交的日志
命令:git log 查看当前提交日志 可以发现目前为止我们已经在本地仓库中提交了3次也就是说有3个不同版本。其中最近的这个版本有一个标示HEAD- master 这就是标记当前分支的当前版本所在位置,如果没有显示当前所在位置可以使用下面命令查看
命令:git log --decorate 查看当前提交日志且显示当前分支的当前版本所在位置在log中每一个版本的前面都有一长串随即数字 b44a10787c2b2bcc7ceb9c39cf06309065518d4b 这是每次提交的commit id 这是通过SHA1算法得到的值Git通过这个唯一的id来区分每次提交
回退到之前版本
命令:git reset --hard HEAD^回归到上一个版本,Git通过HEAD来判断当前所在的版本位置。
那么上一个版本就用HEAD^标示上上一个版本就是HEAD^^
当然往上100个版本写100个^比较容易数不过来所以写成HEAD~100。 这时我们可以在查看一下日志 git log 发现只有两个版本我们在查看一下文件内容 回退到指定版本
命令: git reflog 查看所有操作 找到之后可以使用如下命令进行回退到指定版本
命令:git reset --hard 版本号 回退到指定版本我们回到第三次提交这时我们在查看文件 8.git本地操作-修改撤销 当我们工作区内容想要提交到缓存区时【add】突然发现有问题想要撤销该如何处理
当我们已提交到缓存区的内容发现出现了bug这时又应该如何处理哪
以上操作我们可以使用GIT提供的撤销命令来完成
工作区撤销修改
编辑readme.txt添加“我是第四行” 在你提交缓存区前你突然发现这个修改是有问题的你打算恢复到原来的样子。怎么办
使用git status 命令查看当前状态 命令:git checkout 文件名称 撤销工作区修改我们撤销后在查看文件中内容发现工作区内容已经撤销并查看状态发现状态很干净
暂存区撤销修改
使用 vim 命令 编辑readme.txt添加“我是第五行” 使用git add提交文件至暂存区 撤销到工作区
命令:git reset HEAD readme.txt 撤销到工作区工作区撤销 git checkout readme.txt 我们在查看文件发现已经恢复到最初始样子
9.分支操作
分支就是多长提交串起来的一条线 问题背景要开发一个新功能又不想打扰目前分支main的功能开发于是
可以看到main分支的开发并不会停止可以进行进行C4这个功能的开发而new分支可以开发新功能c5同样不会影响main
new 分支的功能开发测试没有问题了main 也想要 new 的代码怎么办 可以使用merge命令将new分支的变动合并至main分支此时的C6中既包含了C4以来的修改也包括了C5的修改这时如果觉得C5已经没用了可以将它删除。
1分支的创建与切换 创建分支
分支创建示意图 命令: git branch 分支名 创建dev分支 git branch dev
注意分支名字随便书写名字最好达到见名知意张三---》zhangsan分支切换
命令: git checkout dev 切换dev分支编辑readme.txt,添加“我是dev提交的代码” 从工作区提交到缓存区执行:git add readme.txt 执行:从缓存区提交到本地区git commit -m ‘dev分支提交’ 查看文件内容 切换到master分支并查看文件内容 注意如果没有将dev分支合并到主分支上那么在主分支即master上面是无法查看到dev分支提交的内容
2分支合并与删除
分支合并
命令git merge 分支名 合并dev分支 git merge dev注意当前我们是在master分支
合并后我们发现master分支上的readme.txt文件内容已经改变
分支删除
合并完分支之后如果不再使用dev分支则可以删除此分支,先查看当前分支
命令 git branch //查看分支情况当前有两个分支dev与master我们当前是在master分支上如何删除dev分支
命令 git branch -d 分支名 我们使用git branch查看发现dev分支已经被删除
10.git远程仓库介绍与码云仓库的注册创建
远程仓库是公网或外网中的一个仓库主要用于存储个人或团队的提交记录与提交日志团队合作开发也是靠远程仓库实现的。
常用的远程仓库
GitHubhttps://github.comGiteehttps://gitee.comGitlabhttps://about.gitlab.com GitHub是一个面向开源及私有软件项目的托管平台说白了就是给开发者提供了一个远程仓库。现在的GitHub除了承载了代码托管平台的功能更大的功能是组建了一个同行交流平台大量的码农在上面做技术及非技术的交流活跃用户还是很多的可惜这个主站在国外速度一般。
gitee和GitHub是一样的东西是开源中国OSChina推出的基于Git的代码托管平台又叫码云。
注册登录
访问地址https://gitee.com/
创建仓库 填写项目相关的信息 仓库创建完毕可以看到如果我们要与远程仓库同步这里支持多种通信协议当我们选中一种协议后后面会出现对应的远程仓库地址。 11.Git远程仓库操作 1关联
现在readme.txt已经推送到我们自己的本地仓库在推送到码云仓库前我们需要先建立本地仓库与远程仓库的关系
命令:git remote add origin 远程仓库地址 关联远程仓库2拉取
【注意】在推送代码前必须先拉取代码否则无法推送本地仓库代码到码云仓库 命令:git pull origin master --allow-unrelated-histories
首次拉取需要添加:--allow-unrelated-histories
命令:git pull 后续拉取3推送
本地仓库推送到码云仓库 命令: git push -u origin master 首次推送
命令: git push 后续推送 码云仓库有推送的信息 4克隆
新建文件夹learn-Git-B新建的文件中右键 点击 Git bash Here
命令: git clone 远程仓库这时候就拉取出远程仓库的内容 git clone(克隆) 与 git pull(拉取) 区别
#1.相同点都是从远程服务器拉取代码到本地
#2.不同点git clone(克隆) 是在本地没有版本库的时候从远程服务器克隆整个版本库到本地是一个本地从无到有的过程。git pull(拉取) 在本地有版本库的情况下从远程库获取最新commit 数据如果有的话并merge合并到本地。12.IDEA中使用Git
集成
在idea中的file菜单中选中settings 弹出settings后在搜索中输入git,选择Git,指定你的安装的git.exe目录 校验git是否集成完成,点击test,弹出校验窗口点击git Executed successed 成功则表示集成完成 创建过程
创建一个普通的java工程git-project项目,结构如下 基本操作-初始化工作区
点击VCS -- Create Git Repository 选择管理的文件夹这里我现在的为gitProject文件夹 点击左下角Git菜单此时day0901_git下所有的文件都变成棕色,说明我们的工作区添加完成了 忽略文件类型
从version control中我们可以看到有一部分文件我们是不需要提交到本地仓库中去的 那我们怎么做呢可以拷贝资料中.gitignore文件到gitProject的根目录 这个时候你会发现多余的不需要提交的文件类型被忽略了。如果有新的要忽视的文件类型你可以在.gitignore中添加 13.IDEA中使用Git-基本操作
工作区提交 暂存区 add
选中gitProject项目,右键 可以看到Git中的文件颜色由棕色变成的绿色 暂存区提交本地库 commit
点击右下角Version control面板中选中你要提交的文件这里我都需要提交使用全部选中 点击鼠标右键 选中commit 点击Commit 再次确定点击Commit 工作区与本地仓库比较
在Version Control中选中HelloWorld.java右键 点击左下角Git—log,就可以查看提交记录 制造问题
选择Demo01.java,提交刚刚修改的内容到本地仓库中 填写备注然后点击commit 在左下角Git中查看log 在Demo01.java中添加 提交到本地仓库 在左下角Git中查看log 可以看出此时我们一共提交3次下面我们来进行版本的回退
本地仓库回退撤销
在右下方Git点击log此时我们可以看到3个提交的版本 现在我们在本地仓库中回退到第二次提交,选择第二次提交的标记右键 选择Hard 工作区撤销
当我们在工作区编辑代码时候希望撤销未提交本地仓库的代码时候,在Git中右键 弹出如下窗口 点击Rollback,代码则撤销 说明针对上述工作区的代码撤消有同学会有疑问我直接删除不就完了吗为什么这么麻烦其实我们在实际开发中代码会很多那么当你书写了很多不同地方的代码以至于你都忘记哪些是新编写的代码了那么删除是一件很痛苦的事情并且容易误删所以使用工作区撤销更加方便。
14.IDEA中使用Git远程仓库
GitLab是一个用于 仓库管理系统的开源项目。使用Git作为代码的管理工具并在此基础上搭建起来的Web服务。可通过Web界面进行访问公开的或者私人项目。他拥有GitHub和Gitee类似的功能,能够浏览源代码管理缺陷和注释。可以管理团队对仓库的访问它非常易于浏览提交过的版本并提供一个文件历史库。团队成员可以利用内置的简单聊天程序(Wall)进行交流。它还提供一个代码片段收集功能可以轻松实现代码复用。 官网
https://about.gitlab.com登录之后的页面效果