Servlet的概念和使用

Servlet

一、概述

Servlet:Server Applet,是服务器端的一个程序(代码、功能实现),可交互式的处理客户端发送到服务器端的请求,并完成响应操作,实现前后端的交互。

  • 动态网页技术:Servlet、Jsp(el, jstl)、第三方框架(SSM,SSH)。
  • 静态网页技术:HTML、CSS。

二、集成Tomcat

2.1 创建Web项目

IDEA2022为例

  • 首先创建一个新的普通项目

请添加图片描述

  • 右键项目—>添加框架支持—>选中Web项目
    (这里已经创建过了所以没有显示)
    请添加图片描述

2.2 配置tomcat

使用版本为Tomcat 8.5.41

  • 点击右上角启动项目旁边的编辑配置,选中已安装的tomcat,设置可保持默认。

    请添加图片描述

  • 点击部署添加启动时部署

    请添加图片描述

  • 导入Servlet.jar包

    在WEB-INF下创建lib包,将apache-tomcat-8.5.41.zip添加到库
    请添加图片描述

  • 可能遇到的问题

    • tomcat版本过高会出现可能会出现404 NOT FOUND此时可以下降tomcat的版本。

    • 其他问题可上网查找,一般可解决大部分问题。

    • <!--如果tomcat中配置的路径含有项目名,则action属性值不加/
           如果配置的路径为只有/ 则action需要加/-->
      

2.3 测试

  • 点击运行,运行成功会弹出网页。

请添加图片描述

三、Servlet的三种实现方式

3.1 实现原生的Servlet接口

	package lhnservetest;

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

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: lhnservetest
 * @Author: LiHaoNan
 * @Date: 2022/6/30 9:24
 * @Description:
 */
@WebServlet("/demo1")
public class ServletTest implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("初始化方法");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("处理业务核心方法");

    }

    @Override
    public String getServletInfo() {
        System.out.println("获取servlet的信息");
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("销毁");

    }
}

3.2 继承GenericServlet

  • 使得servlet的编写更加简单,它提供了生命周期的init方法和destory方法的简单实现;如果需要写servlet时,只需重写抽象的service方法即可。
  • GenericServlet是Servlet的接口类。
  • 缺点:不区分请求类型
package lhnservetest;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: lhnservetest
 * @Author: LiHaoNan
 * @Date: 2022/6/30 9:42
 * @Description:
 */

@WebServlet("/demo2")
public class GenricServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("只需重写servlet方法即可");

    }
}

3.3 继承HttpServlet

  • HttpServlet是继承GenericServlet,在其基础上对service功能进行了拓展提升。

  • 为符合http的协议的开发规范,对service方法进行了重构,产生了两个新方法:

    doGet() 和 doPost()

    • doGet():支持HTTP的GET请求。
    • doPost():支持HTTP的POST请求。
  • HttpServletRequest、HttpServletResponse

package lhnservetest;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: lhnservetest
 * @Author: LiHaoNan
 * @Date: 2022/6/30 9:50
 * @Description:
 */
@WebServlet(name="/demo1",urlPatterns = "/demoHttpServlet",loadOnStartup = -1)
public class HttpServlet extends javax.servlet.http.HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("初始化servlet");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("统一处理请求");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //不管请求的方式是get还是post,处理请求都在doGet中处理
        doGet(req,resp);
    }
}

四、Servlet的两种配置方式

4.1 xml配置文件

在servlet2.5以前使用

<?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>
        <!-- 自定义名称-->
        <servlet-name>demo1</servlet-name>
        <!-- Servlet全称类名-->
        <servlet-class>lhnservetest.HttpServlet</servlet-class>
        <!-- 启动优先级,越低,优先级越高-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- 映射配置-->
    <servlet-mapping>
        <!-- 自定义名称-->
        <servlet-name>demo1</servlet-name>
        <!-- 资源配置路径-->
        <url-pattern>/demoHttpServlet</url-pattern>
    </servlet-mapping>

</web-app>


4.2 @webservlet注解的配置方式

在servlet3.0以后才可用

  • 注解常用属性
    • name servlet: 名称
    • value: 配置servlet的访问路径,可配置多个
    • urlPatterns: 配置servlet的访问路径,可配置多个,不可用和value同时使用
    • loadOnStartup:优先级
