Servlet

本文介绍了XML的DTD约束和Schema约束,强调了它们在确保数据安全性和有效性方面的作用。接着,文章转向Java中XML的解析,包括DOM和SAX解析方式以及相关库如jaxp、jdom和dom4j的使用。然后,详细讨论了Cookie和Session的概念、作用、使用方法及其安全问题。最后,讲解了Servlet Filter的原理、生命周期以及如何配置和使用Filter。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

XML

DTD

语法自成一派, 早起就出现的。 可读性比较差。

  1. 引入网络上的DTD
    1. 引入本地的DTD
  2. 直接在XML里面嵌入DTD的约束规则

<!DOCTYPE stus [

<!ELEMENT stus (stu)>

<!ELEMENT stu (name,age)>

 <!ELEMENT name (#PCDATA)>

<!ELEMENT age (#PCDATA)>

]>

<!ELEMENT stus (stu)>  : stus 下面有一个元素 stu  , 但是只有一个

<!ELEMENT stu (name , age)>  stu下面有两个元素 name  ,age  顺序必须name-age

<!ELEMENT name (#PCDATA)>

<!ELEMENT age (#PCDATA)>

<!ATTLIST stu id CDATA #IMPLIED> stu有一个属性 文本类型, 该属性可有可无

元素的个数:

    + 一个或多个

    *  零个或多个

    ? 零个或一个

属性的类型定义

    PCDATA : 属性是普通文字

    ID : 属性的值必须唯一

<!ELEMENT stu (name , age)>     按照顺序来

<!ELEMENT stu (name | age)>   两个中只能包含一个子元素

约束的引入方式:

  <!DOCTYPE stus SYSTEM  "stus.dtd" >

<!DOCTYPE stus PUBLIC "stus.dtd" >

xml的约束

     1. DTD约束 :文档内约束、本地系统引入、网络引入

     2. Schema约束

   意义:约束xml元素的书写规范,保证数据的安全性和有效性

     用java 解析 xml

Schema

其实就是一个xml , 使用xml的语法规则, xml解析器解析起来比较方便 , 是为了替代DTD 。

但是Schema 约束文本内容比DTD的内容还要多。 所以目前也没有真正意义上的替代DTD

约束文档:

    <!-- xmlns  :  xml namespace : 名称空间 /  命名空间

    targetNamespace :  目标名称空间 。 下面定义的那些元素都与这个名称空间绑定上。

    elementFormDefault : 元素的格式化情况。  -->

    <schema xmlns="http://www.w3.org/2001/XMLSchema"

        targetNamespace="http://www.whxh.com/teacher"

        elementFormDefault="qualified">

        <element name="teachers">

            <complexType>

                <sequence maxOccurs="unbounded">

                    <!-- 这是一个复杂元素 -->

                    <element name="teacher">

                        <complexType>

                            <sequence>

                                <!-- 以下两个是简单元素 -->

                                <element name="name" type="string"></element>

                                <element name="age" type="int"></element>

                            </sequence>

                        </complexType>

                    </element>

                </sequence>

            </complexType>

        </element>

    </schema>

实例文档:

    <?xml version="1.0" encoding="UTF-8"?>

    <!-- xmlns:xsi : 这里必须是这样的写法,也就是这个值已经固定了。

    xmlns : 这里是名称空间,也固定了,写的是schema里面的顶部目标名称空间

    xsi:schemaLocation : 有两段: 前半段是名称空间,也是目标空间的值 , 后面是约束文档的路径。

     -->

    <teachers

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns="http://www.whxh.com/teacher"     

        xsi:schemaLocation="http://www.whxh.com/teacher teacher.xsd"

    >

        <teacher>

            <name>zhangsan</name>

            <age>19</age>

        </teacher>

        <teacher>

            <name>lisi</name>

            <age>29</age>

        </teacher>

        <teacher>

            <name>lisi</name

            <age>29</age>

        </teacher>

    </teachers>

XML 解析

DOM

SAX

针对这两种解析方式的API

一些组织或者公司, 针对以上两种解析方式, 给出的解决方案有哪些?

 jaxp  sun公司。 比较繁琐

    jdom

    dom4j  使用比较广泛

Dom4j 基本用法

 element.element("stu") : 返回该元素下的第一个stu元素

    element.elements(); 返回该元素下的所有子元素。

  1. 创建SaxReader对象
  2. 指定解析的xml
  3. 获取根元素。
  4. 根据根元素获取子元素或者下面的子孙元素
  1. try {
  2.     //1. 创建sax读取对象
  3.     SAXReader reader = new SAXReader(); //jdbc -- classloader
  4.     //2. 指定解析的xml源
  5.     Document  document  = reader.read(new File("src/xml/stus.xml"));
  6.     //3. 得到元素、
  7.     //得到根元素
  8.     Element rootElement= document.getRootElement();
  9.     //获取根元素下面的子元素 age
  10. //rootElement.element("age")
  11.     //System.out.println(rootElement.element("stu").element("age").getText());
  12.     //获取根元素下面的所有子元素 。 stu元素
  13.     List<Element> elements = rootElement.elements();
  14.     //遍历所有的stu元素
  15.     for (Element element : elements) {
  16.         //获取stu元素下面的name元素
  17.         String name = element.element("name").getText();
  18.         String age = element.element("age").getText();
  19.         String address = element.element("address").getText();
  20.         System.out.println("name="+name+"==age+"+age+"==address="+address);
  21.     }
  22. } catch (Exception e) {
  23.     e.printStackTrace();
  24. }

SaxReader 创建好对象 。

Document Element

  1. 看文档
  2. 记住关键字 。
  3. 有对象先点一下。
  4. 看一下方法的返回值。
  5. 根据平时的积累。 getXXX setXXX

Dom4j 的 Xpath使用

dom4j里面支持Xpath的写法。 xpath其实是xml的路径语言,支持我们在解析xml的时候,能够快速的定位到具体的某一个元素。

  1. 添加jar包依赖

jaxen-1.1-beta-6.jar

  1. 在查找指定节点的时候,根据XPath语法规则来查找
  2. 后续的代码与以前的解析代码一样。
  1.   //要想使用Xpath, 还得添加支持的jar 获取的是第一个 只返回一个。
  2.     Element nameElement = (Element) rootElement.selectSingleNode("//name");
  3.     System.out.println(nameElement.getText());
  4.     System.out.println("----------------");
  5.     //获取文档里面的所有name元素
  6.     List<Element> list = rootElement.selectNodes("//name");
  7.     for (Element element : list) {
  8.         System.out.println(element.getText());
  9.     }

Cookie

应用场景

自动登录、浏览记录、购物车。

为什么要有这个Cookie

http的请求是无状态。 客户端与服务器在通讯的时候,是无状态的,其实就是客户端在第二次来访的时候,服务器根本就不知道这个客户端以前有没有来访问过。 为了更好的用户体验,更好的交互 [自动登录],其实从公司层面讲,就是为了更好的收集用户习惯[大数据].

Cookie怎么用

  • 添加Cookie给客户端
  1. 在响应的时候,添加cookie

Cookie cookie = new Cookie("aa", "bb");

//给响应,添加一个cookie

response.addCookie(cookie);

   2.客户端收到的信息里面,响应头中多了一个字段 Set-Cookie

   3.获取客户端带过来的Cookie

示例

在浏览器客户端存入用户名和密码

设置cookie

@WebServlet(urlPatterns = "/setCookie")//注册service
public class SetCookieServlet extends HttpServlet {

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

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

        String uname = req.getParameter("uname");
        String pwd = req.getParameter("pwd");

        // 1.创建一个Cookie实例
          Cookie cookie = new Cookie("loginUser",uname+"#"+pwd);
          // cookie的相关api
          cookie.setMaxAge(3600); //设置cookie的时效性:int expiry负数(表示浏览器已关闭则cookie失效) 正数(表示保持的有效性时间s 60*60*24*7) 0(清除cookie)
//          cookie.setDomain("www.lxyk.com"); // 设置cookie的访问域名
//          cookie.setPath("/setCookie"); // 设置cookie只有在访问该路径时有效
//          cookie.setValue("fgh,pwd"); // 设置或修改cookie中的值
          resp.addCookie(cookie);//response.addCookie(c);添加cookie到服务器端,发送给浏览器
          resp.setContentType("text/html;charset=utf8");
          resp.getWriter().write("<h3><font color='red'>服务器添加cookie成功!!</font></h3>");

    }
}

获取cookie

工具类:

public class CookieUtil {
    public static Cookie findCookie(Cookie[] cookies, String loginUser) {
        if (cookies==null||loginUser==null||"".equals(loginUser)){
            return null;
        }
        //遍历拿到的cookie并拿到所需要的cookie
        //cookie.getName():得到此cookie对象的名字
        //忽略大小写比较
        for (Cookie ck:cookies) {
            if (loginUser.equalsIgnoreCase(ck.getName())){
                return ck;
            }
        }
        return null;
    }
}
@WebServlet(urlPatterns = "/getCookie")
public class GetCookieSevrlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取客户端请求过来的带有的cookie信息
        Cookie[] cookies = req.getCookies();
        //遍历这个cookies并且从中找到所需要的cookie,CookieUtil是工具类
        Cookie loginUser = CookieUtil.findCookie(cookies, "loginUser");
        System.out.println(loginUser.getName() + "::" + loginUser.getValue());


    }
}

启动tomacat

 

案例:显示最经访问的时间

  1. 判断账号是否正确
  2. 如果正确,则获取cookie。 但是得到的cookie是一个数组, 我们要从数组里面找到我们想要的对象。
  3. 如果找到的对象为空,表明是第一次登录。那么要添加cookie
  4. 如果找到的对象不为空, 表明不是第一次登录。

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        form{
            text-align: center;
            margin: 50px auto;
           border: 3px solid red;
            width: 450px;
            height: 300px;
        }
        h3{
            text-align: center;
        }
        p:nth-of-type(1){
            margin-top: 86px;
        }
    </style>
</head>
<body>
    <h3>登陆页面</h3>
     <!-- 在tomcat中配置访问项目的路径时你带了项目名称,而这里/test访问是根路径为参照的-->
    <form action="/loginCookie" method="post">
        <p>用户名:<input type="text" name="uname" /> </p>
        <p>密&nbsp;&nbsp;码:<input type="password" name="pwd" /> </p>
        <p><input type="submit" value="登录" /></p>
    </form>>

</body>
</html>

cookie类具体实现

@WebServlet(urlPatterns = "/loginCookie")
public class LoginCookie extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //思路  将本次登陆的时间记录在cookie中 下次登陆的时候从cookie中获取上次登陆的时间并将本次登陆的时间再次存入cookie中
        Cookie[] cookies = req.getCookies();
        Cookie findCookie = CookieUtil.findCookie(cookies, "last_login");

        if (findCookie == null) {//找不到最后登录的cookie证明是第一次登录
             String curr=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
             Cookie c=new Cookie("last_login",curr);
             c.setMaxAge(3600);
             resp.addCookie(c);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("<h3><font color='blue'>您是第一次登陆</font></h3>");
        }else{//用户上次登录过,在客户端已经有了记录登录的cookie信息
            String lastTime=findCookie.getValue();//获取上次的登陆时间
            String currl=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            findCookie.setValue(currl);
            findCookie.setMaxAge(3600);
            resp.addCookie(findCookie);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("<h3><font color='blue'>您上次登陆的时间是:"+lastTime+"</font></h3>");
        }
    }
}

