什么是Servlet
Servlet=Server+applet
Server:服务器
applet:小程序
Servlet含义是服务器端的小程序。
Tomcat和Servlet的关系
Tomcat 是Web应用服务器,是一个Servlet/JSP容器。Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户。而Servlet是一种运行在支持Java语言的服务器上的组件。Servlet最常见的用途是扩展Java Web服务器功能。
- Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到
- Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器
Servlet开发流程
Servlet的开发流程
狭义上讲,servlet是servlet是java语言实现的一个类,所以我们就要根据这个类进行相应的扩展开发.
开发流程如下:
- 编写一个java类,继承HttpServlet类
- 重写HttpServlet类的doGet方法和doPost方法
配置web.xml文件,或者使用注解对servlet进行配置
在IDEA里面编写Servlet
1.搭建Tomcat环境与前端文件
具体怎么做的看这片文章
Tomcat
最终目录结构向这样
2.添加Servlet依赖(在Tomcat里面)
点击
- 添加依赖
- 添加完依赖以后,这里就会出现刚才的依赖
3. 编写Servlet
- 在模块里面的src下新建一个包,在包里面创建一个java文件
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author liyadong
* @create 2022-03-22-16:25
*/
public class demo01servlet extends HttpServlet { //继承HttpServlet类
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做get请求的处理
System.out.println("GET");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做post请求的处理
System.out.println("POST");
}
}
3.1.运行逻辑
- 前段发送请求到demo01servlet这个方法
- req就是前段发送过来的全部东西,包括请求头,数据
- 重写HttpServlet里面的do类方法,如果这个请求是post,就会执行doPost方法,如果请求是get,就会执行doGet方法
- 如果请求是get,没有重写doGet方法,就会去父类里面执行doGet方法,而父类里面的do类方法都是提醒你错误的,所以要重写,没重写就给你返回错误4xx状态
- 这个方法执行完了,resp就会被Tomcat返回给前端,所以在这个方法里面可以对resp进行一系列的操作,比如携带一些值返回
4.在web.xml中配置servlet
目的是让浏览器发出的请求知道到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用。
写在web-app标签里面
<servlet>
<servlet-name>demo01servlet</servlet-name>
<servlet-class>lyd.servlet.demo01servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo01servlet</servlet-name>
<url-pattern>/demo01api</url-pattern>
</servlet-mapping>
- servlet-name:给servlet取个名字,这个无所谓取什么,一般跟我们写的servlet类名相同
- servlet-class:servlet的全限定类名,也就是servlet的位置
- 首先在浏览器输入
http://localhost:8080/demo01/demo01api
- 根据url来找到
- 然后根据
里面的名字找到对应的 标签 - 最后找到servlet的位置
- 最终运行程序,在浏览器输入url按回车,IDEA控制台会打印GET,因为浏览器url访问是get方法
4.2多个url
上面的一个
标签可以对应多个 标签, 里面的 和 里面的对上, 可以不同,也就是说可以通过不同的url访问同一个servlet
5. HttpServletRequest取值
Request Payload
前端发送请求的数据是在Payload里面的,是Json格式
请求头是的Content-Type是application/json
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
/**
* @author liyadong
* @create 2022-03-22-16:25
*/
public class demo01servlet extends HttpServlet { //继承HttpServlet类
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做get请求的处理
System.out.println("GET");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做post请求的处理
System.out.println("POST");
//得到Request Payload形式的数据,json字符串(还要经过转换成json)
String jsonstr = getStringFromStream(req);
}
/**
* 从流中获取Request Payload的数据。调用了req.getInputStream()方法后,这个request就不再是json传参了
*/
private String getStringFromStream(HttpServletRequest req) {
ServletInputStream is;
try {
is = req.getInputStream();
int nRead = 1;
int nTotalRead = 0;
byte[] bytes = new byte[10240];
while (nRead > 0) {
nRead = is.read(bytes, nTotalRead, bytes.length - nTotalRead);
if (nRead > 0)
nTotalRead = nTotalRead + nRead;
}
String str = new String(bytes, 0, nTotalRead, "utf-8");
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
QueryString
get方式带参数,请求如http://localhost:8080/demo01/demo01api?name=%E5%BC%A0%E4%B8%89&age=23&score99
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
/**
* @author liyadong
* @create 2022-03-22-16:25
*/
public class demo01servlet extends HttpServlet { //继承HttpServlet类
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做get请求的处理
System.out.println("GET");
String qs = req.getQueryString();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做post请求的处理
System.out.println("POST");
}
}
Form Data
这是请求的数据
注意:这里用的
这是请求头
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
/**
* @author liyadong
* @create 2022-03-22-16:25
*/
public class demo01servlet extends HttpServlet { //继承HttpServlet类
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做get请求的处理
System.out.println("GET");
String qs = req.getQueryString();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做post请求的处理
System.out.println("POST");
req.setCharacterEncoding("UTF-8"); //有中文记得设置编码
String name = req.getParameter("Name");
String age =req.getParameter("Age");
String score=req.getParameter("Score");
}
}
6.Servlet生命周期
Servlet生命周期对应三个方法:init()
service()
destroy()
默认情况下。第一次请求的时候,这个Servlet会进行,实例化(构造方法),初始化(调用init),服务(调用service)
从第二次请求开始,每一次都是服务(service)。
Servlet实例只会创建一个,所有请求都是这个实例去响应。
当容器关闭时,其中的所有servlet实例会被销毁,调用destroy。
第一次请求要实例化,初始化等,可能比较慢,在web.xml里面的<load-on-startup>1</load-on-startup>
,就会在容器启动的时候就加载servlet。第一次请求就不用初始化了。
Servlet是单例的,线程不安全的
7.Session
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
/**
* @author liyadong
* @create 2022-03-22-16:25
*/
public class demo01servlet extends HttpServlet { //继承HttpServlet类
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做get请求的处理
System.out.println("GET");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//做post请求的处理
System.out.println("POST");
//得到session或者生成新的session,新session会在响应头里面Set-Cookie自动发给前端
HttpSession session =req.getSession();//参数传入false表示有就获取,没有就null,不创建新的,默认为true
session.setMaxInactiveInterval(18000);//设置非激活的最大间隔时间,默认1800秒,半个小时不操作,Session就过期了,可以每29分钟操作一次Session,一直在
session.invalidate();//强制性的让会话立即失效
//设置和得到session的值
session.setAttribute("pwd","123456");
session.getAttribute("pwd");
System.out.println(session.getId());
}
}
7.1.逻辑流程
第一次发请求的时候并没有带有SessionIDgetSession()
会自动生成一个Session
响应头会带有一个Set-Cookie
再次刷新页面的时候,网站就保存了这个Sessionid到Cookie里面
而再次发送请求,它会自动携带
带有这个SessionId的请求访问,getSession()
就会得到对应的Session,而不是新建一个Session。通过这个SessionId就能区分开不同的客户端了。
8.服务端转发和客户端重定向
8.1.服务端转发
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
/**
* @author liyadong
* @create 2022-03-22-16:25
*/
public class demo01servlet extends HttpServlet { //继承HttpServlet类
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("执行了demo01");
req.getRequestDispatcher("demo02api").forward(req,res);//转发给demo02api来处理,这个要在web.xml里面配置好
}
}
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.io.IOException;
/**
* @author liyadong
* @create 2022-03-22-22:09
*/
public class demo02servlet extends HttpServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("执行了demo02");
}
}
<?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>
<servlet-name>demo01servlet</servlet-name>
<servlet-class>lyd.servlet.demo01servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo01servlet</servlet-name>
<url-pattern>/demo01api</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>demo02servlet</servlet-name>
<servlet-class>lyd.servlet.demo02servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo02servlet</servlet-name>
<url-pattern>/demo02api</url-pattern>
</servlet-mapping>
</web-app>
8.2.客户端重定向
package lyd.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Collection;
/**
* @author liyadong
* @create 2022-03-22-16:25
*/
public class demo01servlet extends HttpServlet { //继承HttpServlet类
@Override
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
System.out.println("执行了demo01");
res.sendRedirect("demo02api");//客户端重定向,重新发送请求到demo02api
}
}