@WebServlet(name="/demo1",urlPatterns = "/demoHttpServlet",loadOnStartup = 1)
@WebServlet("/demo3")
  • url-pattern规则

    • 精确匹配:/具体的名称;/demo1 只有在访问路径名完全一样时才会访问到。
    • 后缀匹配:/*.xxx; 例如 : 匹配的时结尾为/.jsp的请求才可以访问。
    • 通配符匹配:/* 匹配所有的请求,包括服务器中的所有资源。
    • 通配符匹配:/ 匹配所有请求,但不包括.jsp结尾的请求。
  • load_on_startup

    • web应用程序是否在启动时进行加载,默认不加载。
    • 值必须为整数,表示servlet被加载的前后顺序。
    • 值如果为负,或者没有设置,容器会在servlet被请求时,对此servlet进行加载。
    • 值如果为正整数或者0时,表示在容器启动时加载servlet,值越小,加载优先级越高。

五、案例:在前端页面展示所有数据

项目分级

请添加图片描述

数据库查询操作参照JDBC

package servlet;

import entity.Stu;
import service.impl.StuServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: servlet
 * @Author: LiHaoNan
 * @Date: 2022/6/30 11:43
 * @Description:showAllStuServlet
 */
@WebServlet("/showAllStuServlet")
public class ShowAllStuServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        StuServiceImpl stuService=new StuServiceImpl();
        //通过服务获取全部数据
        List<Stu>stus=stuService.showALLStu();
        //向前端页面发送数据

        //直接展示一个html页面
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().print("<!DOCTYPE html>\n" +
                "<html lang=\"en\">\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <title>Title</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "     <table>\n" +
                "\n" +
                "         <thead>\n" +
                "         <tr>\n" +
                "             <td>ID</td>\n" +
                "             <td>UserName</td>\n" +
                "             <td>PassWord</td>\n" +
                "             <td>Sex</td>\n" +
                "         </tr>\n" +
                "         </thead>\n" +
                "\n" +
                "        <tbody>");
        for(Stu stu:stus){//拼接获取的数据到表头下

            resp.getWriter().append(" <tr>\n" +
                    "            <td>"+stu.getId()+"</td>\n" +
                    "            <td>"+stu.getUsername()+"</td>\n" +
                    "            <td>"+stu.getPassword()+"</td>\n" +
                    "            <td>"+stu.getSex()+"</td>\n" +
                    "        </tr>");
        }

        resp.getWriter().append(" </tbody>\n" +
                "\n" +
                "     </table>\n" +
                "</body>\n" +
                "</html>");


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);

    }
}

效果:

请添加图片描述

六、转发和重定向

  • 现有的问题:
    • 一个servlet既做了数据解析,又做了展示页面的功能,违背了功能单一性。
    • 一个servlet只做数据解析和响应。
    • 一个servlet只做页面响应。

那么两个servlet之间如何相互访问。

6.1转发

定义:一次请求,经过多次资源访问,跳转了多次,但是地址栏不发生改变。

  • 转发发生在服务器端,将请求发送给服务器端的其他资源,以共同完成一次请求的过程。

    req.getRequestDispatcher("showPageServlet?username=李浩楠").forward(req,resp);//放的是URL路径,req即为request作用域
    

数据传递

  • forward:代表一次请求,是服务器内部进行跳转,可以共享request作用域中的所有数据。

    • request作用域:拥有存储数据的空间,在一次请求的过程中的任何位置都可以获取。

    • 可以传递任意类型的数据。

    • 存数据:

      request.setAttribute(key,value);
      
    • 取数据:

      req.getAttribute(key,value);
      

特点

  • 转发是服务器行为。
  • 转发时游览器只发起一次请求。
  • 转发游览器地址栏内容不变。
  • 转发多次跳转之间传递的数据不会丢失。
  • 转发只能将请求发送给同一个web组件中的资源。

6.2 重定向

  • 发生在客户端,客户端将请求发送给服务器之后,服务器响应给客户端一个新的请求地址,客户端再次发起一个请求。

    resp.sendRedirect("showPageServlet");
    

数据传递

  • response:没有作用域,两次请求之间的数据无法共享。
  • 传递数据:通过URL路径拼接的方式传递数据(“showPageServlet?uername=123&password=123”)
  • 获取数据:req.getParameter();

