0%

【JavaWeb】Servlet

关于Servlet的学习


1 Servlet入门

1.1 Servlet介绍

  • Servlet是JavaEE规范之一。规范是接口
  • Servlet是JavaWeb三大组件之一。三大组件分别为:Servlet、Filter、Listener
  • Servlet是运行在服务器上的一个Java小程序,它可以接受客户端发送的请求,并响应数据回客户端

1.2 实现Servlet

  • (1)引入servlet依赖
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!-- tomcat10以下版本 -->
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
    </dependency>

    <!-- tomcat10 -->
    <dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>5.0.0</version>
    <scope>provided</scope>
    </dependency>
  • (2)实现Servlet接口,实现service()方法
    1
    2
    3
    4
    5
    6
    7
    8
    public class HelloServlet implements Servlet {
    // 省略...

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("Hello Servlet!");
    }
    }
  • (3)web.xml配置servlet和其路由路径
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!-- 定义servlet -->
    <servlet>
    <!-- servlet别名 -->
    <servlet-name>HelloServlet</servlet-name>
    <!-- servlet类路径 -->
    <servlet-class>com.letere.servlet.HelloServlet</servlet-class>
    </servlet>

    <!-- 路由与servlet的映射 -->
    <servlet-mapping>
    <!-- 配置映射的servlet名(从上面定义) -->
    <servlet-name>HelloServlet</servlet-name>
    <!-- 访问的路由路径(http://ip:port/工程路径/hello) -->
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  • (4)tomcat启动引入依赖
  • tomcat启动默认不带有jar包,需要自己设置
  • (5)启动测试
  • 访问配置的servlet路由地址,查看后台打印记录

2 Servlet生命周期

  • Servlet构造器方法
  • init初始化方法
  • 以上两种方法是在第一次访问的时候,创建servlet程序时会调用
  • service方法
  • 每次访问一次地址,都会执行一次此方法
  • destroy方法
  • web工程停止运行的时候调用

3 实际开发

3.1 继承HttpServlet实现Servlet

  • (1)实际开发中,一般都是继承HttpServlet来生成Servlet
  • (2)按照不同的请求,重写对应的doGet()、doPost() … 方法
  • (3)将servlet注册到web.xml中
1
2
3
4
5
6
7
8
9
10
11
public class HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// get请求处理 ...
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// post请求处理 ...
}
}

3.2 idea自动生成servlet


4 Servlet继承体系


5 ServletConfig类

  • 作用
  • (1)获取web.xml中的Servlet程序的别名servlet-name的值
  • (2)获取web.xml中的初始化参数init-param
  • (3)获取servletContext对象
  • Config对象获取
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class HelloServlet2 extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
    super.init(config);
    // init方法中使用servletConfig
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 通过getServletConfig方法获取
    ServletConfig config = getServletConfig();
    }
    }
  • 演示
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class HelloServlet2 extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
    super.init(config);
    // 1.获取servlet别名
    String servletName = config.getServletName();
    // 2.获取init-param参数
    String test = config.getInitParameter("test");
    // 3.获取ServletContext对象
    ServletContext context = config.getServletContext();
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    <servlet>
    <servlet-name>HelloServlet2</servlet-name>
    <servlet-class>com.letere.servlet.HelloServlet2</servlet-class>
    <init-param>
    <param-name>test</param-name>
    <param-value>123</param-value>
    </init-param>
    </servlet>

6 ServletContext类

  • 介绍
  • ServletContext是一个接口
  • 一个Web工程只有一个ServletContext对象实例
  • Servlet对象是一个域对象,可以像Map一样存储kv键值对,给其他Servelt共享
  • 作用
  • 获取web.xml中的context-param参数
  • 获取当前工程路径
  • 获取工程在服务器硬盘上的绝对路径
  • 存储、获取、删除kv值
  • 演示
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class ContextServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext context = getServletContext();
    // 1.获取context-param参数
    String common = context.getInitParameter("common");
    // 2.获取当前工程路径
    String contextPath = context.getContextPath();
    // 3.获取工程部署后在服务器磁盘的绝对路径
    String realPath = context.getRealPath("/");
    // 4.设置、获取、删除kv值
    context.setAttribute("key", "value");
    Object value = context.getAttribute("key");
    context.removeAttribute("key");
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <context-param>
    <param-name>common</param-name>
    <param-value>123456</param-value>
    </context-param>
    <servlet>
    <servlet-name>ContextServlet</servlet-name>
    <servlet-class>com.letere.servlet.ContextServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>ContextServlet</servlet-name>
    <url-pattern>/context</url-pattern>
    </servlet-mapping>

7 HTTP协议

  • 介绍
  • 指客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫做HTTP协议,HTTP协议中的数据又叫做报文

7.1 GET请求

  • (1)常规(请求行)
  • (2)请求头

7.2 POST请求

  • (1)常规(请求行)
  • (2)请求头
  • (3)请求体

7.3 常见响应码

  • 200:请求成功
  • 302:请求重定向
  • 404:服务器收到请求,但找不到对应资源(url错误)
  • 500:服务器收到请求,服务器内部出现错误(代码错误)

7.4 MIME类型

  • 介绍
  • 是HTTP协议中的数据类型
  • MIME(Multipurpose Internet Mail Extensions),多功能Internet邮件扩展服务
  • MINE格式:大类型/小类型