启动tomacat  报错:java.lang.IllegalArgumentException: Cookie值中存在无效字符[32]

解决办法j在tomcat的根目录的conf目录context.xml加上下面的代码即可解决问题

<!-- 解决Cookie中不允许出现非法字符-->
    <CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" />

Cookie总结

  1.  什么是cookie

    HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。

    打个比方,我们去银行办理储蓄业务,第一次给你办了张银行卡,里面存放了身份证、密码、手机等个人信息。当你下次再来这个银行时,银行机器能识别你的卡,从而能够直接办理业务。

  2. cookie机制

    当用户第一次访问并登陆一个网站的时候,cookie的设置以及发送会经历以下4个步骤:

    客户端发送一个请求到服务器 --> 服务器发送一个HttpResponse响应到客户端,其中包含Set-Cookie的头部 --> 客户端保存cookie,之后向服务器发送请求时,HttpRequest请求中会包含一个Cookie的头部 -->服务器返回响应数据

Session

会话 , Session是基于Cookie的一种会话机制。 Cookie是服务器返回一小份数据给客户端,并且存放在客户端上。 Session是,数据存放在服务器端。

Cookie JSESSIONID=sessionid

  • 常用API

//得到会话ID

String id = session.getId();

//存值

session.setAttribute(name, value);

