客户端与服务端交互原理
含义:http协议就相当于客户端和服务端定义好的一个规范,通过这个规范,所有人在请求和响应的过程中都需要遵循这样的规范
http协议作用:规范了浏览器和服务器之间的数据交互
特点
- 简单快速灵活
- 无状态
- 支持b/s和c/s架构
注意:http1.1之后支持可持续连接
http请求报文格式
http请求方法
get与post请求区别
- get请求参数直接显示在地址栏的,而post的请求参数放在请求体中
- get方式不安全,post安全
- get请求参数有限指,post没有限制
- get只能传输字符数据,post可以传输字节数据
http响应报文格式
http响应状态码
含义:servlet全称server applet,其是基于http协议协议的在服务端生成的程序,我们把实现servlet接口的java程序叫做servlet程序
主要功能:交互式的浏览生成数据,生成动态web内容
servlet目录结构
servlet的使用
- 导入java servlet api 的包
- 写一个类,继承httpservlet类
- 重写doget/dopost等方法
- 配置web.xml映射路径
- 配置tomcat(将写好的类部署到web服务器中)
1.导入java servlet api 的包
打开idea的file-project structure,在modules的依赖窗口加jars(servlet-api.jar),从tomcat的lib目录中
2.写一个类,继承httpservlet类,重写doget/dopost等方法
public class myservlet1 extends httpservlet {
@override
protected void doget(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception {
resp.getwriter().write("");
}
@override
protected void dopost(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception {
super.dopost(req, resp);
}
}
注意:因为我要发get请求,所以我只在doget方法中向浏览器输入内容
3.配置web.xml映射路径
项目名
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
myservlet
com.msb.myservlet1
myservlet
/first
注意:
- 配置过程中的访问路径与类名通过servlet-name连接起来
- 映射路径可以写多个
- servlet-name可以任意写,但是相同的servlet-name表明一个特定的请求路径对应一个包名.类名
- url-pattern写请求路径(里面可以有通配符*),servlet-class写包名.类名
- 也可以多条路径访问同一个类,只需要多个相同的servlet-name对应不同的url-pattern即可
- 上面的理解:收到该项目下的/first请求路径的请求叫myservlet,其会被com.msb.myservlet1这个类处理(通过反射机制)
- 也可以不写配置文件直接在servlet类上写注解@webservlet(urlpatterns = {"uri"})代替路径映射标签,注意uri的前面必须有/
4.配置tomcat
打开edit configurations,添加tomcat
点击deployment后点击右边的 号添加你项目的war包然后apply并ok
注意:访问路径前缀(虚拟项目名)标识的是某一项目的war包,因为可能将多个项目放入tomcat容器中
访问:localhost:8080/web1/first
servlet运行流程
过程:浏览器发起请求到web容器(tomcat),之后web容器产生两个对象(请求,响应)web容器根据请求url地址中的url信息在webapps目录下找到对应的项目文件夹(虚拟项目名),然后再web.xml中检索出对应的servlet,找到后调用并执行servlet的生命周期函数
servlet的生命周期
public interface servlet {
void init(servletconfig var1) throws servletexception;
servletconfig getservletconfig();
void service(servletrequest var1, servletresponse var2) throws servletexception, ioexception;
string getservletinfo();
void destroy();
}
- 初始化:在开启服务并首次调用该服务时,servlet主动调用init方法,该方法只会被调用一次
- 提供服务:用户每次发起请求servlet都会调用service方法,该方法可以被调用多次
- 销毁:当服务关闭时servlet会主动调用destroy方法,该方法只会被调用一次
关于初始化:在servlet标签里面配置
servlet继承结构
servlet接口<——genericservlet抽象类<——httpservlet抽象类(无抽象方法)
注意:genericservlet抽象类并没对service方法做任何处理,而httpservlet抽象类重写了service方法并进行了判断,重写内容为判断你发的请求是什么类型,什么类型的请求在service方法里面调用什么类型的方法(doget/dopost)
含义:request对象用来解析请求参数,当浏览器访问服务器时,携带着一些请求参数,可以通过servlet提供的request对象提供的api来解析请求参数
注意:request对象封装了请求报文
获取请求行
string getmethod():获取请求中的请求方式
stringbuffer getrequest:获取请求完整地址
string getrequesturi():获取请求资源路径
string getscheme():获取请求中的协议
获取请求头
注意:由于请求头是key:value键值对形式的,所以直接获取key就可以获得对应的value值
string getheader("key"):获取对应key的请求头信息
enumeration
getheadernames(): 获取请求头信息中的所有key的枚举对象
获取请求体
注意:
- 由于请求体是key:value键值对形式的,所以直接获取key就可以获得对应的value值
- 无论请求方式是post还是get,获取用户数据的方式不变
string getparameter("key"):获得请求体中key所对应的value值
enumeration
getparameternames(): 获取用户数据中的所有keystring[] getparametervalues("key"):如果key是多值,那么就将key的多值封装成一个数组
enumeration parameternames = request.getparameternames();
while (parameternames.hasmoreelements()){
system.out.println(parameternames.nextelement());
}
其他方法
string getremoteaddr():获取远程客户端地址
string getremotehost():获取远程客户端主机名称
int getremoteport():获取远程客户端端口号
string getlocaladdr():获取本地计算机地址
string getlocalname():获取本地计算机名称
int getlocalport():获取本地计算机端口号
void setattribute(string var1, object var2):在request对象内设置var1属性值为var2
object getattribute(string var1):在request对象内获取var1属性的值
void removeattribute(string var1):在request对象内移除var1属性及值
string getquerystring():指获取查询字符串的值(也就是?后面的值,post请求不支持)
解决乱码
void setcharacterencoding("utf-8"):设置请求编码格式为utf-8
含义:httpservletresponse对象是服务器的响应对象,这个对象中封装了向客户端发送数据,发送响应头,发送响应状态码的方法
注意:rsponse对象封装了响应报文
设置响应头
void setheader("key", "value"):设置响应头,按照k:v键值对形式,key相同时value可以被覆盖
void addheader("key", "value"):设置响应头,按照k:v键值对形式,key相同value不可以被覆盖
其他常用方法
void senderror(状态码,"状态码信息"):设置响应状态
printwriter getwriter():获取打印流
servletoutputstream getoutputstream():获取字节输出流
常用属性
void setcharacterencoding("utf-8"):设置响应编码格式为utf-8
void setcontenttype("text/html;charset=utf-8"):让浏览器以html和utf8编码的方式解析数据
void setheader("access-control-allow-origin","*"):允许任何源跨域
含义:当浏览器发送请求访问服务器中的某一个资源时,该资源将请求转交给另外一个资源进行处理的过程
请求转发特点
- 请求转发过程是一次请求,一次响应
- 请求转发过程中request对象是同一个
- 请求转发过程中,浏览器的地址没变化,所显示的页面是转发后的页面
- 转发到另一个servlet后,原servlet就无法响应页面,但转发后的代码还是可以往后继续执行的
- 转发前后的两个资源必须属于同一个web应用,否则将无法进行转发
转发方式:请求对象.getrequestdispatcher("/servlet内部url地址或jsp页面").forward(请求对象, 响应对象);
注意:url的前面一定要有/
含义:属于客户端行为。服务器在收到客户端请求后,会通知客户端浏览器重新向另外一个 url 发送请求,这称为请求重定向。它本质上是两次 http 请求,对应两个 request 对象和两个 response对象。
重定向特点
- 重定向前后是两次请求,两次响应
- 重定向前后,浏览器地址栏地址会发生变化
- 重定向前后request对象不是同一个
- 重定向前后的两个资源可以来自不同的web应用,甚至可以来自不同的虚拟主机和服务器
重定向:响应对象.sendredirect(string url)
前言:http是一个无状态的协议,当一个客户端向服务端发送请求,在服务器返回响应后,连接就关闭了,在服务端不会保留连接信息
含义:cookie是在客户端保持http状态信息的技术
特点
- cookie是在浏览器访问服务器的某个资源时,由web服务器在响应头传送给浏览器的数据
- 浏览器如果保存了某个cookie,那么以后每次访问服务器的时候,都会在请求头传递给服务端(cookie默认在虚拟项目名对应的目录下都有效)
- 一个cookie只能记录一种信息,是以key-value形式
- 一个web站点可以给浏览器发送多个cookie(但最多存放20个),一个浏览器也可以存储多个站点的cookie(最多300个)
- cookie大小有限制:4kb
- cookie是有有效期的,若不设置有效期,则默认关闭浏览器失效
创建cookie
创建cookie:cookie cookie = new cookie(string name,string value)
设置cookie
响应对象.addcookie(cookie var1):将cookie设置到response中,返回值为void
cookie.setmaxage(int expiry):为cookie设置有效期,单位为秒,返回值为void
cookie.setpath("/"):只要访问同一个tomcat中所有的项目资源,都会携带cookie,返回值为void
cookie.setpath("/cookie"):只要访问当前项目(cookie)中的所有资源,都会携带cookie,返回值为void
cookie.setpath("/cookie/abc"):只要访问当前项目(cookie)的abc路径下的所有资源,都会携带cookie,返回值为void
获取cookie
请求对象.getcookies():获得cookie数组
cookie.getname():获得cookie的name,返回值为string
cookie.getvalue():获得cookie的值,返回值为string
删除和修改cookie
- 对于不设置有效期的cookie,关闭浏览器后自动失效
- 对于设置有效期的cookie,创建一个同名cookie将有效期设置为0再响应给浏览器
- 修改cookie:新建一个重名cookie覆盖掉原有的cookie
含义:session表示会话,在一段时间内,用户与服务器之间的一系列交互操作。
session对象:用户发送不同请求的时候,在服务器端保存不同请求共享数据的存储对象
特点
- session是依赖于cookie技术的服务器端的数据存储技术
- 由服务器进行创建
- 每个用户独立拥有一个session对象
- 默认存储时间是30分钟,有请求则刷新;关闭浏览器后session失效
- 因为session是依赖cookie技术实现的,所以session默认在虚拟项目名对应的目录下都有效
session的流程
理解:session相当于在服务端开了一个房,服务端生成session后保存起来,将sessionid与会话结束时间传入cookie返回给浏览器,之后用户根据这个含有sessionid的cookie取出sessionid就可以打开对应的session房子得到相应数据。
session获取
获取session对象:httpsession session = 请求对象.getsession()
session.getid():获取sessionid,返回值为string类型
session.getattribute(string name):获取session属性值,返回值为object
session设置
session.setattribute(string name,object value):设置session属性,返回值为void
session.setmaxinactiveinterval(int n):修改session时长,以秒为单位,返回值为void
1
session删除
session.invalidate():注销session,返回值为void
session.removeattribute(string name):移除session中名为name的属性,返回值为void
- cookie:服务端给客户端一个信件,信件里面记录了你的信息,客户端下次访问服务端带上信件就可以了
- session:服务器登记你来过了,下次你来的时候匹配你(只需要确认是你就行)
理解:
- session是存在服务器上的,安全;而cookie是存在浏览器上的,不安全
- session数据的取出依赖于sessionid,而sessionid存在于cookie中
- 名与值类型:session:string和object、cookie:string和string
前言:web容器启动的时候,他会为每个web程序都创建一个对应的servletcontext对象,它代表当前的web项目(虚拟项目名下面的目录)
特点:
- 其由服务器创建
- 所有用户共享一个servletcontext对象
- 每一个web项目对应的是一个servletcontext对象
- servletcontext对象是web服务器中一个已知路径的根路径(原虚拟项目名->文件名)
获取servletcontext对象
servletcontext servletcontext = this.getservletcontext();
servletcontext servletcontext = this.getservletconfig().getservletcontext();
servletcontext servletcontext = req.getsession().getservletcontext();
下面的参数为/虚拟项目名/具体的servlet路径映射(多余)
servletcontext servletcontext = this.getservletcontext().getcontext("/servletcontext/three")
注意:在同一个web应用中获取到的servletcontext对象相同
servletcontext常用方法
获取web.xml文件中的公共属性(初始化参数)
name
value
string getinitparameter(string name):获取初始化参数中name属性对应的值
enumeration
getinitparameternames(): 获取所有初始化参数名
enumeration initparameternames = servletcontext.getinitparameternames();
while (initparameternames.hasmoreelements()){
system.out.println(initparameternames.nextelement());
}
string getrealpath(string name):获得此项目内文件名为name的相对于电脑盘符所在的真实路径
string getcontextpath():获取虚拟项目名路径
请求转发:servletcontext对象.getrequestdispatcher(string uri).forward(req, resp)
含义:servletconfig对象是servlet的专属配置对象,每个servlet都单独拥有一个servletconfig对象,主要用来获取web.xml文件中的初始化信息。
为每个servlet程序设置初始化信息,通过servletconfig对象来获取
获取servletconfig对象:servletconfig servletconfig = this.getservletconfig()
获取初始化参数name:string getinitparameter(string name)
获得所有的初始化key:enumeration
getinitparameternames()
servletconfig
cn.tedu.configservlet
name
value
servletconfig
/one
protected void doget(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception {
servletconfig servletconfig = this.getservletconfig();
//获取初始值
string value = servletconfig.getinitparameter("name");
system.out.println(value);
}
含义:过滤器是能够对web请求和web响应的头属性和内容体进行操作的一种特殊web组件
注意:
- 过滤器的特殊之处在于本身并不能够直接生成web请求和响应,而是拦截web请求和响应,以便查看、提取或以某种方式操作客户机和服务器之间交换的数据
- 可以用注解@webfilter(urlpatterns = {"uri"})代替web.xml中的配置文件来让tomcat识别,只需要将该注解放到对应的过滤器类上
过滤器的功能
- 分析web请求,对输入数据进行预处理
- 阻止web请求和响应的进行
- 根据功能改动请求的头信息和数据体
- 与其他web资源协作
过滤器的核心接口
- javax.servlet.filter
- javax.servlet.filterconfig
- javax.servlet.filterchain
过滤器的工作原理
过滤器的生命周期
public interface filter {
//用于完成tomcat的初始化,tomcat的启动时执行一次
void init(filterconfig var1) throws servletexception;
//进行处理,var3用于放行
void dofilter(servletrequest var1, servletresponse var2, filterchain var3) throws ioexception, servletexception;
//销毁功能,tomcat关闭的时候执行一次
void destroy();
}
filterconfig对象
作用:来获取过滤器的初始化参数和servlet的相关信息。
常用方法
过滤器的使用
public class myfilter implements filter {
//过滤器的生命周期函数
@override
public void init(filterconfig filterconfig) throws servletexception {
string name = filterconfig.getinitparameter("name");
system.out.println("初始化参数值为" name);
}
@override
public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception {
system.out.println("filter逻辑处理");
servletresponse.setcontenttype("text/html;charset=utf-8");
//添加此语句之后放行
filterchain.dofilter(servletrequest, servletresponse);
system.out.println("放行后");
}
@override
public void destroy() {
system.out.println("我是filter销毁");
}
}
myfilter
com.jt.myfilter
name
value
myfilter
/*
在web.xml文件中指定过滤器过滤请求
- /*:匹配本项目中的所有请求
- /*.do:匹配本项目中所有后缀为.do的请求(servlet路径中带.do)
- /filter.do:匹配本项目中请求为filter.do的请求
注意:
- 使用过滤器必须实现filter接口以及配置web.xml或注解
- 每次filter能匹配的路径发起请求都先经过过滤器,过滤器优先于servlet程序执行
- 经过过滤器的请求经由过滤器链的dofilter方法进行放行传给下一个过滤器或servlet程序(不调用的话会阻塞),待下一个程序都执行完再执行过滤器链的dofilter方法后面的方法
- 过滤器仅能处理本项目内的servlet程序,其他项目的不可以
过滤器链(filterchain)
含义:在一个web应用中,也可以部署多个过滤器,这些过滤器组成了一个过滤器链。
过滤器链执行流程
注意:code1为过滤器链的dofilter方法之前的代码,code2为过滤器链的dofilter方法之后的代码
过滤器链的执行顺序
过滤器链中的执行顺序按照web.xml中
标签的配置顺序决定的(只要满足过滤器链的请求都会走过滤器链)此标签越靠前的过滤器在过滤器链中越先执行 原因:路径查找在web.xml中是从头到尾进行查找,越在前面越先被查找到就越先被执行,找到路径后直接映射到具体的filter类执行具体逻辑
含义:servlet监听器用于监听一些重要的事件发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理
注意:
- 通过实现servlet api提供的listense接口,可以在监听正在执行的某一个程序,并且根据程序的需求做出适当的响应
- 一般都通过web.xml配置监听器,不过也可以在监听器类上加@weblistener来让tomcat识别
- 监听器优先于过滤器执行,过滤器优先于servlet程序执行
三种监听器
- httpsession监听器:监听httpsession对象,可以使web应用了解会话期间的状态并作出反应
- servletcontext监听器:监听servletcontext对象可以使web应用得知web组件的加载和卸载等运行情况
- servletrequest监听器:监听servletrequest对象,可以使web应用控制web请求的生命周期
servletrequestlistener
作用:监听servlet中request对象的创建及销毁
servletrequestevent对象方法
servletrequestevent.getservletcontext():获得servletcontext对象
servletrequestevent.getservletrequest():获得servletrequest对象
servletrequestattributelistener
作用:监听servlet中request对象属性的相关配置(属性的添加,删除和修改)
servletrequestattributeevent方法
servletrequestattributeevent.getname():获得属性的名,返回值为string类型servletrequestattributeevent.getvalue():获得属性的值,返回值为object类型
public class mylistener implements servletrequestlistener, servletrequestattributelistener {
//servletrequestlistener
//request对象被销毁时调用
@override
public void requestdestroyed(servletrequestevent servletrequestevent) {
system.out.println("rquest对象被销毁");
}
//request对象被调用时调用
@override
public void requestinitialized(servletrequestevent servletrequestevent) {
system.out.println("request对象被创建");
}
//servletrequestattributelistener
//监听向request中添加属性
@override
public void attributeadded(servletrequestattributeevent servletrequestattributeevent) {
system.out.println("监听向request作用域添加数据");
system.out.println("添加了" servletrequestattributeevent.getname() "值为" servletrequestattributeevent.getvalue());
}
//监听向request中移除属性
@override
public void attributeremoved(servletrequestattributeevent servletrequestattributeevent) {
system.out.println("监听向request中移除数据");
system.out.println("移除了" servletrequestattributeevent.getname() "值为" servletrequestattributeevent.getvalue());
}
//监听向request中属性的修改
@override
public void attributereplaced(servletrequestattributeevent servletrequestattributeevent) {
system.out.println("监听向request中属性的修改");
system.out.println("替换了" servletrequestattributeevent.getname() "新值为" servletrequestattributeevent.getvalue());
}
}
com.msb.listener.mylistener
servletcontextlistener
作用:监听servletcontext对象的创建和销毁
servletcontextevent对象方法
servletcontextevent.getservletcontext():获得servletcontext对象
servletcontextattributelistener
作用:监听servletcontext对象属性的相关配置(属性的添加,删除和修改)
servletcontextattributeevent对象方法
servletcontextattributeevent.getname():获得servletcontext属性名,返回值为string类型
servletcontextattributeevent.getvalue():获得servletcontext属性值,返回值为object类型
public class mylistener1 implements servletcontextlistener, servletcontextattributelistener {
//servletcontextlistener
//servletcontext对象创建时调用
@override
public void contextinitialized(servletcontextevent servletcontextevent) {
system.out.println("servletcontext对象创建");
}
//servletcontext对象销毁时调用
@override
public void contextdestroyed(servletcontextevent servletcontextevent) {
system.out.println("servletcontext对象销毁");
}
//servletcontextattributelistener
//servletcontext属性增加时调用
@override
public void attributeadded(servletcontextattributeevent servletcontextattributeevent) {
system.out.println("增加了" servletcontextattributeevent.getname() "属性,值为" servletcontextattributeevent.getvalue());
}
//servletcontext属性移除时嗲用
@override
public void attributeremoved(servletcontextattributeevent servletcontextattributeevent) {
system.out.println("移除了" servletcontextattributeevent.getname() "属性,值为" servletcontextattributeevent.getvalue());
}
//servletcontext属性修改时调用
@override
public void attributereplaced(servletcontextattributeevent servletcontextattributeevent) {
system.out.println("修改了" servletcontextattributeevent.getname() "属性,新值为" servletcontextattributeevent.getvalue());
}
}
com.msb.listener.mylistener1
httpsessionlistener
作用:监听session对象的创建和销毁
httpsessionevent对象方法
httpsessionevent.getsession():获取session对象
httpsessionattributelistener
作用:监听session对象属性的相关配置(属性的添加,删除和修改)
httpsessionbindingevent对象方法
httpsessionbindingevent.getname():获得session属性名,返回值为string类型
httpsessionbindingevent.getvalue():获得session属性值,返回值为object类型
httpsessionbindingevent.getsession():获得session对象
public class mylistener2 implements httpsessionlistener, httpsessionattributelistener {
//httpsessionlistener
//session对象被创建时调用
@override
public void sessioncreated(httpsessionevent httpsessionevent) {
httpsession session = httpsessionevent.getsession();
system.out.println("session对象被创建");
}
//session对象被销毁时调用
@override
public void sessiondestroyed(httpsessionevent httpsessionevent) {
system.out.println("session对象被销毁");
}
//httpsessionattributelistener
//session添加属性时调用
@override
public void attributeadded(httpsessionbindingevent httpsessionbindingevent) {
system.out.println("session添加属性时调用");
system.out.println();
}
//session移除属性时调用
@override
public void attributeremoved(httpsessionbindingevent httpsessionbindingevent) {
system.out.println("session移除属性时调用");
}
//session修改属性时调用
@override
public void attributereplaced(httpsessionbindingevent httpsessionbindingevent) {
system.out.println("session修改属性时调用");
}
}
com.msb.listener.mylistener2