特点

  • 重定向是客户端行为。
  • 重定向至少发起了两次请求。
  • 重定向地址栏发生改变。
  • 重定向多次请求之间无法传递数据。
  • 重定向可以指向任意资源,包括当前应用程序中的资源,也包括同一站点上的其他资源,以及其他站点的资源。

6.3 get和post的区别

  • get
    • get提交的数据会放在URL之后,以?分割,参数之间以&符号连接。
    • get以明文方式传递数据,数据量小,不安全。
    • 效率高,游览器默认的访问方式为GET。
    • 对应的Servlet方法为doGet();
  • post
    • post方法将提交的数据Http请求中。
    • 密文传递数据,进行一次加密(md5等),数据量大,安全。
    • 效率相对于GET低。
    • 对应的Servlet方法为doPost();

七、生命周期

servlet生命周期的四个阶段

  1. 实例化:当用户第一次访问servlet时,由容器调用servlet的构造方法创建一个具体的servlet对象;也可以在容器启动后立即创建实例对象,通过代码设置属性值为1;

    注意:只执行一次

  2. 初始化:调用init()方法,通过ServletConfig类进行初始化。

  3. 服务:调用service方法(例如HttpServlet中的doget()和dopost());

  4. 销毁:destory()方法;只执行一次

流程

客户端发起请求—>容器(tomcat)解析请求—>创建servlet实例—>调用init()方法来进行初始化—>调用service()方法解析请求—>输出响应—>响应请求—>销毁servlet

八、Cookie和Session

8.1 Cookie

  • Cookie是在游览器访问web服务器某个资源时,由web服务器在HTTP响应头中附带传送的一小段数据。
  • 一旦某个游览器存储了某个Cookie,在之后访问对应的web服务时,都应在HTTP请求头中携带此Cookie,把Cookie回传给服务器。
  • 一个Cookie由标识该信息的名称(name)和值(value)组成。
8.1.1 添加Cookie
package test;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: test
 * @Author: LiHaoNan
 * @Date: 2022/7/1 10:02
 * @Description:
 */
@WebServlet("/addCookie")
public class CookieTestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建Cookie对象
        Cookie cookie=new Cookie("20220701","java实训");
        //设置过期时间 三种取值 >0 有效期,单位:秒  ;=0 游览器关闭失效; <0 内存存储,默认-1
        cookie.setMaxAge(3600);
        //设置访问路径
        cookie.setPath("/");
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

8.1.2 获取Cookie
package test;

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

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: test
 * @Author: LiHaoNan
 * @Date: 2022/7/1 10:11
 * @Description:
 */
@WebServlet("/getCookie")
public class GetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求中携带的cookie
        Cookie[]cookies=req.getCookies();

        for(Cookie cookie:cookies){
            //检索cookie getName()获取cookie名称, getValue()获取cookie值
            if(cookie.getName().equals("20220701")){
                System.out.println("20220701:"+cookie.getValue());
                break;
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

8.1.3 修改Cookie

只需保证Cookie的名和路径一致即可

package test;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: test
 * @Author: LiHaoNan
 * @Date: 2022/7/1 10:18
 * @Description:
 */
@WebServlet("/updateCookie")
public class UpdateCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie cookie=new Cookie("20220701","峡~谷~~之~~巅,爱慕未批,mvp~~15.4的鳄鱼");
        cookie.setPath("/");
        cookie.setMaxAge(-1);
        resp.addCookie(cookie);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req,resp);
    }
}

8.1.4 Cookie优缺点
  • 优点
    • 可以配置到期规则。
    • 简单:一个基于文本的轻量型结构,只包含键值对。
    • 数据持久性:cookie默认在过期之前一直保存在客户端的游览器上
  • 缺点
    • 大小受到限制,4K-8k
    • 用户可设置成禁用。
    • 潜在的安全风险,cookie可以被篡改。

8.2 Session

Session记录用户的状态。session指的是在一段时间内,单个客户端与服务器之间的一连串相互交互的过程。

在一个Session中,客户端可能会发起多次请求,可以访问一个资源,或者多个资源,session对象不变