//取值

session.getAttribute(name);

//移除值

session.removeAttribute(name);

// 判断会话是否是一次新的会话 :true,表示建立新的会话;false,表示维持之前的会

  boolean isnew = session.isNew();

Session何时创建 , 何时销毁?

Cookie的安全问题。

由于Cookie会保存在客户端上,所以有安全隐患问题。 还有一个问题, Cookie的大小与个数有限制。 为了解决这个问题 ---> Session .

什么是Session?

服务器为了保存用户状态而创建的一个特殊的对象。

当浏览器第一次访问服务器时,服务器创建一个session对象(该对象有一个唯一的id,一般称之为sessionId),服务器会将sessionId以cookie的方式发送给浏览器。当浏览器再次访问服务器时,会将sessionId发送过来,服务器依据sessionId就可以找到对应的session对象。

2)如何获得session对象?

方式一 HttpSession s = request.getSession(boolean flag);

方式二 HttpSession s = request.getSession();

购物车案例

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>
<body>
     <h3>商品列表页面</h3>
     <p><a href="cartServlet?pid=0">红米note7</a> </p>
     <p><a href="cartServlet?pid=1">华为7</a> </p>
     <p><a href="cartServlet?pid=2">苹果7</a> </p>
     <p><a href="cartServlet?pid=3">魅族7</a> </p>
