Servlet概念
server applet 运行在服务器上的小程序
Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则
将来我们自定义一个类,实现Servlet接口,复写方法
快速入门
创建JavaEE项目
定义一个类,实现Servlet接口
实现接口中的抽象方法
配置Servlet:在web.xml中配置
<!--配置Servlet-->
[Java] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
<servlet>
<servlet-name>
demo01
</servlet-name>
<servlet-class>
cn.itcast.web.servlet.ServletDemo01
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo01</servlet-name>
<url-pattern>/demo01</url-pattern>
</servlet-mapping>
注:一般在IDEA中配置Tmocatd的Application context为/项目名称,再调用时需要用localhost:8080/项目名称/....
Servlet的执行原理
当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
查找web.xml,是否有对应的<url-pattern>标签内容
通过servlet-pattern找到servlet-name,又通过name找到资源的class全类名.
tomcat将类加载进内存,通过反射创建对象并调用service方法
Servlet中的生命周期
init方法-创建
初始化方法,在Servlet被创建时执行,只会执行一次
- Servlet什么时候被创建?
*默认情况下,第一次被访问时,Servlet被创建
*可以在web.xml中配置创建时机
<servlet>
<load-on-startup>
0/正值:服务器启动时创建,值越大优先级越小,一般从2开始,因为1被tomcat占用了
负值:第一次被访问时创建
</load-on-startup>
</servlet>
- Servlet在服务器中只有一个对象,所以说Servlet是单例的
*多个用户同时访问时,可能存在线程安全问题
*解决方案:尽量不要在Servlet中定义成员变量,而是使用局部变量;即使定义了成员变量,也不要对其修改值
service方法-提供服务
每一次Servlet被访问一次则执行一次
destory方法-销毁
Servlet被杀死(服务器正常关闭)时执行一次
一般用于释放资源
ServletConfig方法 获取ServletConfig对象
ServletInfo方法 获取ServletInfo,如版本.作者,信息等,但一般不实现该方法
Servlet 3.0注解配置
-[ ] 好处:支持注解配置,可以不需要web.xml了-[ ] 步骤
创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
定义一个类,实现Servlet接口
复写方法
在类上使用@WebServlet注解进行配置
@WebServlet("资源路径")
IDEA和tomcat的相关配置
[ ]IDEA会为每一个tomcat部署项目单独建立一份配置文件
启动后服务器控制台有输出Log:
Using CATALINA_BASE: "C:\Users\Mcdull\.IntelliJIdea2017.3\system\tomcat\Tomcat_8_5_31_webServer_2"
在Edit Configure下就可以修改配置文件和虚拟目录
工作空间项目和tomcat部署的web项目
tomcat真正访问的是"tomcat部署的web项目","tomcat部署的web项目"对应着"工作空间项目"的web目录下的所有资源
!!!!理解
采用的部署方式为第三种,在config/catalina/下部署
打开Using CATALINA_BASE路径,可以找到config/catalina/day13_servlet.xml
打开servlet.xml,<Context docBase="E:\Projects\webServer\out\artifacts\day13_servlet_war_exploded" \>
里面指明了tomcat项目的路径
WEB-INFO目录下的资源不能被浏览器直接访问
断点调试
打断点,后用debug模式启动服务器
Servlet结构体系
Servlet的实现类: GenericServlet(抽象类)-->HttpServlet(抽象类)
GenericServlet
GenericServlet将除了servic()以外的方法都空实现
将来定义Servlet时可以继承GericServlet,只需实现servic类即可.
其他类也可以重写HttpServlet
-[ ] 实际上做项目时,我们一般使用GenericServlet的子类HttpServlet,因为HttpServlet封装了Http协议
不使用HttpServlet时,service方法需要实现的功能
判断用户的请求方式(get/post...)
String method = req.getMethod();
if("GET".equals(method)){//get方式获取数据逻辑操作}
else if("POST".equals(methos){//post方式获取数据逻辑操作}
HttpService 将判断请求方式封装起来,并提供doGet()和doPost()方法,分别写在两个逻辑体中
1.定义类继承HttpServlet类
2.重写doGet/doPost/...方法
[Java] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
System.out.println("doGet...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
System.out.println("doGet...");
}
Servlet urlpattern相关配置
1.urlpattern:Servlet访问路径可以有配置多个
一个Servlet可以定义多个访问路径,在注解中使用{"路径1","路径2"...}来配置
2.urlpattern:Servlet路径的定义规则
1)./xxx 以这种方式为主
2)./xxx/xxx
3).*.后缀名
[强制!]开发中后缀名只能用*.do或*.action
HTTP概念
Hyper Text Transfer Protocol:超文本传输协议
传输协议:定义了客户端和服务器端通信时发送数据的格式
特点:
1). 基于TCP/IP的高级协议
2). HTTP的默认端口号为80
当访问资源时,如果服务器端口号为80,则可以省略
3). 基于请求/响应模型的:一次请求对应一次响应
4). 无状态的:每次请求之间相互独立,不能交互数据
历史版本:
1.0版本:每一次请求都需要建立一个连接
1.1版本:复用连接
请求消息数据格式
请求行
格式
请求行格式:
请求方式 请求url 请求协议/版本
例: GET /login.html http/1.1
请求方式
HTTP协议中有7种请求方式,常用的有2种
*GET:
1.请求参数在请求行中,在url后
2.请求的url长度是有限制的
3.不太安全
*POST:
1.请求参数在请求体中
2.请求的url长度没有限制
3.相对安全
请求头-浏览器告诉服务器一些信息
格式
请求头格式:
请求头名称:请求头值
请求头名称
常见的请求头:
1.User-Agent**:浏览器告诉服务器,访问者使用的浏览器版本信息
*可以在服务器端获取该头信息,解决浏览器兼容性问
2.Referer**:告诉服务器,当前请求从哪里来(发起请求的页面)
*例:Referer:http://localhost:8080/day_14/login.html
*作用:
1)防盗链:
if(referer.equals()){操作}
else{"想看吗?来XXX网站吧!"}
2)统计工作:
统计工作:统计请求来源
if(refer.eauals("百度"){百度++}
else if(){}...
3.Connection:告诉服务器连接的状态(是否可服用)
4.Host:请求主机的地址
5.Accept:告诉服务器,作为浏览器可以解析什么格式的文件
请求空行-用于分割POST请求的请求头和请求体
空行
请求体(正文)-封装post请求消息的请求参数
格式
参数名=参数值
响应消息数据格式
响应行
组成
协议/版本 响应状态码 状态码的描述
响应状态码:服务器高速客户端浏览器本次请求和响应的一个状态
分类:
1xx: 服务器接收客户端消息,没有接收完成,等待一段时间后,发送1xx
2xx: 成功 代表状态码:200
3xx: 重定向 代表状态码:302(重定向) 304(访问缓存)
4xx: 客户端错误 代表状态码:404(请求路径错误) 405(请求方式没有对应的doXXX方法)
5xx: 服务器错误 代表状态码:500(服务器内部出现异常)
响应头
格式
头名称:值
常见的响应头
1.Content-Type:服务器告诉客户端响应体数据格式以及编码格式
例:Content-Type:text/html;charset=UTF-8
2.Content-disposition:服务器告诉客户端以什么格式打开响应体数据
*值:
*in-line:默认值,在当前页面内打开
*attachment;filename=xxx:以附件形式打开响应体.文件下载
响应空行
响应体:传输的数据
响应字符串格式Request对象Request和Response对象的原理
1.tomcat服务器会根据请求url中的资源路径,创建对应的Servlet对象
2.tomcat服务器会创建request和response对象;request对象中封装消息数据
3.tomcat将request和response两个对象传递给service方法,并调用service方法
4.程序员可以通过request对象来获取请求消息数据;可以通过response对象来设置响应数据
5.tomcat在给浏览器作出响应之前,会从response对象中获取消息响应数据并响应给浏览器
注意:
1) request和response对象是由服务器创建的,我们来使用它们
2) request对象是来获取请求消息,response对象来设置响应消息
Requset对象的继承结构
ServletRequset(接口)->HttpServletReqest(接口)->RequestFacade(tomcat写的实现类)
Request对象的功能获取请求消息数据
1.获取请求行数据
-请求行数据: GET /day14/demo01?name=zhangsan HTTP/1.1
-获取方法:
1)获取请求方式: GET
*String getMethod()
2)获取虚拟目录**: /day14
*String getContextPath()
3)获取Servlet路径 /demo1
*String getServletPath()
4)获取请求参数 /name=zhangsan
*String getQueryString()
5)获取请求的URI**: /day14/demo1
*String getRquestURI :/day14/demo1
*StringBuffer getRequestURL: http://localhost/day14/demo1
6)获取浏览器的协议及版本 HTTP/1.1
*String getProtocol()
7)获取客户机的IP地址
*String getRemoteAddr()
注意:
URL:统一资源定位符 http://localhost//day14/demo1
URI:统一资源标识符
day14/demo1
URL的范围比URI的范围小
2.获取请求头数据
1) String getHeader(String name):通过请求头名称获取请求头的值
2) Enumeration<String> getHeadernames():获取所有请求头的名称
Enumberation 和 Iterator类似:
hasMoreElement() <--> hasNext()用于判断
nextElement() <--> next() 用于获取下一下元素
3.获取请求体数据只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
步骤:
1).获取流对象
*BufferedReader getReader():获取字符输入流
*ServletInputStream getInputStream():获取字节输入流
2).从流对象中获取数据
4.总结:常用的方法
1)获取虚拟目录:getContextPath()
2)获取请求URI:getRequestURI()/getRequestURL()
3)获取请求头:getHeader(String name)
==其他功能==
==1.获取请求参数(通用方式)==
1)String getParameter(String name):根据参数名称获取参数值
2)String[] getParameterValues(String name): 根据参数名称获取参数值的数组,多用于复选框
如:hobby=xx&hobby=game
3)Enumeration<String> getParameterNames():获取所有请求的参数名称
4)Map<String,String[]> getParameterMap():获取所有参数的map集合
- 中文乱码问题
*get方式: tomcat8 已经将get方式乱码问题解决了
*post方式: 会乱码
解决:在获取参数前,设置request编码
request.setCharacterEncoding("utf-8")
==2.请求转发:一种在服务器内部的资源跳转的方式==
步骤
1)通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
2)使用RequestDispatcher对象来进行转发:forward(ServletRequest request,ServletResponse)
特点
1) 浏览器地址栏路径不发生变化2) 只能转发至当前服务器的内部资源中3) 转发是一次请求
==3.数据共享==
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中去共享数据
request资源共享方法
1) void setAttribute(String name ,Object obj) :存储数据2) Object getAttribute(String name) 通过键来获取值3) void removeAttribute(String name) 通过键来移除键值对
==4.获取ServletContext对象==
-ServletContext getServletContext()
BeanUtils
用于封装JavaBean
JavaBean
JavaBean:标准的Java类
类必须被public修饰
必须提供空参的构造器
成员变量必须使用private修饰
提供公共的setter和getter方法
JavaBean的功能:封装数据
概念
成员变量
属性:setter和getter方法截取后的产物
例如:getUsername()-->Username-->username大部分情况下属性和成员变量是一样的
BeanUtils的方法
1.setProperty(javaBean,"属性名","值")
2.getProperty(javaBean,"属性名")
3.populate(javaBean,属性集map)
Response对象
功能:设置响应消息
设置响应行
设置响应头
设置响应体
设置响应行1.格式HTTP/1.1 200 ok2.设置状态码setStatus(int sc)
设置响应头
setHeader(String name, String value)
设置响应体
使用步骤
1.获取输出流 *字符输出流:PrintWriter getWriter() *字节输出流:ServletOutputStream getOutputStream()2.使用输出流将数据输出到客户端浏览器
案例完成重定向(redirect)
代码实现
//1.设置状态码为 302response.setStatues(302);//2.设置响应头locationresponse.setHeader("location","/虚拟路径/资源路径")
简单的重定向方法
resonpse.sendRedirect("/虚拟路径/资源路径")
重定向的特点
1. 地址栏发生变化2. 重定向可以访问其他服务器的资源3. 重定向是两次请求
路径写法:
1.相对路径: 通过相对路径不可以确定唯一资源 * 以 ./开头 表示当前路径 * 以 ../开头 表示后退一级 *规则: 找到当前资源和目标资源之间的相对位置关系 2.绝对路径: 绝对路径可以确定唯一资源 在这里可以写为/虚拟路径/资源路径
在浏览器输出字符数据
代码实现
//1.获取字符输出流PrintWriter pw = resp.getWriter();//2.向浏览器写出字符数据pw.write("<h1>你好,response</h1>");此实现会出现乱码,因为获取的流的默认编码为IOS-8859-1
乱码问题
上一个代码实现会出现乱码问题
解决方法:在获取流之前设置编码和web解码方式
//1.设置response的编码格式(默认为IOS-8859-1)
//response.setCharacterEncoding("编码格式")
//2.使用response设置响应头,要求使用特定的编码格式去解码
response.setHeader("content-type","text/html;charset=编码格式")
简单方法:
response.setContentType("text/html;charset=编码格式")
注意:使用语句2,就可以设置编码格式,和浏览器的解码格式.第1步就可以不用写了
作者:黑马程序员JavaEE培训学院
首发:http://java.itheima.com/