Servlet的相关原理以及使用

文章目录


前言

Servlet相关的原理以及具体使用


一、servlet是什么?(运行于服务器上)

使用servlet之前需要导入servlet-api.jar包

(1)servlet定义

servlet是运行在web服务器中的一小段java程序,它能够通过web服务器接受并处理浏览器发送的http请求,并能够通过web服务器将动态生成的结果应答给客户端,从而实现动态网页的功能。
  • 自定义的servlet类需要继承一个HttpServlet的类,其实HttpServlet继承了GenericServlet类,而GenericServlet类最终是继承了Servlet类
  • 服务器端运行的servlet类,继承HttpServlet抽象类,重写类中的方法,用来处理客户端不同的请求,该类的对象是由服务器负责创建,类中的方法都是有服务器自动调用:重写里面的doGet和doPost方法,或者直接重写里面的service方法代替前面的两个方法也得

(2)servlet的一些配置

从servlet3.0版本开始用注解标识servlet类处理的请求地址,之前版本需要在web.xml文件中配置

两种方式实现servlet标注

  • 以/@WebServlet("/test")形式对应前端发来的请求,请求地址的相对路径是"/test"命名,通过请求地址栏参数传入-----客户端参数传递格式为:/test?name=zhangsan&age=20形式进行请求
    需要注意的是: Get方式传入的参数是在请求url地址栏上是可见的,且对于请求的数据不需要进行编码格式处理,由于Get方式的编码格式是取决于Tomcat的默认URLencoding的编码,所以在tomcat设置过编码格式做过处理了,Get方式的请求就不需要设置请求编码格式了;然而对于响应对象,设置响应对象输出内容格式及编码,必须在获取输出流之前设置----- response.setContentType(“text/html;charset=utf-8”);
@WebServlet("/test")
public class TestServlet extends HttpServlet {