</body>
</html>

servlet

@WebServlet(urlPatterns = "/cartServlet")
public class cartServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /**
         * 将前端页面提交过来的商品加入到购物车中存储起来
         *    设计一个购物车(容器-->集合(商品名称,商品数量))Map<String,Integer>
         *     可以考虑将购物车存入到Session中,这样子在各个页面都可以获取到
         */

        /**
         * 获取商品pid
         */
               String pid=req.getParameter("pid");
               String[] products={"红米note7","华为7","苹果7","魅族7"};

        /**
         * 获取Session中的购物车
         *   没有(第一次购物)创建一个购物车Map<String,Integer>
         *   有:开始存入购物车
         *        购物车中有此商品  数量+1
         *        购物车中没有此商品 数量=1
         *   将添加了商品的购物车再次存入session
         */
         //创建session
        HttpSession session= req.getSession();
        //获取购物车
        Map<String,Integer> cart=(Map<String, Integer>) session.getAttribute("cart");
        int index=Integer.parseInt(pid);
        String pName =products[index];
        //第一次
        if (cart==null){
            cart=new LinkedHashMap<>();
            cart.put(pName,1);
        }else {
            //判断有没有此商品
            if (cart.containsKey(pName)){
                cart.put(pName,cart.get(pName+1));
            }else {
                cart.put(pName,1);
            }
        }
        /**
         * 跳转到中间页面等待下一步客户端的用户的处理
         */
        resp.setContentType("text/html;charset=utf8");
        PrintWriter out= resp.getWriter();
        out.write("<h3><font><a href='/product.html'>继续购物</a></font></h3>");
        out.write("<h3><font><a href='/cart.jsp'>去购物车结算</a></font></h3>");
    }
}

Filter

一、Filter简介

  Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
  Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:

 Filter生命周期
1、Filter接口中三个重要的方法
init()方法:初始化参数,在创建Filter时自动调用,当我们需要设置初始化参数的时候,可以写到该方法中。
doFilter()方法:拦截到要执行的请求时,doFilter就会执行。这里面写我们对请求和响应的预处理
destory()方法:在销毁Filter时自动调用

Filter对象 - FilterConfig

