什么是Servlet
- Servlet 是Java EE 规范之一,规范就是接口
- Servlet 就是 JavaWeb 三大组件之一,三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器
- Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端
手动实现 Servlet 程序
- 编写一个类去实现 Servlet 接口
- 实现 Service()方法,处理请求,并响应数据
package com.atguigu.Servlet; import javax.servlet.*; import java.io.IOException; public class HelloServlet implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { /** * service专门用来处理请求和响应的 * */ System.out.println("Hello Servlet 被访问了"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
- 到 web.xml 中去配置 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"> <!--servlet 给 Tomcat 配置 Servlet 程序--> <servlet> <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名)--> <servlet-name>HelloServlet</servlet-name> <!-- servlet-class Servlet 的全名--> <servlet-class>com.atguigu.Servlet.HelloServlet</servlet-class> </servlet> <!-- servlet-mapping 给 servlet 程序配置访问地址 --> <servlet-mapping> <!--servlet-name 作用是告诉服务器,我们当前配置的地址给哪个Servlet程序使用--> <servlet-name>HelloServlet</servlet-name> <!--url-pattern 配置访问地址 </br> /在服务器解析的时候,表示地址:http://ip:port/工程路径 </br> /hello 表示:地址为:http://ip:port/工程路径/hello </br> --> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
圈起的就是我们项目的工程路径 - 运行
Servlet-url 地址如何定位到Servlet 程序去访问的
Servlet 的生命周期
- 执行Servlet构造器方法
- 执行init初始化方法
第1,2步是在第一次访问,创建Servlet程序会调用 - 执行Service方法
第3步,每次访问都会调用 - 执行destory销毁方法
程序停止运行的时候才会执行
Servlet的分发处理
1、首先在webapp下创建一个HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/Servlet_war_exploded/hello" method="get">//有两种请求方式 get 和 post
<input type="submit">
</form>
</body>
</html>
2、在 service 方法中执行请求方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
/**
* service专门用来处理请求和响应的
* */
System.out.println("3 Hello Servlet 被访问了");
// 类型转换(servletRequest 不能直接用,他的子类能用)
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
String method = httpServletRequest.getMethod();
System.out.println(method);
// 得到请求的方法之后判断是哪种请求,如果是post请求执行post请求的方法,是get请求就执行get请求的方法
if("GET".equals(method)){
// 当post和get请求很多时,这样会显得很臃肿,所以我们创建两个方法,这样后期也好维护
doGet();
}else if ("POST".equals(method)){
doPost();
}
}
public void doGet(){
System.out.println("执行get请求的方法");
System.out.println("执行get请求的方法");
System.out.println("执行get请求的方法");
System.out.println("执行get请求的方法");
System.out.println("执行get请求的方法");
System.out.println("执行get请求的方法");
System.out.println("执行get请求的方法");
System.out.println("执行get请求的方法");
}
public void doPost(){
System.out.println("执行post请求的方法");
System.out.println("执行post请求的方法");
System.out.println("执行post请求的方法");
System.out.println("执行post请求的方法");
}
通过继承 HttpServlet 实现 Servlet 程序
一般在实际开发中,都是通过使用继承 HttpServlet 类的方式去实现 Servlet 程序
- 编写一个类去实现 HttpServlet 类
- 根据业务重写 doGet() 方法 和 doPost() 方法
package com.atguigu.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 // get请求的时候调用 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); System.out.println("get请求"); } @Override // post请求的时候调用 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); System.out.println("post请求"); } }
- 到 web,xml 中去配置 Servlet 程序的访问地址
</servlet-mapping> <servlet> <servlet-name>HelloServlet2</servlet-name> <servlet-class>com.atguigu.Servlet.HelloServlet2</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet2</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping>
修改a.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="http://localhost:8080/Servlet_war_exploded/hello2" method="get"> <input type="submit">s </form> </body> </html>
使用 IDEA 创建 Servlet 程序
有时候idea没有这种创建Servlet的方法,我们可以在file -> Project Structure -> Modles 下把圈到的地方全选
这样在一定的程度上减少了代码量,创建出来的Java文件直接继承的是HttpServlet类了,里面有重写doGet() 和 doPost() 方法就可以
Servlet 的继承体系
ServletConfig 类
ServletConfig 从类名上来看就知道是Servlet 程序的配置信息类
Servlet程序和ServletConfig对象都是由Tmcat负责创建,我们负责使用
Servlet程序默认是第一次访问被创建,ServletConfig对象是每个Servlet程序创建时就创建一个ServletConfig对象
1、ServletConfig 类的三大作用
- 可以获取Servlet程序的别名 servlet-name 的值
- 获取初始化参数 init-param
- 获取 ServletContext 对象
先在web.xml文件中配置init-param
<!--servlet 给 Tomcat 配置 Servlet 程序-->
<servlet>
<!--servlet-name 标签 Servlet 程序起一个别名(一般是类名)-->
<servlet-name>HelloServlet</servlet-name>
<!-- servlet-class Servlet 的全名-->
<servlet-class>com.atguigu.Servlet.HelloServlet</servlet-class>
<!-- init-param 是初始化参数-->
<init-param>
<!-- param-name 是参数名-->
<param-name>url</param-name>
<!-- param-value 是参数值-->
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
获取
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2 init初始化方法");
// 可以获取Servlet程序的别名 servlet-name 的值
System.out.println("Servlet程序的别名是:"+servletConfig.getServletName());
// 获取初始化参数 init-param
System.out.println("初始化参数namespace的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url"));
// 获取 ServletContext 对象
System.out.println("ServletContext的对象是:"+servletConfig.getServletContext());
//也可以使用
@Override
// get请求的时候调用
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("get请求");
ServletConfig servletConfig = getServletConfig();
System.out.println(servletConfig);
System.out.println("Servlet程序的别名是:"+servletConfig.getServletName());
// 获取初始化参数 init-param
System.out.println("初始化参数namespace的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url"));
// 获取 ServletContext 对象
System.out.println("ServletContext的对象是:"+servletConfig.getServletContext());
}
执行结果
2、重写init方法时
public void init(ServletConfig config) throws ServletException {
super.init(config);//必须写
}因为getServletConfig()方法是GenericServlet类的一个方法,如下:
因为GenericServlet类 对init()方进行了封装,重写时要继承不然会丢失
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
@Override
// get请求的时候调用
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("get请求");
// 也可以使用
ServletConfig servletConfig = getServletConfig();
System.out.println(servletConfig);
System.out.println("Servlet程序的别名是:"+servletConfig.getServletName());
// 获取初始化参数 init-param
System.out.println("初始化参数namespace的值是:"+servletConfig.getInitParameter("username"));
System.out.println("初始化参数url的值是:"+servletConfig.getInitParameter("url"));
// 获取 ServletContext 对象
System.out.println("ServletContext的对象是:"+servletConfig.getServletContext());
}
ServletContext 类
1、什么是ServletContext?
- Servletcontext 是一个接口,他表示 Servlet 上下文对象
- 一个web 工程只有一个Servlet 对象实例
- ServletContext 对象是一个域对象
- Servletcontext是在web工程启动时创建,在web工程关闭时销毁
- 什么是域对象:就是可以像Map一样存取对象的对象,这里的域对象是指存取数据的操作范围
存数据 | 取数据 | 删除数据 | |
Map | put() | get() | remove() |
域对象 | setAttribute() | getAttribute() | removeAttribute() |
2、ServletContext 类的四个作用
- 获取 web.xml 中配置的上下文参数 context-param
- 获取当前的工程路径名,格式/工程路径
- 获取工程在部署后在硬盘上的绝对路径
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取 web.xml 中配置的上下文参数 context-param ServletContext text = getServletConfig().getServletContext(); String username = text.getInitParameter("username"); System.out.println("上下文参数 context-param的username为:"+username); String password = text.getInitParameter("password"); System.out.println("上下文参数 context-param的password为:"+password); // 获取当前的工程路径名,格式/工程路径 System.out.println("当前的工程路径名:"+text.getContextPath()); // 获取工程在部署后在硬盘上的绝对路径 // 斜杠被服务器解析为 http://ip:port/工程名/ 映射到IDEA代码的webapp目录 System.out.println("当前工程的绝对路径为:"+text.getRealPath("/")); System.out.println("当前工程的a.html的绝对路径为:"+text.getRealPath("/a.html")); }
- 像 Map 一样存取数据
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取servletContext对象
ServletContext servletContext = getServletContext();
servletContext.setAttribute("key1","value1");
System.out.println("context中获取域数据的key1的值是;"+servletContext.getAttribute("key"));
}
Http协议
1、什么是http协议?
所谓http协议就是客户端和服务端之间通信时,发送的数据(报文),需要遵守的规则,叫http协议
2、请求http协议的格式
两种请求方式:
1、get请求
请求行
- 请求的方式 get
- 请求的资源路径[+?+请求参数]
- 请求的协议版本号 HTTP/1.1
请求头
- key:value 组成 不同的键值对 表示不同的含义
2、post请求
请求行
- 请求的方式 post
- 请求的资源路径[+?+请求参数]
- 请求的协议版本号 HTTP/1.1
请求头
- key:value 组成 不同的键值对 表示不同的含义
空行
请求体 =====>>>就是发送给服务器的数据
常用的请求头的说明
- Accept:表示客户端可以接受的数据类型
- Accept-Language:表示客户端可以接受的语言类型
- User-Agent:表示客户端浏览的信息
- Host:表示请求时的服务器的ip和端口号
哪些是get请求,哪些是post请求
get请求有哪些:
- form 标签 method = get
- a 标签
- link 标签引入 css
- Script 标签引入 js 文件
- img 标签引入图片
- ifram 引入 html 页面
- 在浏览器输入地址栏输入地址后敲回车
post请求有哪些:
- form 标签 method = post
3、响应的HTTP协议格式
1、响应行
- 响应的协议和版本号
- 响应状态码
- 响应状态描述符
2、响应头
- key:value 组成 不同的键值对 表示不同的含义
空行
3、响应体
就是回传给客户端的数据
常见的响应码
响应码 | 说明 |
200 | 表示请求成功 |
302 | 表示请求重定向 |
404 | 表示服务器已经收到但是你要的数据不存在 |
500 | 表示服务器已经收到请求,但是服务器内部错误 |
MIME类型说明
MIME是 http 协议中的数据类型
常见的MIME类型
如何查看HTTP协议
HttpServletRequest类
1、HttpServletRequest类有什么作用
2、HttpServletRequest类的常用方法
getRequestURI() | 获取请求的资源路径 |
getRequestURL() | 获取请求的统一资源定位符(绝对路径) |
getRemoteHost() | 获取客户端的ip地址 |
getHeader() | 获取请求头 |
getParameter() | 获取请求的参数 |
getParameterValues() | 获取请求的参数(多个值的时候使用) |
getMethod() | 获取请求的方式get或post |
setAttribute(key,value) | 设置域数据 |
getAttribute(key) | 获取域数据 |
getRequestDispatcher() | 获取请求转发对象 |
3、如何获取请求参数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/Servlet_war_exploded/helo" method="get">
姓名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
兴趣爱好:<input type="checkbox" name="hobby" value="cpp">c++
<input type="checkbox" name="hobby" value="java">java
<input type="checkbox" name="hobby" value="js">javaScript<br>
<input type="submit">
</form>
</body>
</html>
获取参数
package com.atguigu.Servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
public class Hello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的参数
request.setCharacterEncoding("UTF-8");//解决中文乱码问题,获取请求参数之前调用才有效
String username = request.getParameter("username");
String password = request.getParameter("password");
// String hobby = request.getParameter("hobby");
String[] hobby = request.getParameterValues("hobby");//有多个值的时候使用
System.out.println("用户姓名:"+username+"/n密码:"+password+"/n兴趣爱好:"+ Arrays.asList(hobby));
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
结果
请求的转发
1、什么是请求的转发?
请求转发是指,服务器收到请求后,从一次资源跳到另一资源的操作叫做请求转发
Servlet1
package com.atguigu.Servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的参数
String username = request.getParameter("username");
System.out.println("在柜台一查看参数(材料):"+username);
//给材料盖一个章,并传递到柜台二
request.setAttribute("key","柜台一的章");
//问路 Servlet2 怎么走
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
//走向柜台二
requestDispatcher.forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Servlet2
package com.atguigu.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 Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的参数
String username = request.getParameter("username");
System.out.println("在柜台二查看参数(材料):"+username);
//检查 柜台一是否有盖章
Object key = request.getAttribute("key");
System.out.println("柜台一是否有章:"+key);
//处理自己的业务
System.out.println("Servlet2处理自己的业务");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
结果
base标签的作用
没有base标签的话 a.html 就不可以和 index.html 相互访问
web中的相对路径和绝对路径
web中斜杠的不同意义
HttpServletResponse 类
1、 HttpServletResponse 类的作用
2、两个输出流的说明
3、如何往客户端回传数据
4、Servlet解决响应的中文乱码
5、请求重定向
请求重定向是指客户端向服务器端发请求,然后服务器告诉客户端说,我给你一些地址,你去访问新地址,叫请求重定向,因为之前的地址可能已经被废弃
respoonse1
package com.atguigu.Servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("曾到此地一游 response1");
//设置响应状态码302,表示重定向,(已搬迁)
response.setStatus(302);
//设置响应头,说明新的地址在哪
response.setHeader("location","http://localhost:8080/Servlet_war_exploded/response2");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
response2
package com.atguigu.Servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("response2's result");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
结果
6 、另一种请求重定向的方法
把上面的response1修改一下
package com.atguigu.Servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("曾到此地一游 response1");
//设置响应状态码302,表示重定向,(已搬迁)
// response.setStatus(302);
//设置响应头,说明新的地址在哪
// response.setHeader("location","http://localhost:8080/Servlet_war_exploded/response2");
response.sendRedirect("http://localhost:8080");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}