    /**
     * 处理客户端get方式发生过来的请求
     * get方式:
     * 1、直接在浏览器url输入地址
     * 2、a标签超链接方式
     * 3、form表单默认方式,method="get"方式
     * @param request       客户端请求对象,跟请求相关的内容都封装在此对象中
     * @param response      服务端响应对象,跟响应相关的内容都封装在此对象中
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("当前请求方式为get方式");
        //获取客户端传递过来的参数,根据参数名称获取参数值,客户端参数传递格式为:/test?name=zhangsan&age=20
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        //设置响应对象输出内容格式及编码,必须在获取输出流之前设置
//        response.setContentType("text/html");
//        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("Hello World!");
        out.write("<h3>Hello World!</h3>");
        out.write("<h3>你好,世界!</h3>");
        out.write("<h3>姓名:"+name+",年龄:"+age+"</h3>");
        out.flush();
        out.close();
    }
}
  • 以/@WebServlet("/test")形式对应前端发来的请求,请求地址的相对路径是"/test"命名,处理客户端post方式发过来的请求------post方式:form表单method=“post“方式
    需要注意的是: Post方式传入的参数是通过表单形式,在请求url地址栏上是不可见的,且对于请求的数据需要进行编码格式处理,需要设置请求对象编码格式,解决post方式传递中文参数乱码问题--------request.setCharacterEncoding(“utf-8”);
@WebServlet("/test")
public class TestServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("当前请求方式为post方式");
        //设置响应对象编码格式
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //设置请求对象编码格式,解决post方式传递中文参数乱码问题
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //查询数据库
        if(username.equals("zhangsan")&&password.equals("123456")){
            //创建一个会话,保存用户登录信息
            HttpSession session = request.getSession();
            //设置会话有效期,单位是秒,默认有效期是30分钟
            session.setMaxInactiveInterval(60);
            //保存用户账号
            session.setAttribute("username",username);
            out.write("<h3>登录成功,欢迎:"+username+",<a href=\"index\">主页面</a></h3>");
        }else{
            out.write("<h3 style=\"color:red;\">用户名或者密码错误</h3>");
        }
        out.flush();
        out.close();
    }
}
  • 以web.xml配置文件形式进行标识
通过自定义servlet类名,对应上请求地址"/login",当我们在请求Url地址栏请求"/login"时,服务器能够找到对应上的我们自定义的TestServlet类

servlet标签中:
(1)servlet-name标签: 为一个Servlet定义一个名字,这个名字就是这个servlet在文本应用中的唯一标识
(2)servlet-class标签:用于指定Servlet由哪个类实现,在这个配置选项中,必须填写类的全名,即包名加类名

servlet-mapping标签中:
(1)servlet-name标签:前面定义过的servlet的名字,与之对应
(2)url-pattern标签:用于指定servlet对应的URL,url-pattern的值以”/”开头,代表web应用的根,如果一个servlet对应的url为:
http://localhost:8080/myapp/time ,在url-pattern中应当配置为 /time

 <!--配置servlet名称和对应的类-->
    <servlet>
        <servlet-name>TestServlet</servlet-name>
        <servlet-class>com.entor.servlet.TestServlet</servlet-class>
    </servlet>
<!--配置servlet名称和对应的请求地址-->
    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
通过自定义servlet类名,对应上请求地址"/test",当我们通过表单请求形式请求/test时,服务器能够找到对应上的我们自定义的TestServlet类

表单中的action=""就是要指定到标签url-pattern的请求名称相对地址

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
    <form method="post" action="login">
        账号:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
            <input type="submit" value="登录"><br/>
    </form>
</body>
</html>

二、页面的请求转发和重定向

  • 页面的重定向(相当于间接请求转发----相当于发了两次请求):重定向要返回客户端,由浏览器发起第二次请求,重定向时地址栏的地址会发生变化,而且重定向时两个servlet处于两个不同的请求当中,不共享一个request对象;重定向可以定向到其他应用中
页面重定向通过response对象下的sendRedirect("")方法传入要指定到的页面,相当于重新访问一个新的地址页面----url是能够明显的发生改变的,相当于一次超链接跳转
  • 页面的请求转发(相当于直接请求转发-----相当于发了一次请求):请求转发是在服务器内部实现的,请求转发时,浏览器的地址不会变,而且请求转发时两个servlet处于一个请求当中,使用的是一个request对象;请求转发只能在相同应用中使用
页面请求转发是通过request对象中的getRequestDispatcher("")中传入转发到下一个请求相对地址名标记,在其方法下的forward(request,response)方法和include(request,response)方法就可以实现请求转发,后面的forward(request,response)和include(request,response)是为了保证是同一次请求的标记,把前一次的request请求对象都得到,在下一次请求中就可以获取(也就是同一个请求对象中的转发,两个servlet可以共享request对象中的数据)-------把请求转发到某一个请求地址,客户端浏览器显示的还是第一个请求地址,请求转发是发生在服务器内部,客户端是不知道的,所以url是不会发生改变的
  • 代码案列
@WebServlet("/test1")
public class Test1Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("name","张三");
        //把请求转发到/test2,客户端浏览器显示的还是第一个请求地址,请求转发是发生在服务器内部,客户端是不知道的
        //是同一个请求对象中的转发,两个servlet可以共享request对象中的数据
//        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/test2");
//        requestDispatcher.forward(request,response);
        request.getRequestDispatcher("/test2").forward(request,response);

    }
}


@WebServlet("/test2")
public class Test2Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("姓名:"+request.getAttribute("name"));
        //调用Test3Servlet的service方法,两个servlet公用同一个request对象
        request.getRequestDispatcher("/test3").include(request,response);
        System.out.println("年龄:"+request.getAttribute("age"));
    }
}


@WebServlet("/test3")
public class Test3Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("age",20);
    }
}

三.利用请求转发、重定向和session会话机制实现简单的登录验证

  • 前端html表单获取用户名和密码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
    <form method="post" action="login">
        账号:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
            <input type="submit" value="登录"><br/>
    </form>
</body>
</html>
  • 后台servlet请求地址为login的servlet处理
@WebServlet("/login")
public class TestServlet extends HttpServlet {
	/**
     * 处理客户端post方式发过来的请求
     * post方式:form表单method=“post“方式
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("当前请求方式为post方式");
        //设置响应对象编码格式
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //设置请求对象编码格式,解决post方式传递中文参数乱码问题
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //查询数据库
        if(username.equals("zhangsan")&&password.equals("123456")){
            //创建一个会话,保存用户登录信息
            HttpSession session = request.getSession();
            //设置会话有效期,单位是秒,默认有效期是30分钟
            session.setMaxInactiveInterval(60);
            //保存用户账号
            session.setAttribute("username",username);
            out.write("<h3>登录成功,欢迎:"+username+",<a href=\"index\">主页面</a></h3>");
        }else{
            out.write("<h3 style=\"color:red;\">用户名或者密码错误</h3>");
        }
        out.flush();
        out.close();
    }
}
  • 如果验证成功则通过超链接形式,再一次请求到"/index"的servlet
@WebServlet("/index")
public class IndexServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        HttpSession session = request.getSession();
       // Object username = session.getAttribute("username");
        if(session.getAttribute("username")==null){
            out.write("请先登录,<a href=\"login.html\">登录</a>");
        }else{
            out.write("欢迎:"+session.getAttribute("username")+",<a href=\"logout\">注销</a>");
        }
        out.flush();
        out.close();
    }
}
  • 如果session在有效期中还有值,那么该页面附着者注销退出的功能(该功能主要是为了清除用户曾经存放在session机制中的信息)------主要是用到了session中的invalidate()方法,这样保证了用户的信息安全
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        //清空会话对象中保存的所有数据
        session.invalidate();
        //如果想移除单个数据可以使用removeAttribute方法
//        session.removeAttribute("username");
        //重定向到登录页面
        response.sendRedirect("login.html");
    }
}

四、上下文ServletContext类使用

  • 通过request.getServletContext()获取上下文对象,并往上下文对象中设置参数值
@WebServlet("/demo1")
public class Demo1Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取上下文对象,该对象在服务器启动时候创建,关闭时销毁
        ServletContext context = request.getServletContext();
        //在上下文对象中设置值,全体所有servlet对象都可以取到
        context.setAttribute("phone","13812345678");
        context.setAttribute("address","南宁市西乡塘区");
    }
}

  • 通过request.getServletContext()获取上下文对象,由于在上下文对象中设置值,全体所有servlet对象都可以取到,并往上下文对象中获取之前设置过的参数值
@WebServlet("/demo2")
public class Demo2Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取上下文对象,该对象在服务器启动时候创建,关闭时销毁
        ServletContext context = request.getServletContext();
        //在上下文对象中获取值
        System.out.println("手机:"+context.getAttribute("phone"));
        System.out.println("地址:"+context.getAttribute("address"));
    }
}

五、servlet的生命周期的几个阶段

  • 单例模式,当用户第一次请求时创建对象,之后请求都是使用原有对象
  • servlet对象生命周期三个方法
  • 0、对象创建,默认是客户端第一次请求,
  • 也可以通过web.xml中标签或者注解属性loadOnStartup设置加载顺序,数字越小加载越早
  • 可以设置服务器启动时就创建
  • 1、init,初始化对象,执行一次
  • 2、service,提供服务,每次请求都执行
  • 3、destroy,销毁对象,执行一次

servlet对象初始化参数有两种形式

  • 通过注解@WebServlet里的参数设置
@WebServlet(value = "/count",loadOnStartup = 1,initParams = {
        @WebInitParam(name = "name",value = "张三"),//servlet对象初始化参数,私有参数,其中loadOnStartup是加载顺序,默认是-1,数字越小加载越早
        @WebInitParam(name = "sex",value = "男")
    })

相当于

  • 在web.xml文件中的servlet标签中的配置
 <servlet>
//serlvet对象创建的时机,数字越小越早
        <load-on-startup>0</load-on-startup>
        servlet对象初始化参数,参数名称,参数值,通过ServletConfig对象调用
        <init-param>
            <param-name>name</param-name>
            <param-value>张三</param-value>
        </init-param>
        <init-param>
            <param-name>sex</param-name>
            <param-value></param-value>
        </init-param>
  </servlet>
  • servlet案列
/**
 * 单例模式,当用户第一次请求时创建对象,之后请求都是使用原有对象
 * servlet对象生命周期三个方法
 * 0、对象创建,默认是客户端第一次请求,
 * 也可以通过web.xml中标签<load-on-startup>或者注解属性loadOnStartup设置加载顺序,数字越小加载越早,
 * 可以设置服务器启动时就创建
 * 1、init,初始化对象,执行一次
 * 2、service,提供服务,每次请求都执行
 * 3、destroy,销毁对象,执行一次
 */
@WebServlet(value = "/count",loadOnStartup = 1,initParams = {
        @WebInitParam(name = "name",value = "张三"),//servlet对象初始化参数,私有参数
        @WebInitParam(name = "sex",value = "男")
    })
public class CountServlet extends HttpServlet {