用户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装filter初始化参数的FilterConfig对象传递进来。
通过filterConfig对象的方法,可以获得:

String getFilterName():得到filter名称
String getInitParameter(String name):返回在部署描述中指定名称的初始化参数的值,如果不存在返回null
Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名称的枚举集合
public ServletContext getServletContext():返回Servlet上下文对象的引用

用户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装filter初始化参数的FilterConfig对象传递进来。
通过filterConfig对象的方法,可以获得:
String getFilterName():得到filter名称
String getInitParameter(String name):返回在部署描述中指定名称的初始化参数的值,如果不存在返回null
 Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名称的枚举集合
 public ServletContext getServletContext():返回Servlet上下文对象的引用


过滤器链 - FilterChain
一组过滤器对某些web资源进行拦截,那么这组过滤器就成为过滤链。过滤器的执行顺序和<filter-mapping>有关

举例(非注解方式)

需要web.xml

<?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">
    <welcome-file-list>
        <welcome-file>login.html</welcome-file>
    </welcome-file-list>

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>fiter.CharacterEncodingFilter</filter-class>
        <!--设置初始化参数-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

注解方式

/**
 * 定义一个编码过滤器:对所有的请求进行编码拦截处理
 */
@WebFilter(urlPatterns = "/*",initParams = {@WebInitParam(name = "encoding",value = "utf8")})
public class CharacterEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println(" CharacterEncodingFilter被创建了");
    }

    /**
     *
     * @param servletRequest:请求对象
     * @param servletResponse:响应对象
     * @param filterChain:过滤器链
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("CharacterEncodingFilter执行了编码拦截");
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        HttpServletResponse response= (HttpServletResponse) servletResponse;
        //request中的中文编码
        //使用包装模式解决中文乱码的请求对象
        MyRequest myRequest=new MyRequest(request);
        //过滤器链放行请求和响应对象
        filterChain.doFilter(myRequest,response);
    }

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

/**
 * 包装代理类
 */
class MyRequest extends HttpServletRequestWrapper{
    private  HttpServletRequest request;
    private boolean hasEcode;

    public MyRequest(HttpServletRequest request) {
        super(request);
        this.request=request;
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        String method = request.getMethod();

        try {
            if ("post".equalsIgnoreCase(method)){
                request.setCharacterEncoding("utf8");
                return request.getParameterMap();
            }else if ("get".equalsIgnoreCase(method)) {
                if (!hasEcode) {
                    //获取中文乱码问题中的数据
                    Map<String, String[]> pmap = request.getParameterMap();
                    //对请求的键值对数据中的值进行手动转码
                    Collection<String[]> values = pmap.values();
                    for (String[] vals : values) {
                        for (int i = 0; i < vals.length; i++) {
                            vals[i] = new String(vals[i].getBytes("iso-8859-1"), "utf8");
                        }
                    }
                }
                hasEcode=true;
                return request.getParameterMap();
            }else { return super.getParameterMap();
            }
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String getParameter(String name) {
        String[] vals = this.getParameterMap().get(name);
        if (vals == null) {
         return null;
        }
        return vals[0];
    }

    @Override
    public String[] getParameterValues(String name) {
        return this.getParameterMap().get(name);
    }
}

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        form{
            text-align: center;
            margin: 50px auto;
           border: 3px solid red;
            width: 450px;
            height: 300px;
        }
        h3{
            text-align: center;
        }
        p:nth-of-type(1){
            margin-top: 86px;
        }
    </style>
</head>
<body>
    <h3>登陆页面</h3>
     <!-- 在tomcat中配置访问项目的路径时你带了项目名称,而这里/test访问是根路径为参照的-->
    <form action="/loginCookie" method="post">
        <p>用户名:<input type="text" name="uname" /> </p>
        <p>密&nbsp;&nbsp;码:<input type="password" name="pwd" /> </p>
        <p><input type="submit" value="登录" /></p>
    </form>>

</body>
</html>

若是有多个Filter则按字典顺序排序

若是用的xml注册则按照注册顺序排序

@WebFilter(urlPatterns = "/*",filterName = "a")
public class FilterA implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterA be执行了拦截请求");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("FilterA af执行了拦截请求");

    }