8.2.1 原理
  • 服务器会为每一个会话分配一个session对象。
  • 同一个游览器不管发起多少此请求,只要游览器没有关闭,都属于同一个会话。
  • 首次使用session时,服务器会自动创建session,并创建Cookie保存SessionID发送回客户端。
8.2.2 Session使用
  • 作用域:拥有存储数据的空间,范围是一次会话有效。

    • 一次会话是同一个游览器发送的多次请求。一旦游览器关闭,则会话结束。

    • 可以将数据存入Session作用域中,在作用域中的任何位置都可以获取。

    • 可以传递任意类型的值。

      package test;
      
      import javax.servlet.ServletException;
      import javax.servlet.annotation.WebServlet;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import javax.servlet.http.HttpSession;
      import java.io.IOException;
      
      /**
       * @BelongsProject: testservlet0630
       * @BelongsPackage: test
       * @Author: LiHaoNan
       * @Date: 2022/7/1 11:03
       * @Description:
       */
      @WebServlet("/testsession")
      public class TestSessionServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //获取Session对象
              HttpSession session=req.getSession();
              //存值
              session.setAttribute("username","李浩楠");
              //取值
              String username=(String) session.getAttribute("username");
              //移除作用域中的值
              session.removeAttribute("username");
      
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req,resp);
          }
      }
      
      
8.2.3 Session和request的区别
  • request是一次请求有效,请求改变,则request改变。

  • session是一次会话有效,游览器改变,则session改变。

    • tomcat中可设定session的过期时间
        <session-config>
            <session-timeout>30</session-timeout>
        </session-config>
    
8.2.4 验证码

生成验证码通过ValidateCode.jar包来实现

package servlet;

import cn.dsna.util.images.ValidateCode;

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

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: servlet
 * @Author: LiHaoNan
 * @Date: 2022/7/1 11:20
 * @Description:
 */
@WebServlet("/createCode")
public class CreateCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //生成验证码的类
      ValidateCode validateCode= new ValidateCode(200,30,4,10);
      //获取生成的验证码
      String code=validateCode.getCode();
      System.out.println("生成的验证码:"+code);
      //存入session
        req.getSession().setAttribute("code",code);
        //把生成的验证码图片返回给前端,输出到前端
        validateCode.write(resp.getOutputStream());

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--如果tomcat中配置的路径含有项目名,则action属性值不加/
     如果配置的路径为只有/ 则action需要加/-->
      <form action="verifyCodeServlet"method="get">
          用户名:<input type="text" name="username"\n>
          密码:<input type="text" name="password"\n>
          验证码:<input type="text" name="code"\n>
          <img src="createCode">
          <input type="submit" value="登录">
      </form>
</body>
</html>

验证码输入是否正确

package servlet;

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

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: servlet
 * @Author: LiHaoNan
 * @Date: 2022/7/1 11:27
 * @Description:
 */