    private int count;

    /**
     * 对象创建,只创建一次
     */
    public CountServlet(){
        System.out.println("servlet对象创建");
    }
    /**
     * 多次调用,提供处理请求服务
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("servlet对象提供请求服务");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("<h3>当前计数器:"+(count++)+"</h3>");
        /**
        *其中的count是单一变量,当我们通过本浏览器不同请求去访问时,count的值是会在原有基础上递增的
        */
        out.flush();
        out.close();
    }

    /**
     * 对象销毁之前调用,只执行一次
     */
    @Override
    public void destroy() {
        System.out.println("servlet对象销毁");
    }

    /**
     * 初始化方法,只执行一次
     * @param config
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("servlet对象初始化");
        //获取servlet初始化参数值
        String name = config.getInitParameter("name");
        String sex = config.getInitParameter("sex");
        System.out.println("姓名:"+name);
        System.out.println("性别:"+sex);
    }
}

六、session和cookie

(1)session会话的创建,其主要是调用HttpServletRequest下的getSession()方法进行创建获得HttpSession对象,其语法是

  • public HttpSession getSession();
    public HttpSession getSession(boolean value);

1、如果没有与当前请求关联的会话,则 getSession() 方法用于创建会话。
2、如果布尔值为 true 且当前没有与请求关联的会话,则使用 getSession(boolean value) 创建会话。如果布尔值为 false,且没有与当前请求关联的会话,返回null。

(2)会话对象的一些特性

  • HttpSession是tomcat在服务器端为每个浏览器准备的私人储物箱,每个浏览器在tomcat里都有一个属于自己的HttpSession对象,用于存储私人数据
  • 在Servlet中可以通过request.getSession(true)方法来获得session对象,这个方法总是返回与发送请求的浏览器对应的session对象-------这就体现了session的私有的性质,主要体现在每个浏览器的每一次请求没结束期间的多次访问,该浏览器的session的id,也就是cookie的jsessionid值是一样的

(3)session对象存取数据的方法

  • 存数据:session.setAttribute( “name”, object );
    name : 数据的别名
    object:存储的数据本身
  • 取数据:session.getAttribute(“name”);
    name :要获取的数据别名
    返回值:与name对应的数据对象

(4)session的作用(解决登录问题-------从服务器内部进行判断)

  • 借助用户用户名是否存在会话中进行判断(在会话结束之前)
  1. 如果sessoin保存了用户名:说明该用户已经登陆过
  2. 如果sesson没有保存用户名:说明该用户没有登陆

(5)session对象的生命周期(session是多例模式):客户端请求服务器时调用getSession方法时由服务器创建,有效期超时后自动销毁,或者服务器关闭销毁

  • 创建 : 当用户第一次调用getSession(true)方法
  • 销毁 : 用户长时间没有执行操作(timeout),默认30分钟;;或者服务器关闭
  • 设置session对象时间

第一种:可以在web.xml中设定session超时的时间

<session-config>
<session-timeout>10</session-timeout>
</session-config>

第二种:调用session对象中的setMaxInactiveInterval()方法,里面的参数是以秒为单位

  • session对象的钝化和锐化现象
    钝化:当服务器内存空间紧张或tomcat关闭时,tomcat会将不活跃的session保存到磁盘中
    锐化:当需要使用时或tomcat重新启动时再次加载到内存中来

(7)session与request对象的区别
request对象:命名属性可以在由forward连接的多个servlet之间共享
生命周期较为短暂:当请求到达服务器时创建,当应答送回到浏览器时销毁
session对象:命名属性可以在同一个浏览器的多次请求之间共享
生命周期较长:在调用request.getSession(true)时被创建,在超时之后被销毁

(8)session与cookie的联系

  • Tomcat会为每个拥有session的浏览器设置一个特别的Cookie,称作会话Cookie.会话Cookie的名字固定叫做 “JSESSIONID”, Cookie的值就是该浏览器对应的session ID号(这是session请求处理时自带的),其生命周期为-1
  • 当调用getSession(true)时,他首先检查用户的会话Cookie是否存在
    如果不存在 : 为其创建新的session对象,将session对象的ID保存到新建的会话Cookie中,并将会话cookie送回浏览器 。
    如果存在 : 则按照会话Cookie 的值找到对应的session对象返回

(9)什么是cookie:是服务器保存在用户浏览器上的一段字符串

  • 当浏览器向服务器发送请求时,会自动将这些浏览器存储的字符串发送到服务器,然后与服务器端的session的ID进行比对,判断是否是曾经访问过
  • 我们可以利用这些字符串记录用户的重要状态,如是否登录,用户权限等
  • 在服务器端的Servlet中,通过检查这些字符串来判断用户的状态(从浏览器客户端之前请求过的保存在浏览器cookie中,再次访问时,客户端会把之前的cookie(Jsessionid,这是服务器响应给客户端浏览器携带的字符串,也可以把其他参数的值,以变量-值的形式添加到cookie中,随着服务器响应给客户端就携带返回了)的值一起发送至请求中,等待服务器端处理
  • cookie的生命周期
    1.通过new Cookie创建属性名和对应的属性值
    2.通过Cookie对象中的setMaxAge()方法设置生命周期,单位是秒;当cookie生命周期结束时,客户端浏览器会自动删除该cookie-----setMaxAge的特殊值:
    -1 :会话Cookie,浏览器关闭时自动删除
    0 : 表示要删除一个cookie
    如果没有调用setMaxAge()方法,默认值为-1

    3.将Cookie存储在用户的浏览器中,通过response的addCookie()方法进行响应之后,随着应答内容被携带到浏览器中
    4.Cookie是否被正确的添加到浏览 器中,可以通过浏览器的查看Cookie功能进行验证
    5.获取客户端cookie信息,通过request的getCookies()方法,其返回类型是Cookie数组,通过遍历就可以把它输出出来。通过cookie对象中的getName()方法获取属性名,getValue()方法获取对应的属性值
  • cookie的一些特征
    1.采用字符串形式存储数据,简单灵活
    2.存储在用户的浏览器上,减少对服务器的压力
    3.对于重要数据而言,数据存储在浏览器上不安全的
    4.无法存储格式复杂的数据格式,如对象和集合等

(10)session与cookie使用的代码实例

@WebServlet("/session")
public class SessionServlet extends HttpServlet {
    /**
     * servlet生命周期的方法,可以处理所有方式的请求
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建会话对象,如果会话存在,使用原来的,如果不存在,则创建新的对象
        //同时创建会话Cookie,固定名称是jsessionid,值是session的id,写入客户端浏览器返回,浏览器下次访问时带上Cookie
        HttpSession session = request.getSession();
       // boolean aNew = session.isNew();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("会话ID:"+session.getId()+"<br>");
        out.write("会话创建时间:"+sdf.format(new Date(session.getCreationTime()))+"<br>");
        out.write("系统当前时间:"+sdf.format(new Date())+"<br>");
        out.write("系统当前时间:"+sdf.format(new Date(session.getLastAccessedTime()))+"<br>");
        //创建Cookie对象
        Cookie username = new Cookie("username", "zhangsan");
        Cookie password = new Cookie("password", "123456");
        //设置有效时间,单位是秒,默认不设置,有效期-1,关闭浏览器则删除cookie
        username.setMaxAge(60);
        //把cookie写入浏览器,返回给客户端,只有当服务器成功响应结束之后cookie才写入到浏览器
        response.addCookie(username);
        response.addCookie(password);

        //获取客户端浏览器的cookie
        Cookie[] cookies = request.getCookies();
        Arrays.stream(cookies).forEach(cookie->{
            System.out.println(cookie.getName()+"="+cookie.getValue());
        });
        out.flush();
        out.close();
    }
}

七、验证servlet是单例模式

单例模式:当用户第一次请求时创建对象,之后请求都是使用原有对象
下面的count属性,在不同的请求中,count的值是连续的

public class CountServlet extends HttpServlet {
    private int count;
      /**
     * 多次调用,提供处理请求服务
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("servlet对象提供请求服务");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("<h3>当前计数器:"+(count++)+"</h3>");
        out.flush();
        out.close();
    }

八、过滤器(Filter)的使用

过滤器:如果一个Servlet配置了过滤器,那么请求在到达Servlet之前先要经过过滤器的处理,需要实现Filter接口,实现重写该接口中的三个无返回值的三个方法,分别是init(初始化)、doFilter(过滤操作,主要是通过这个进行过滤操作)、destroy(销毁)
过滤器的生命周期(单例模式)
  • 0、对象创建,创建一次,服务器启动时执行
  • 1、对象初始化,执行一次
  • 2、对象过滤服务,每次过滤都执行,根据条件判断是否放行请求
  • 3、对象销毁,执行一次,服务器关闭时执行
Filter一些配置有两种形式
  • 注解形式:自定义的Filter类需要加上@WbFilter注解标识这是一个过滤器类,形如@WebFilter(value = “/*”),其中的/*对所有请求都过滤
  • web.xml配置文件形式,只有满足过滤条件的请求才能到达servlet服务
<filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>com.entor.filter.EncodingFilter</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>
代码如下(示例):
@WebFilter(value = "/*")
public class EncodingFilter implements Filter {

    /**
     * 创建对象
     */
    public EncodingFilter(){
        System.out.println("EncodingFilter对象创建");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("EncodingFilter对象初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("EncodingFilter对象过滤服务");
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        //统一设置请求对象和响应对象的字符编码格式
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        //放行请求
        filterChain.doFilter(request,response);
    }

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

如果存在多个过滤器处理的情况下注意的问题

如果存在多个过滤器,执行的顺序:

  • 1、如果在web.xml配置文件中,根据配置的先后顺序执行
  • 2、如果是注解方式,根据类名字母asci码先后顺序
  • 3、配置文件和注解两种方式都有,先执行配置文件的,再执行注解的

过滤器的作用于对非法的url请求地址进行过滤,除非是先登录后或者其他条件执行后才给放行
代码示例----设置了用户可以访问相对路径是/index和/login的请求都放行,都可以访问到页面,在地址栏中输入;如果都不是就会设置重定向到登录页面

web.xml配置

<!--配置过滤器,多个过滤器根据配置文件先后顺序加载过滤-->
    <filter>
        <filter-name>SessionFilter</filter-name>
        <filter-class>com.entor.filter.SessionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SessionFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

java代码

public class SessionFilter implements Filter {

    private String allow;
    public SessionFilter(){
        System.out.println("SessionFilter过滤器对象创建");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("SessionFilter过滤器对象初始化");
        Properties p = new Properties();
        try {
            p.load(SessionFilter.class.getResourceAsStream("/static.properties"));
            allow = p.getProperty("allow");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("SessionFilter过滤器对象过滤服务");
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        String url = request.getRequestURL().toString();// 获取请求的url: 统一资源定位符 http://localhost:8084/servlet_0316/任意输入的请求相对servlet地址
        if(request.getQueryString()!=null){
            url += "?"+request.getQueryString();
        }
        /*
        System.out.println("url:"+request.getRequestURL().toString());
        System.out.println("uri:"+request.getRequestURI());
        System.out.println("contextPath:"+request.getContextPath());
        System.out.println("scheme:"+request.getScheme());
        System.out.println("serverName:"+request.getServerName());
        System.out.println("serverPort:"+request.getServerPort());
        System.out.println("queryString:"+request.getQueryString());
        //url = scheme+serverName+serverPort+uri
        //地址栏=url+queryString
        */
        if(request.getSession().getAttribute("username")==null&&!isExist(url)){//没有登录
            //重定向到login.html
            response.sendRedirect("login.html");
            return;
        }
        filterChain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        System.out.println("SessionFilter过滤器对象销毁");
    }

    /**
     * 判断url是否包括白名单关键字
     * @param url
     * @return
     */
    public boolean isExist(String url){
        String[] keys = allow.split(",");
        for(int i=0;i<keys.length;i++){
            if(url.contains(keys[i])){
                return true;
            }
        }
        return false;
    }
}

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

九、监听器(listener)

定义:当web应用中某一特定事件发生时,会调用相关的listener

常用的listener
  • ServletContextListener:监听ServletContext(上下文)的创建和销毁
  • HttpSessionListener : 监听HttpSession对象的创建和销毁
两种方式使用监听器
  • 配置web.xml文件
<listener>
<listener-class>监听器类全路径名</listener-class>
</listener>
  • 添加注解@WebListener标识
代码实例

监听会话对象

public class MyHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("会话对象创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("会话对象销毁");
    }
}

监听上下文对象

@WebListener
public class MyServletContextListener implements ServletContextListener {


    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("服务器启动初始化");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("服务器关闭");
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值