当前位置:   article > 正文

【JavaWeb】Servlet与过滤器

【JavaWeb】Servlet与过滤器

Servlet

  • Server+Applet,是一种服务器端的Java应用程序
  • 只有当一个服务器端的程序使用了Servlet API的时候,这个服务端的程序才能称之为Servlet
  • Servlet是JavaWeb三大组件之一,三大组件是:Servlet程序、Filter过滤器、Listener监听器
  • Servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的请求,并响应数据给客户端

Servlet做了什么

  • 本身不做任何业务处理
  • 只是接收请求并决定调用哪个JavaBean去处理请求
  • 确定用哪个页面来显示处理返回的数据

JSP与Servlet的关系

在这里插入图片描述Servlet是运行在服务器端的Java应用程序

主要Servlet API介绍

  • javax.servlet.Servlet接口
    所有Java Servlet的基础接口类,规定了必须由Servlet具体类实现的方法集
  • javax.servlet.GenericServlet类
    是Servlet的通用版本,是一种与协议无关的Servlet
  • javax.servlet.http.HttpServlet类
    在GenericServlet基础上扩展的基于Http协议的Servlet

如何创建Servlet

  • 实现Servlet接口
  • 继承GenericServlet类
  • 继承HttpServlet类

Servlet中主要方法

  • init():Servlet的初始化方法,仅仅会执行一次
  • service():处理请求和生成响应
  • destroy():在服务器停止并且程序中的Servlet对象不再使用的时候调用,只执行一次

ServletRequest

  • 封装客户的请求信息
  • 作用相当于JSP内置对象request

ServletResponse

  • 创建响应信息,将处理结果返回给客户端
  • 作用相当于JSP内置对象response

ServletConfig

  • 包含了Servlet的初始化参数信息

Servlet生命周期

  1. 加载和实例化
  2. 初始化
  3. 处理请求
  4. 销毁
生命周期谁来做何时做
实例化Servlet 容器当Servlet容器启动或者容器检测到客户端请求时
初始化Servlet 容器实例化后,容器调用Servlet的init()初始化对象
处理请求Servlet 容器得到客户端请求并做出处理时
销毁Servlet 容器当程序中的Servlet对象不再使用的时候,或者Web服务器停止运行的时候

在这里插入图片描述

Servlet创建

package com.zjl.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author: zjl
 * @datetime: 2024/4/10
 * @desc:
 */
public class HelloServlet extends HttpServlet {
    public HelloServlet() {
        System.out.println("生命周期之——————创建实例");
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        String mycharset = config.getInitParameter("mycharset");
        System.out.println("初始化时加载配置中的参数为:" + mycharset);
        System.out.println("生命周期之——————初始化");
    }