文件 后缀名 MINE类型
超文本标记语言文本 .html text/html
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
GIF图形 .gif image/gif
JPEG图形 .jpeg .jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 .mid .midi audio/midi audio/x-midi
RealAudio音乐文件 .ra .ram audio/x-pn-realaudio
MPEG文件 .mpg .mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar

8 HttpServletRequest类

8.1 基本介绍

  • 介绍
  • 每有一个请求,tomcat会将请求封装到Request类中,传递给service()方法提供我们使用,可以通过HttpServletRequest获取请求信息
方法 说明
getRequestURI() 获取请求资源路径
getRequestURL() 获取完整的请求资源路径
getRemoteHost() 获取客户端ip地址
getHeader() 获取请求头
getParamter() 获取请求参数
getParamterValues() 获取请求参数(参数值为多个时使用)
getMothed() 获取请求方式
getRequestDispatcher() 获取请求转发对象
  • 注意
  • Post请求获取请求参数时,若参数为中文,会出现乱码;需要调用方法setCharaterEncoding("UTF-8")来进行设置request编码

8.2 请求转发

  • 将当前请求按照要求,转发给其他服务器/servlet处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 请求转发 -->
<servlet>
<servlet-name>ForwardServlet1</servlet-name>
<servlet-class>com.letere.servlet.forward.ForwardServlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ForwardServlet1</servlet-name>
<url-pattern>/forward1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ForwardServlet2</servlet-name>
<servlet-class>com.letere.servlet.forward.ForwardServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ForwardServlet2</servlet-name>
<url-pattern>/forward2</url-pattern>
</servlet-mapping>
1
2
3
4
5
6
7
8
9
10
public class ForwardServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 请求转发
// (1)转发到servlet
req.getRequestDispatcher("/forward2").forward(req, resp);
// (2)转发到资源文件【WEB-INF是不允许外部链接直接访问】
req.getRequestDispatcher("/WEB-INF/头像.jpg").forward(req, resp);
}
}
1
2
3
4
5
6
public class ForwardServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("这里是forwardServlet2");
}
}

9 HttpServletResponse类

  • 用于设置返回数据给客户端

9.1 两种输出流

  • 字节流:用于返回文件,进行下载
  • 字符流:用户返回字符串
  • 注意:两种流一次只能使用一个,不能同时使用
1
2
3
4
5
6
7
8
9
public class ResponseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// (1)字节流:传入字节数组
resp.getOutputStream().write(new byte[1]);
// (2)字符流:传入字符串
resp.getWriter().write("hello world!");
}
}

9.2 中文乱码

  • 返回字符串为中文时,会出现乱码,需要进行设置
  • 有两种解决方法,选择其中一种即可
1
2
3
4
5
6
7
8
9
10
11
 public class ResponseServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// (1)服务器,浏览器分别设置“UTF-8”
resp.setCharacterEncoding("UTF-8");
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
// (2)一步将服务器和浏览器设置为UTF-8
resp.setContentType("text/html; charset=UTF-8");
resp.getWriter().write("你好啊!");
}
}

9.3 请求重定向

  • 客户端发送请求,服务器告诉客户端此地址已转移,请访问新地址,此行为称为请求转发
  • 重定向写法有两种,择其中一种即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 重定向 -->
<servlet>
<servlet-name>RedirectServlet1</servlet-name>
<servlet-class>com.letere.servlet.redirect.RedirectServlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RedirectServlet1</servlet-name>
<url-pattern>/redirect1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RedirectServlet2</servlet-name>
<servlet-class>com.letere.servlet.redirect.RedirectServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RedirectServlet2</servlet-name>
<url-pattern>/redirect2</url-pattern>
</servlet-mapping>
1
2
3
4
5
6
7
8
9
10
11
public class RedirectServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 请求重定向
// (1)状态码设置302,请求头设置location
resp.setStatus(302);
resp.setHeader("location", "http://localhost:8080/6_Servlet/redirect2");
// (2)一步到位
resp.sendRedirect("http://localhost:8080/6_Servlet/redirect2");
}
}
1
2
3
4
5
6
7
public class RedirectServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=UTF-8");
resp.getWriter().write("这是重定向后的Servlet!");
}
}
  • 重定向特点
  • 浏览器地址栏会发生变化
  • 总共发送两次请求

10 Listener监听器

  • Listener是JavaEE规范,是接口
  • 监听器作用是监听事务的变化,然后同回调函数执行相应的处理
1
2
3
4
5
6
7
8
9
10
11
12
13
// 1 创建一个类继承监听器(以ServletContextListener为例),实现其初始化和销毁方法
public class MyListener implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("web工程创建时调用");
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("web工程销毁时调用");
}
}
1
2
3
4
<!-- 在web.xml中配置监听器 -->
<listener>
<listener-class>com.letere.listener.MyListener</listener-class>
</listener>

11 知识补充

11.1 base标签

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- base标签能够无视地址栏上的地址(最后的'/'不可省略)-->
<base href="http://localhost:8080/6-Servlet/">
</head>
<body>
<!-- 直接以base标签为当前路径进行拼接 -->
<a href="./头像.png"></a>
</body>
</html>