servlet 使用手册
servlet
servlet的基本概念
需要服务器能够认识找到servlet的结构->web.xml文件
servlet就是一组接口,这组接口是与服务器进行数据交换的规则
大致流程:
创建java EE项目
定义类实现servlet接口,五个抽象方法init,destroy,getservletconfig,getservletinfo,service(service最重要)
配置servlet(服务器url地址mapping)
将具体的类配置为servlet,在web.xml文件中使用<servlet>标签来进行配置配置服务器url地址与servlet的映射,使用<servlet-mapping>标签进行配置<url-pattern>另一种是通过注解进行配置,实际上是web.xml配置的子功能
逻辑实际执行流程:
客户端发送http请求->服务器接收到请求->服务器处理
servlet的生命周期
服务器在第一次调用一个servlet类的时候,会创建servlet对象,这个对象只会存在一个被保存在服务器的上下文环境中,供服务器的持续调用,知道服务器下线,servlet对象才会调用销毁destroy方法,结束生命周期
init方法:
- 在servlet被创建的时候会调用一次
service方法
- 服务器调用servlet的方法
destroy方法
- 服务器正常关闭时调用
servletConfig方法,servletInfo方法
servletConfig方法用于获取servletconfig对象的,该对象中记录了web.xml中servlet的各种信息,包括:
- 获取在web.xml中的名字 getservletName
- 获取在web.xml中通过<init-param>标签配置的初始化参数 getinitparameter
- 获取所有 初始化参数的名字枚举 getinitparameternames
- 获取当前web应用的servletcontext对象, getsevletcontext(*****servletContext用于不同的servlet之间共享数据)
servletInfo方法用于获取servlet的信息:
- servlet版本
- servlet作者
servlet的具体调用
- 默认情况下就是第一次调用servlet的时候调用init
但是可以改变sevlet的创建时机,<servlet>标签下通过<load-on-startup>服务器启动时创建,负数就是默认值 - servlet被销毁,服务器被正常关闭才会执行destroy方法,这个方法也是服务器调用的.
servlet的问题
因为是单例存在于服务器中,所以存在线程安全问题
如果同时多个用户访问同一个servlet
为了保证servlet的执行效率和并行效率,不能对servlet进行加锁
所以在servlet中尽量不使用成员变量的修改,使用局部变量不会有线程安全问题
servlet注解配置
在servlet3.0开始,支持注解配置servlet,解决了使用web.xml配置繁琐的问题,并且更好理解servlet的配置
改变:
- 创建java EE时需要选则servlet3.0以上版本(java EE 6开始)
- 可以不用创建web.xml文件
- 在类上使用@webServlet注解
@webServlet注解结构
根据之前配置web.xml文件的经验,注解应该包含以下的配置选项
配置servlet
- name String
- loadOnStartup int default -1
name可以不用配置了,因为name用于配置映射的作用不再需要了,直接在类上配置路径即可完成映射
loadOnStartup就是servlet的创建时机配置,默认是-1,配置为非负数就是服务器启动的时候创建servlet
配置mapping
- urlPatterns String[]
- value String[]
urlPattern 这个就是对应的服务器资源路径,需要注意的是,资源路径一定是/开头
value 如果不配置其他属性,那么可以直接写String[]参数作为value的值,其实就是urlpatterns
资源路径小知识
定义资源路径有三种方法
- /xxx
- /xxx/xxx
- *.do
what mean?
第一种是基础,指明了资源路径必须由/开头
第二种表示路径可以有多层
第三种指明了*可以代表任意资源名称,这个*也需要带上/
服务器小知识
要配置服务器应用,需要将servlet所在工程拷贝到服务器的配置目录下
工程中的web-inf目录的资源不能被客户端直接访问,可以将隐私资源放在这个目录下
资源小知识
web资源分为静态资源和动态资源
- 静态资源
也就是所有用户看到的都是相同的内容,不需要做出改变的资源
- 动态资源 (servlet/jsp,php,asp)
需要servlet根据不同的条件对资源进行加工,转变成静态资源之后再返回给客户端
所以jsp文件不能直接用浏览器渲染,而改为html文件就可以直接打开
通信三要素
- ip
- 端口
- 传输协议
传输协议:
安全协议tcp: 三次握手四次挥手
tcp/http协议
不安全udp
HttpServlet
Http协议
先介绍Http协议
http是四个字母的缩写,hyper text tranform protocol 超本文传输协议
定义了客户端和服务端发送数据的格式,使得两边能够相互解释二进制序列
特点
基于TCP/IP协议,是一种安全协议,不会丢失
HTTP服务的默认端口是80
基于请求响应模型:一次请求得到一次响应,减少服务端压力
无状态协议:每次请求之间没有关系
历史版本
1.0版本 每次连接响应之后都会断开
1.1版本 复用链接,如果短时间内没有请求在断开连接
HTTP数据格式
Http请求消息格式
一共四个部分
- 请求行
- 请求头
- 请求空行
- 请求体
- 请求行 使用一行 描述清楚请求的网络信息
请求方式 请求url 请求协议/版本号
- 请求头
直接接着请求行下一行开始,语法格式:
请求头属性名称:值,值…
- 空行用于分割请求头和请求体,也就是使用换行符分割每一条数据
- 请求体(正文)
get方式没有请求体
请求体里面表单信息,例如username=value
7种请求方式
常用的有get和post请求
get方法与post方法的区别:
- 最大区别在于传递参数的位置不同,get方式参数跟在url中,明文显示,post的参数在请求体中
- get方式的url有长度限制,而post没有,因为post不需要将url中的参数解析出来的步骤
- post相对安全,不过也只是相对,有心人拦截了请求包照样能解析出请求体的数据
请求头属性
请求头属性的目的就是告诉服务器客户端的一些信息
服务器主要使用的信息有:
Host 服务器的地址
user_agent 浏览器版本信息,服务器解决兼容性问题
Accept 浏览器能够接受的response格式
Accept-language:zh-CN
referer (*****)告诉服务器当前请求是从那个url发出的可以用来防止盗取链接
统计工作
connection 是否连接复用
request,response的来历
服务器解析http请求之后
- 服务器先根据路径找到servlet
- 服务器创建request对象和response对象,将http请求中的数据封装进去
- 服务器将request和response对象交给servlet加工处理
- 服务器将servlet处理后的request方法和response交给filter处理
- 服务器根据response生成响应消息返回浏览器客户端
request的继承体系结构
不同的协议,请求消息的数据结构不一样,所以request有不同的子接口
例如servletrequest,HttpservletRequest
ServletRequest –接口
|继承
HttpServletRequest –接口
|实现
org.apache.catalina.connector.RequestFacade (tomcat会创建这个类)
使用request
获取请求消息
- 获取请求行数据
- 获取请求头数据
- 获取请求体数据
1 获取请求行数据
例如 get /day14/demo1?name=zhangsan HTTP/1.1
- 获取请求方式 String getMethod()
- (*****)获取虚拟目录,通过虚拟目录可以映射到物理路径 String getcontextPath()
- 获取servlet路径 String getServletPath()
- 获取get方式的url参数 String getQuery()
- (*****)获取请求URI String getRequestURI() 获取URL getRequestURL()
- 获取协议版本 String getProtocol()
- 获取客户端ip 如果请求头中包含X-forwarded-for或者X-real-ip字段,那么此方法会优先获取到此信息作为返回,如果不包含这些ip字段信息,会返回底层连接的ip String ggetRemoteAdrr()
关于虚拟目录
一般用户无法直接分辨URL中的虚拟目录部分和Servlet资源路径部分。对于一般用户来说,URL中的路径部分通常是不透明的,他们只会看到完整的URL,而无法直接分辨其中的虚拟目录和Servlet资源路径。
虚拟目录和Servlet资源路径的概念主要是针对开发者和服务器端的应用程序来说的,用于确定请求应该由哪个Servlet或资源来处理。一般用户通常只需要关注完整的URL路径,而无需关心其中的具体细节。
因此,对于普通用户来说,URL路径通常是作为整体来使用的,而不需要区分其中的虚拟目录和Servlet资源路径部分。这些细节主要由开发者和服务器端来管理和处理。
2 获取请求头数据
- 通过请求头属性名获取值 String getHeader(String name)
- 获取所有请求头属性名 Enumeration<String> getHeaderNames()
3 获取请求体数据
只有post方式才有请求体,其中封装了请求参数
因为请求体的参数类型不确定,请求体的大小也不确定,有二进制数据,也有文本数据参数
所以请求体的参数大都需要自己解析
- 获取请求体流对象 BufferReader getReader() 获取字符输入流
- ServletInputStream getInputStream() 获取字节流输入,可以操作任意数据类型
中文乱码问题
因为编码的问题,需要在request设置流的编码
request.setCharacterEncoding(“utf-8”)
输出流也需要设置
4 其他高效功能
(*****)获取请求参数的通用方法 String getParameter(string name )根据参数名称获取参数值
String[] getParameterValues(string name) 用于获取同一个参数多个值的类型
Enumeration<String> getParameterNames()获取所有参数名
Map<String,String> getParameterMap() 获取所有参数键值对
请求转发(而不是重定向)
是一种在服务器内部资源跳转方式,将请求交给其他servlet处理好处->可以让servlet更加内聚,每个servlet专门做一件事情,减少耦合
方法:
- 获取请求的转发对象
因为servlet没有服务器根据请求调用servlet的功能,所以这个功能需要通过服务器的手段,服务器提供的手段就是转发对象 RequestDispatcher getRequestDispatcher(“path”)- 调用转发对象的forward方法 forward(request,response)
请求转发的特点:
- 客户端不知道,浏览器url不变化
- 只能转到服务器内部资源,不能转到外部资源
- 转让发是一次请求,不会降低效率
共享数据
不同的域就有不同的作用范围,比如我在main函数中定义的一个对象,在main函数此代码后面的所有代码都可以使用这个对象,而在后面某个函数中定义的对象,在main调用无法使用
这就是不同的作用域的概念
servlet中的作用域如下:
request作用域,因为request每次请求服务器只会创建一个,所以本次请求中所有都在作用域中,通过setAttribute设置共享数据 getAttribute获取通过removeAttribute移除数据
获取servletContext
记得servlet接口中五个方法,除了生命周期的三个方法,还有getServletConfig和getServletInfo方法
其中getServletConfig能够获取到servlet的配置信息,大多是web.xml中的配置信息,而这个对象也能够获取到servletContext
servletContext 叫做servlet上下文环境,也就是servlet对象所在的域
每个servlet都能够获取到同一个SErvletContext
Http响应消息格式
response对象通过getWriter获取到输出字符流
我们通过向输出字符串输出相应内容