    //接收Get请求
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("生命周期之——————处理请求");
        req.setCharacterEncoding("UTF-8");//设置请求字符集编码
        resp.setCharacterEncoding("UTF-8");//设置响应字符集编码
        req.setAttribute("key","value");//将数据保存在request域,以键值对方式
        req.getSession().setAttribute("sessionKey","sessionValue");//根据request获取所在的session会话,并向会话保存一个数据
        req.getRequestDispatcher("welcome.jsp").forward(req,resp);//转发跳转页面
    }
    //接收POST请求
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("生命周期之——————处理请求");
    }

    /*@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("生命周期之——————处理请求");
    }*/
    @Override
    public void destroy() {
        System.out.println("生命周期之——————销毁");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

Servlet部署与运行

  • 修改web.xml(部署描述文件)
    • 添加:把Servlet内部名映射到一个Servlet类名
    • 添加:把用户访问的URL映射到Servlet的内部名
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.zjl.servlet.HelloServlet</servlet-class>
    <init-param>
      <param-name>mycharset</param-name>
      <param-value>utf-t</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello.do</url-pattern>
  </servlet-mapping>
</web-app>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 通过URL访问Servlet
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

ServletConfig类

  • ServletConfig类从类名上来看,就知道是Servlet程序的配置信息类
  • Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责调用
  • Servlet程序默认是第一次访问的时候创建,ServletCongfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象

ServletConfig类的三大作用

  1. 可以获取Servlet程序的别名servlet-name的值
  2. 获取初始化参数init-param
  3. 获取ServletContext对象
	@Override
    public void init(ServletConfig config) throws ServletException {
        String mycharset = config.getInitParameter("mycharset");
        System.out.println("初始化时加载配置中的参数为:" + mycharset);
        System.out.println("生命周期之——————初始化");
        config.getServletContext();
        config.getServletName();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

ServletContext类

  1. ServletContext是一个接口,它表示Servlet上下文对象
  2. 一个web工程,只有一个ServletContext对象实例
  3. ServletContext对象是一个域对象
  4. ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁

域对象:是可以像Map一样存取数据的对象
这里的域指的是存取数据的操作范围是整个web工程

存数据取数据删除数据
Mapput()get()
域对象setAttribute()getAttribute()

ServletContext类的四个作用

  1. 获取web.xml中配置的上下文参数context-param
    属于整个工程,也就是说所有的Servlet都可以访问到
<!--context-param是上下文参数(它属于整个web工程)-->
<context-param>
  <param-name>username</param-name>
  <param-value>context</param-value>
</context-param>
<!--context-param是上下文参数(它属于整个web工程)-->
<context-param>
  <param-name>password</param-name>
  <param-value>root</param-value>
</context-param>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 获取当前的工程路径,格式:/工程路径
//2、获取当前的工程路径,格式: /工程路径
System.out.println("当前工程路径:" + servletContext.getContextPath());
  • 1
  • 2
  1. 获取工程部署后在服务器硬盘上的绝对路径
	@Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取工程部署后在服务器硬盘上的绝对路径
        /**
         *      / 斜杠被服务器解析地址为http://ip:port/工程名/  映射到IDEA代码的web目录
         */
        System.out.println("工程部署的路径是:" + servletContext.getRealPath("/"));
        System.out.println("工程下imgs目录的绝对路径是:" + servletContext.getRealPath("/imgs"));
        System.out.println("工程下imgs目录下1.jpg的绝对路径是:" + servletContext.getRealPath("/imgs/1.jpg"));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 像Map一样存取数据
  • 当我们存储之前,还未存储的时候,此时去获取数据,是获取不到即返回null
  • 一个web工程,只有一个ServletContext对象实例,因此地址一致
	@Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取ServletContext对象
        ServletContext servletContext = getServletContext();
        // System.out.println(servletContext);
        System.out.println("保存之前Context1 中获取域数据key1的值是:" + servletContext.getAttribute("key1"));

        servletContext.setAttribute("key1", "value1");

        System.out.println("Context1 中获取域数据key1的值是:" + servletContext.getAttribute("key1"));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

HTTP协议

  • 协议是指双方、或多方,相互约定好的,大家都需要遵守的规则,叫协议
  • 所谓HTTP协议,就是指:客户端和服务端之间通信时,发送的数据,需要遵守的规则,叫HTTP协议
  • HTTP协议中的数据又叫报文
  • 客户端给服务器发送数据叫请求
  • 服务器给客户端回传数据叫响应

GET请求和POST请求

GET

格式
  1. 请求行
    请求的方式
    请求的资源路径[+?+请求参数]
    请求的协议的版本号
  2. 请求头
    key : value 组成,不同的键值对,表示不同的含义
    在这里插入图片描述在这里插入图片描述

POST

格式
  1. 请求行
    请求的方式
    请求的资源路径[+?+请求参数]
    请求的协议的版本号
  2. 请求头
    key : value 组成,不同的键值对,表示不同的含义
  3. 请求体 ==> 就是发送给服务器的数据
    在这里插入图片描述在这里插入图片描述

常用的请求头的说明

  • Accept:表示客户端可以接受的数据类型
  • Accpet-Language:表示客户端可以接受的语言类型
  • User-Agent:表示客户端浏览器的信号
  • Host:表示请求时的服务器ip和端口号

GET请求和POST请求的种类(即哪些是)

GET请求有:
  1. form 标签 method=“get”
  2. a 标签
  3. link 标签引入 css 文件
  4. Script 标签引入 js 文件
  5. img 标签引入图片
  6. iframe 引入 html 页面
  7. 在浏览器地址栏中输入地址后敲回车

POST请求有:

  • form 标签 method=“post”

响应的HTTP协议格式

  1. 响应行
    响应的协议和版本号
    响应状态码
    响应状态描述符

  2. 响应头
    key : value 不同的响应头,有其不同的含义

  3. 响应体 ==> 就是回传给客户端的数据
    在这里插入图片描述在这里插入图片描述

常用的响应码

响应码说明
200表示请求成功
302表示请求重定向
404表示请求服务器以及收到了,但是你要的数据不存在(请求地址错误)
500表示服务器已经收到请求,但是服务器内部错误(代码错误)

MIME类型说明

  • MIME是HTTP协议中的数据类型
  • MIME 的英文全称是"Multipurpose Internet Mail Extensions" 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应
常见的MIME类型
文件MIME类型
超文本标记语言文本.html, .htm text/html
普通文本 .txt text/plain
RTF文本.rtf application/rtf
GIF图形.gif image/gif
JDEG图形.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

HttpServletRequest类

  • 对应JSP的内置对象request
  • 每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中,然后传递到service方法或doGet方法或doPost方法中给我们使用。而我们可以通过HttpServletRequest对象,获取到所有请求的信息
  • 普通的访问无法访问到WEB-INF目录下的内容,但是请求转发可以访问到
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/form.html");
  • 1
  • 无法访问工程以外的资源,因为默认放本工程目录下
RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.baidu.com");//会报错
  • 1

常用方法

方法名作用
getRequestURI()获取请求的资源路径
getRequestURL()获取请求的统一资源定位符(绝对路径)
getRemoteHost()获取客户端的ip地址
getHeader()获取请求头
getParameter()获取请求的参数
getParameterValues()获取请求的参数(多个值的时候使用)[如复选框]
getMethod()获取请求的方式GET或POST
setAttribute(key, value)设置域数据
getAttribute(key)获取域数据
getRequestDispatcher()获取请求转发对象

HttpServletResponse类

  • 对应JSP内置对象response
  • HttpServletResponse类和HttpServletRequest类一样,每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息
  • 我们如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置
  • 不共享Request域中数据
  • 不能访问WEB-INF下的资源。是因为WEB-INF是受保护的,而浏览器是不能够访问受保护的,当重新第二次到新地址,也是浏览器发送请求,因此不能访问到受保护的WEB-INF目录
  • 可以访问工程下的资源
类别表示作用
字节流getOutputStream()常用于下载(传递二进制数据)
字符流getWriter()常用于回传字符串(常用)

注意:两个流同时只能使用一个
使用了字节流,就不能再使用字符流了,反之亦然,否则就会报错

@WebServlet注解

  • 在Servlet中,设置了@WebServlet注解,当请求该Servlet时,服务器就会自动读取当中的信息

  • 如果注解@WebServlet(“/category”),则表示该Servlet默认的请求路径为…/category,这里省略了urlPatterns属性名,完整的写法应该是:@WebServlet(urlPatterns = “/category”)

  • 如果在@WebServlet中需要设置多个属性,必须给属性值加上属性名称,中间用逗号隔开,否则会报错.

  • 若没有设置@WebServlet的name属性,默认值会是Servlet的类完整名称.

  • 在servlet3.0以后,web.xml中对Servlet配置,同样可以在@WebServlet注解中配置.

属性列表

属性名类型描述
nameString指定Servlet 的 name 属性,等价于 。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。
valueString[]该属性等价于 urlPatterns 属性。两个属性不能同时使用。
urlPatternsString[]指定一组 Servlet 的 URL 匹配模式。等价于标签。
loadOnStartupint指定 Servlet 的加载顺序,等价于 标签。
initParamsWebInitParam[]指定一组 Servlet 初始化参数,等价于标签。
asyncSupportedboolean声明 Servlet 是否支持异步操作模式,等价于 标签。
descriptionString该 Servlet 的描述信息,等价于 标签。
displayNameString该 Servlet 的显示名,通常配合工具使用,等价于 标签。

过滤器

拦截所有访问web资源的请求或者响应(servlet、Jsp页面、HTML页面),从而实现我们自己的业务逻辑,这些逻辑可以是实现访问权限的控制、过滤敏感词、压缩响应等功能。

  • 是向Web应用程序的请求和响应添加功能的Web服务组件
  • 过滤器可以统一地集中处理请求和响应
  • 使用过滤器技术实现对请求数据的过滤

原理

过滤器是"链接"在容器的处理过程中的,它会在servlet处理器之前访问进入的请求,并且在响应信息返回客服端之前访问这些响应信息。这样就可以动态的修改请求和响应中的内容。
在这里插入图片描述在这里插入图片描述

代码

package com.zjl.filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author: zjl
 * @datetime: 2024/4/10
 * @desc:
 */
public class MyCharsetFilter implements Filter {
    private String encode;
    public MyCharsetFilter(){
        System.out.println("生命周期之——创建");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        encode = filterConfig.getInitParameter("encode");
        System.out.println("生命周期之——初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("生命周期之——执行过滤");
        servletResponse.setCharacterEncoding(encode);
        servletRequest.setCharacterEncoding(encode);
        filterChain.doFilter(servletRequest,servletResponse);//执行过滤
    }

    @Override
    public void destroy() {
        System.out.println("生命周期之——销毁");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

配置

<filter>
    <filter-name>mycharset</filter-name>
    <filter-class>com.zjl.filter.MyCharsetFilter</filter-class>
    <init-param>
      <param-name>encode</param-name>
      <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>mycharset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

生命周期

  • 实例化
  • 初始化:init()
  • 过滤:doFilter()
  • 销毁:destroy()

destroy()

  • 当web服务器调用该方法时,表示过滤器将被销毁。

init()

  • 当web服务器调用该方法时,表示过滤器将被注册到服务中

doFilter()

  • 当服务器调用Filter中的doFilter()方法,它会将每一个请求或者响应传递给下一个资源

备注

  • Filter是在应用启动是被创建和初始化的。
  • Filter是单例多线程的(创建和初始化只会被执行一次)
  • doFilter()方法无论是那一个线程访问,只要由该Filter进行过滤,那么就会执行该Filter的doFilter()方法,并且是每过滤一次就会执行一次doFilter()。
  • Filter中destroy方法是在应用被停止时调用的,它意味着销毁这个Filter。
  • FilterConfig指的是Filter在web.xml中的注册信息 ,它将注册信息进行封装,然后通过形参的方式传给初始化方法

<filter-mapping>

  • <filter-mapping>标签表示拦截匹配,也就是要拦截那些请求。
  • <filter-name>:要拦截的过滤器名称
  • <url-pattern>:拦截那些路径

<url-pattern>

  • 注意Filter中在写拦截所有路径的时候只能写成/*,而不能写成/,因为写成/它就不走拦截器中的doFilter方法了。

  • 在Servlet中/*即会拦截动态资源又会拦截静态资源,而/不会拦截动态资源

Filter里面的标签

  • dispatcher表示分发器,表示过滤器所拦截的资源被servlet容器调用的方式,可以是REQUEST,INCLUDE,FORWARD,ERROR中的任何一个,默认是REQUEST。
  • 用户可以设置多个<dispatcher>子元素用来指定过滤器对资源的多种调用方式进行拦截。
属性作用
FORWARD表示当前过滤器只会拦截由一个Servlet通过RequestDispatcher的forward()完成跳转
INCLUDE表示当前过滤器只会拦截由一个Servlet通过RequestDispatcher的include()完成跳转
REQUEST表示当前过滤器会拦截普通请求,但对于forward()与include()的跳转不进行拦截,REQUEST是默认的。
ERROR表示当跳转到指定的错误处理页面时,这个跳转请求会被当前过滤器拦截

过滤器链

多个过滤器会形成过滤器链
在这里插入图片描述

总结:执行原理

Servlet的执行原理:

  • 在Servlet中有两个Map,这两个Map的key均为Servlet注册时的值,但value是不同的。第一个Map的value是Servlet实例对象的引用,第二个Map的value为的值,即Servlet类的全限定类名。

  • 当对Servlet的请求到达Servlet容器时,会先对请求进行解析,使用该解析出的URL,作为比较对象,从第一个Map中查找是否有匹配的key,若不存在匹配的key,那么读取其value,即Servlet对象的引用,执行该Servlet的service()方法。

  • 若不存在匹配的key ,那么再从第二个Map中查找是否有匹配的key。若存在,这读取其value,即读取其value,即要访问的Servlet的全限定类名。然后使用反射机制创建该Servlet实例,并将该实例写入到第一个Map中,然后在执行该Servlet的service()方法。

  • 若第二个Map中也没有找到匹配的key,那么就跳转到错误处理页面404。

Filter的执行原理:

  • 一个数组与一个Map :

    • 一个Map:Map的key为的值,value为Filter实例对象的引用
    • 一个数组:存在着与请求相匹配的所有Filter
  • 当对某资源的请求到达Web容器时,会先对请求进行解析,使用解析出的URI作为比较对象,从Map中查找是否存在相匹配的key。若存在,那么读取其value,即Filter对象的引用,将该应用存入到数组中。然后继续向后查找,直到将Map查找完毕。这样在数组中就会存在按照查找顺序排好序的Filter引用。

  • 数组初始化完毕后,开始按照数组元素顺序进行执行。所有数组中的Filter全部执行完毕后,再跳转到请求的目标资源。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/404644
推荐阅读
  

闽ICP备14008679号