1.Servlet简介
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
- Servlet就是sun公司开发动态web的一门技术。
- Sun在这些API中提供一个接口叫做:Servelt,如果你想开发一个Servlet程序,只需要完成两个小步骤
- 编写一个类,实现Servlet接口
- 把开发好的java类部署到web服务器
把实现了Servlet接口的java程序叫做,servlet
什么是Servlet?
1.Servlet是javaee规范之一。规范就是接口。
2.Servlet就javaweb三大组件之一。三大组件就是:Servlet程序,Filter过滤器,Lister监听器
3.Servlet是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
2.HelloServlet
1.构建一个普通的maven项目。
2.父工程对应的jar包
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
3.编写一个Servlet程序
1.编写一个普通类。
2.实现Servlet接口,这里我们直接继承HttpServle
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入doGet方法");
//ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter();//响应流
writer.print("hello,Serlvet");
}
}
3.编写Servlet的映射
为什么需要映射:我们写的是java程序,但是要通过浏览器访问,浏览器需要连接web服务器,所以我们再要web服务注册我们写的Servlet,还需要给他浏览器能够访问的路径。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<!-- 注册Servlet-->
<servlet>
<!-- servlet-name 标签 Servlet程序起一个别名(一般是类名)-->
<servlet-name>hello</servlet-name>
<!-- servlet-class 是Servlet程序的全类名-->
<servlet-class>com.pang.servlet.HelloServlet</servlet-class>
</servlet>
<!-- servlet-mapping 标签给servlet程序配置访问地址-->
<servlet-mapping>
<!-- servlet-name 标签的作用是高数服务器,我当前配置的地址给哪个Servlet程序使用-->
<servlet-name>hello</servlet-name>
<!-- url-pattern 标志配置访问地址
/ 在服务器解析的时候,表示的地址为:http://ip:port/工程路径
/hello
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
4.配置Tomcat
5.启动测试
![在这里插入图片描述](https://img-blog.csdnimg.cn/1fb2a13bb3a44d0db6658ea701e1a504.png)
Servlet程序
url地址到servlet程序的访问
servlet生命周期
1、执行Servlet构造器方法
2、执行init初始化方法
第一第二步,是第一次访问,的时候创建Servlet程序会调用
3、执行servlet方法
第三步,每次访问都调用
4、执行destory销毁方法
第四步,在web工程停止的时候调用
GET和POST请求的分发处理
我们为了区别GET和POST请求,我们使用了ServletRequest类里面的HttpServletRequest接口的getMethod()方法。
这里GET和POST请求有什么区别呢?
最直观的区别就是 GET 把参数包含在 URL 中,POST 通过 request body 传递参数。
详细看这:链接。
package com.pang.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet implements Servlet {
public void HelloServlet(){
System.out.println("1");
}
//由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
// @Override
// protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
// }
// @Override
// protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//
// System.out.println("进入doGet方法");
// //ServletOutputStream outputStream = resp.getOutputStream();
// PrintWriter writer = resp.getWriter();//响应流
// writer.print("hello,Serlvet");
// }
@Override
public void init(ServletConfig servletConfig) throws ServletException {
// 初始化代码...
System.out.println("初始化");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("第3步");
//类型转换
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
//获取请求的方式
String method = httpServletRequest.getMethod();
if("GET".equals(method)){
doGet();
}else{
doPost();
}
}
@Override
public String getServletInfo() {
return null;
}
public void doGet(){
System.out.println("Get请求");
}
public void doPost(){
System.out.println("Post请求");
}
@Override
public void destroy() {
System.out.println("第4步");
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/3aa4196c0abc4d48af5cbcbcc67922eb.png)
但是呢,我们这样每次都写dopost和doget方法比较繁杂,我们可以使用更加简便的方法去执行。
通过继承HttpServlet类实现Servlet程序
一般在实际项目开发中,都是使用继承HttpServlet类的方式去实现Servlet程序
1、编写一个类去继承 HttpServlet类
2、根据业务需要重写doGet或doPost方法
3、到web.xml中的配置Servlet程序的访问地址
package com.pang.servlet;
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 HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet方法");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost方法");
}
}
Servlet类的继承体系
2.ServletConfig类
ServletConfig类从类名上来看,就知道是Servlet程序的配置信息类。
Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。
Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象。
ServletConfig类的三大作用
1、可以获取Servlet程序的别名servlet-name的值
2、获取初始化参数init-parpam
3、获取ServletConfig对象
@Override
public void init(ServletConfig servletConfig) throws ServletException {
// 初始化代码...
System.out.println("初始化");
// 1、可以获取Servlet程序的别名servlet-name的值
System.out.println("HelloServlet的别名是"+servletConfig.getServletName());
// 2、获取初始化参数init-parpam
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数username的值是:"+servletConfig.getInitParameter("url" ));
// 3、获取ServletConfig对象
System.out.println(servletConfig.getServletContext());
}
我们还可以在doGet()方法中用getServletConfig()获取到ServletConfig()对象,不过他只能获取到当前对象和当前参数的值。
![在这里插入图片描述](https://img-blog.csdnimg.cn/a9a380b80a0942ddb8a6f1da8fba7266.png)
如果说我重写init()方法,我们看一下会出现什么?
我们重启一下。
![在这里插入图片描述](https://img-blog.csdnimg.cn/0f1c893d5635428b84902f7f575829be.png)
因为我们getServletConfig是在GenericServlet上获取到的,而GenericServlet只有ServletConfig这一个引用。
在GenericServlet类上也有init()方法,那我们重写子类的时候,父类的init()方法就会丢失,
所以我们需要在重写子类init()的时候加上super.init(config)就行,去调用父类的init()方法。
![在这里插入图片描述](https://img-blog.csdnimg.cn/716ef3b98033405a9075b6994223fd04.png)
3.ServletContext类
什么是ServletContext?
1、ServletContext是一个接口,他表示Servlet上下文对象。
2、一个web工程,只有一个ServletContext对象实例
3、ServletContext对象是一个域对象。
4.ServlectContext是在工程部署启动的时候创建,在web工程停止的时候销毁。
那什么是域对象?
域对象是服务器在内存上创建的存储空间,用于在不同动态资源(servlet)之间传递与共享数据。
这里的域指的是存取数据的操作范围,整个Web工程。
存数据 | 取数据 | 删除数据 | |
---|---|---|---|
Map | put() | get() | remove() |
域对象 | setAtttibute() | getAtttibute() | removeAtttibute() |
作用:
1.获取配置web.xml配置的上下文参数的context-param 不能获取init-param
2.获取到的context-param里面的username和password
3.获取到当前的工程路径和服务器上的绝对路径
4.像Map一样储存数据
public class ContextServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context= getServletContext();
System.out.println("在没保存之前:ContextServlet,context获取到的key1的值"+context.getAttribute("key1"));
context.setAttribute("key1","value1");
System.out.println("ContextServlet,context获取到的key1的值"+context.getAttribute("key1"));
}
}
当我们在另外的一个ContextServlet创建getServletContext的时候,获取key1的值看看是否能不能拿到。
public class ContextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context1=getServletContext();
System.out.println("ContextServlet,context1获取到的key1的值"+context1.getAttribute("key1"));
}
}
可以拿到,但是呢必须是在启动了ContextServlet1类之后,上面也刚讲过ServlectContext是在工程部署启动的时候创建,在web工程停止的时候销毁。那只有在保存之后,在启动就可以拿到,我们还会发现我又再次启动了ContextServlet1类,发现在没保存之前我们依旧也获取到key1的值。
如果说重新创建Servlet则会拿不到,需要重新启动ContextServlet1类才能拿到key1值。
3.Http协议
a)什么是HTTP协议
什么是协议?
协议是指双方,或多方,相互约定好,大家需要遵守的规则,叫协议。
所谓HTTP协议,就是指,客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫HTTP协议。
HTTP协议中的数据又叫报文。
b)请求的HTTP协议格式
客户端给服务器发送数据的是请求。
服务器给客户端回传数据的是响应。
请求又分为GET请求和POST请求。
i.GET请求
1.请求行
(1).请求的方式 GET
(2).请求的资源路径[+?+请求参数]
(3).请求的协议版本号 HTTP/1.1/
2.请求头
key:value 组成 不同的键值对,表示不同的含义。
ii.post请求:
1.请求行
(1).请求的方式 GET
(2).请求的资源路径[+?+请求参数]
(3).请求的协议版本号 HTTP/1.1/
2.请求头
(1).key:value 不同的请求头有不同的含义
空行
3.请求体 ======>>>就是发送给服务器的数据
iii.常用请求头说明:
Accept:表示客户端可以接收的数据类型
Accept-Language:表示客户端可以接收的语言类型
User-Agent:表示客户端浏览器的信息
Host:表示请求时的服务器ip和端口号
iv.什么时候用get请求和post请求?
当请求无副作用时(如进行搜索),便可使用GET方法;当请求有副作用时(如添加数据行),则用POST方法。一个比较实际的问题是:GET方法可能会产生很长的URL,或许会超过某些浏览器与服务器对URL长度的限制。
若符合下列任一情况,则用POST方法:
- 请求的结果有持续性的副作用,例如,数据库内添加新的数据行。
- 若使用GET方法,则表单上收集的数据可能让URL过长。
- 要传送的数据不是采用7位的ASCII编码。
若符合下列任一情况,则用GET方法:
- 请求是为了查找资源,HTML表单数据仅用来帮助搜索。
- 请求结果无持续性的副作用。
- 收集的数据及HTML表单内的输入字段名称的总长不超过1024个字符。
c).响应的HTTP协议格式
1.响应体
(1).响应的协议和版本号
(2).响应状态码
(3).响应状态描述符
2.响应头
(1).key:value 不同的响应头有不同的含义
空行
(3).响应体 ---->>>> 就是回传给客户端的数据
d)常用的响应码说明
200 | 表示请求成功 |
---|---|
302 | 表示请求重定向 |
404 | 表示服务器请求已经收到了,但是你要的数据不存在(请求地址错误) |
500 | 表示服务器已经收到请求了,但是服务器内部错误(代码错误) |