    @Override
    public void destroy() {

    }
}

启动tomacat

Listener

监听器

1.能做什么事?

监听某一个事件的发生。 状态的改变。

监听器就是监听某个对象的的状态变化的组件

监听器的相关概念:

事件源:被监听的对象  ----- 三个域对象 request  session  servletContext

 servletContext:

1.      是一个域对象

2.      可以读取全局配置参数

3.      可以搜索当前工程目录下面的资源文件

4.      可以获取当前工程名字(了解)

具体:(80条消息) ServletContext介绍及用法_白衬衫丶的博客-优快云博客_servletcontexthttps://blog.youkuaiyun.com/qq_36371449/article/details/80314024

监听器:监听事件源对象  事件源对象的状态的变化都会触发监听器 ---- 6+2

注册监听器:将监听器与事件源进行绑定

响应行为:监听器监听到事件源的状态变化时 所涉及的功能代码 ---- 程序员编写代 码

2.监听器有哪些?

第一维度:按照被监听的对象划分:ServletRequest域   HttpSession域    ServletContext域

第二维度:监听的内容分:监听域对象的创建与销毁的    监听域对象的属性变 化的

Web监听器

总共有8个 划分成三种类型

  1. 定义一个类,实现接口
  2. 注册 | 配置监听器
/**
 * 三域生死监听器
 *   在恰当的时机出发对应域的函数,程序员就可以在该函数中去做相应的业务逻辑
 */
public class MyServletListener implements ServletRequestListener, HttpSessionListener, ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("contextScope init listening");

    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("contextScope destroy listening");

    }

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("requestScope init listening");

    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("requestScope init listening");
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        HttpSession session = httpSessionEvent.getSession();
        System.out.println("requestScopr created listening"+session.getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {

    }
}

使用过滤器和监听器完成统计访问登陆app的用户的IP和访问的次数案例

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center;width: 300px;margin: 50px auto">
     <a href="/test/countServlet">点击查看成功登录的次数</a>
    </div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>错误页面</title>
</head>
<body>
<h3 style="color: red;text-align: center">错误页面</h3>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        form{
            text-align: center;
            margin: 50px auto;
           border: 3px solid red;
            width: 450px;
            height: 300px;
        }
        h3{
            text-align: center;
        }
        p:nth-of-type(1){
            margin-top: 86px;
        }
    </style>
</head>
<body>
    <h3>登陆页面</h3>
     <!-- 在tomcat中配置访问项目的路径时你带了项目名称,而这里/test访问是根路径为参照的-->
    <form action="/test/longinServlet" method="post">
        <p>用户名:<input type="text" name="uname" /> </p>
        <p>密&nbsp;&nbsp;码:<input type="password" name="pwd" /> </p>
        <p><input type="submit" value="登录" /></p>
    </form>>

</body>
</html>

实现类

@WebServlet(urlPatterns = "/test/longinServlet",initParams = @WebInitParam(name = "count",value = "0"))
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取请求过来的用户名和密码数据
        String uname = req.getParameter("uname");
        String pwd = req.getParameter("pwd");
        /**
         * user=service>dao>db
         *
         */
        ServletContext sc = req.getServletContext();

        if ("abcde".equals(uname)&&"123456".equals(pwd)){
            //成功登录,计数
            //int count=Integer.parseInt(this.getServletConfig().getInitParameter("count"));
            //count++;

            Object count = sc.getAttribute("count");
            if (count==null){
                sc.setAttribute("count",1);
            }else {
                sc.setAttribute("count",(Integer)count+1);
            }
            resp.sendRedirect(sc.getContextPath()+"/html/count.html");

        }else {
           //错误
            resp.sendRedirect(sc.getContextPath()+"/html/error.html");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
 @WebServlet(urlPatterns = "/test/countServlet")
public class countServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取登陆成功的次数
        ServletContext sc = req.getServletContext();
        int count = (Integer) sc.getAttribute("count");

        PrintWriter out = resp.getWriter();
        resp.setContentType("text/html;charset=utf8");
        out.write("<h3><font color='blue'>longin sucess"+count+"times!!</font></h3>");
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值