@WebServlet("/verifyCodeServlet")
public class VerifyCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //前端传递的code
        String code=req.getParameter("code");
        //生成的code码
        String mgrcode=(String) req.getSession().getAttribute("code");
        //判断验证码是否正确,STRING内容是否相同,不区分大小写
        // code.equalsIgnoreCase(mgrcode)不区分大小写的比较方法
        // code.isEmpty()判空操作
        if(code.equalsIgnoreCase(mgrcode)&&!code.isEmpty()){
            System.out.println("验证通过!");
        }else {
            System.out.println("验证失败!");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

效果:
请添加图片描述
请添加图片描述

九、ServletContext

9.1 概述

  • 全局对象,拥有作用域,对应Tomcat中的一个web应用。
  • 当web服务器启动时,会自动的为每一个web应用分配一个共享的内存空间。
  • servletContext 在web服务器启动时创建,服务器关闭时销毁。

9.2 获取对象

  1. GenericServlet提供了一个方法getServletContext();(注:推荐使用
  2. HttpServlet提供了一个方法getServletContext();(注:推荐使用
  3. HttpSession对象提供了一个方法getServletContext();(做了解)

9.3 作用

     //如何获取tomcat中web应用的真实路径
        ServletContext servletContext=req.getServletContext();
        String realPath=req.getServletContext().getRealPath("\\img");
        System.out.println(realPath)
  //获取应用程序名称
        System.out.println(servletContext.getContextPath());
        System.out.println(req.getContextPath());
  • 存储数据:servletContext.setAttribute(key,value);
  • 获取数据:servletContext.getAttribute(key);
  • 移除数据:servletContext.removeAttribute(key);

9.4 特点

  • 唯一性:一个应用程序只对应一个servletContext。
  • 生命周期:只要应用不关闭或者应用不卸载,servletContext对象一直存在。

9.5 案例:记录程序的访问次数

package day0702;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: day0702
 * @Author: LiHaoNan
 * @Date: 2022/7/2 9:10
 * @Description:
 */
@WebServlet("/countServlet")
public class CountServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取servletContext对象
        ServletContext application =req.getServletContext();
        //每次访问此servlet时,作用域中的某个值自增

        /*基本数据类型  包装类
        * int Integer
        * char Character
        * byte Byte
        * long Long
        * double Double
        * float Float
        * boolen Boolen
        * short Short
        * */
        Integer count=( Integer)application.getAttribute("count");

        //当第一次访问时,count不存在
        if(count==null){
            count=1;
//            application.setAttribute("count",count);
        }
        else{
            count++;
        }
        //返回前端页面
        resp.setContentType("text/html;charset=UTF-8");
        application.setAttribute("count",count);
        resp.getWriter().write("servlet的访问次数为:"+count);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

十、过滤器

Filter

  • 概念:是处于客户端和服务器之间的一道过滤技术。
  • 作用:执行地位在servlet之前,客户端发送请求时,会经过filter,再到达目标的servlet,响应时,再次反向执行filer,之后到达客户端。
  • 可以解决多个servlet之间代码冗余的问题。例:前端编码设置

10.1 实现

  • 编写java类实现filter接口
  • 在doFilter中写拦截逻辑
package entity.filter;

import com.alibaba.druid.proxy.jdbc.DataSourceProxy;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.util.logging.LogRecord;

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: entity.filter
 * @Author: LiHaoNan
 * @Date: 2022/7/2 9:56
 * @Description:
 */
@WebFilter("/*")
public class TestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    }
}

10.2 配置

  • 在自定义的Filter类上加一个@WebFilter注解即可

  • xml

        <filter>
            <!--   自定义名称-->
            <filter-name>demo1</filter-name>
            <!--   过滤器全称类名-->
            <filter-class>entity.filter.TestFilter</filter-class>
        </filter>
        <!--   映射配置-->
        <filter-mapping>
            <!--   自定义名称 和filter对应-->
            <filter-name>demo1</filter-name>
            <url-pattern>/countServlet</url-pattern>
        </filter-mapping>
    
  • 过滤器路径

    • 精确过滤匹配:/countServlet /index.jsp
    • 后缀过滤匹配:/*.jsp等
    • 通配符匹配:/* 拦截所有请求;不能使用/进行匹配。/aaa/bbb/*.jsp,表示aaa文件夹下bbb的所有.jsp文件

10.3 过滤器链和优先级

10.3.1 过滤器链
  • 客户端对服务器发起一个请求后,服务器调用servlet之前会先执行一组过滤器(多个过滤器),那么这一组过滤器就成为过滤器链。

  • 每个过滤器都有特定的功能,当第一个filter的doFilter()被调用时,web服务器会创建一个代表filter链的filterChain对象传送给dofilter(),如果开发人员调用了filterchain中的dofilter方法,则web服务器会检查filterChain中是否还有filter,如果有,则调用第二个filter,如果没有则调用目标资源。

10.3.2 优先级
  • 如果都为注解,按照类名全称的字符串顺序决定执行顺序。abc 、abb:abb先执行。
  • 如果是web.xml,是按照注册的先后顺序执行。
  • web.xml的优先级高于注解。
  • 如果同时配置,不会报错,会创建多个过滤器对象,对目标资源过滤多次。
10.3.3 实例(处理乱码)
package entity.filter;

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

/**
 * @BelongsProject: testservlet0630
 * @BelongsPackage: entity.filter
 * @Author: LiHaoNan
 * @Date: 2022/7/2 10:21
 * @Description: 处理乱码
 */
public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        servletRequest.setCharacterEncoding("UTF-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

10.4 案例

  1. 登录:验证码、验证是否已经登录。

  2. 注册:验证两次输入的密码一致。

  3. 展示信息:展示所有用户的信息。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寥寥楠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值