过滤器和注解

过滤器

1:过滤器的作用

把通用的、相同的处理代码用过滤器实现,可以共享,然后在web.xml中将过滤器配置给相关的资源使用即可

2:过滤器的开发方法

  1. 写一个类实现Filter接口
  2. 重写Filter接口的三个方法

  1. IDE开发工具开发过滤器的步骤:
  2. 在doFilter()方法写逻辑: System.out.println("MyFilter.doFilter()...");
  3. 创建servlet,运行servlet测试.
    1. 放行  执行chain.doFilter(request,response)
    2. 不放行 不执行chain.doFilter(request,response)
package com.tjetc.filter;

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

public class HelloFilter implements Filter {
    public HelloFilter() {
        System.out.println("HelloFilter的构造方法");
    }

    /**
     * 初始化, 调用一次, Tomcat启动时会调用Filter的init ?
     *
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("HelloFilter的init方法被调用");
        String filterName = filterConfig.getFilterName();
        System.out.println("filterName=" + filterName);
        Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {//initParameterNames.hasMoreElements())遍历过程中判断是否还有元素遍历
            //获取参数名称
            String parameterName = initParameterNames.nextElement();
            //获取参数对应的value值
            String parameterValue = filterConfig.getInitParameter(parameterName);
            System.out.println(parameterName + "=" + parameterValue);
        }
        ServletContext servletContext = filterConfig.getServletContext();
        //获取上下文对象
        System.out.println("servletContext=" + servletContext);
    }

    /**
     * 每次Filter拦截到的请求, 都会调用doFilter方法, 可调用多次
     *
     * @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("HelloFilter的doFilter方法被调用");
        //例如:验证是否的登录过,没有登录,返回到登录页面或者返间json, 需要的登录
        //filterChain  过滤器链, 不处理过滤器链, 那就认为链条断掉, 后续的filter和servlet都不会访问
        //filterChain.doFilter(servletRequest,servletResponse);
        filterChain.doFilter(servletRequest, servletResponse);//放行,执行后续的filter和servlet
    }

    /**
     * 销毁Filter时调用, 调用一次, 使用场景:释放资源
     */
    @Override
    public void destroy() {
        System.out.println("HelloFilter的destroy方法被调用");
    }
}

 web.xml配置HelloFilter

    <filter>
        <filter-name>HelloFilter</filter-name>
        <filter-class>com.tjetc.filter.HelloFilter</filter-class>
        <init-param>
            <param-name>age</param-name>
            <param-value>19</param-value>
        </init-param>
        <init-param>
            <param-name>email</param-name>
            <param-value>ww@163.com</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>HelloFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

 3、过滤器的各个方法执行顺序

  1. 构造方法
  2. init(filterConfig)初始化方法
  3. doFilter()方法
  4. destroy()方法
package com.tjetc.servlet;

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;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // resp.setContentType("text/html;charset=utf-8");
        // resp.getWriter().write("<h1>HelloServlet欢迎您!</h1>");

        //请求转发到my.jsp页面
        req.getRequestDispatcher("/my.jsp").forward(req, resp);
    }
}

web.xml配置HelloServlet

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.tjetc.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

my.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <img src="static/img/14.jpg" width="500px">
    </body>
</html>

TestServlet

package com.tjetc.servlet;

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

@WebServlet(value = "/test", initParams = {
        @WebInitParam(name = "username", value = "jack"),
        @WebInitParam(name = "age", value = "20")
})

public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = super.getInitParameter("username");
        String age = super.getInitParameter("age");
        System.out.println("username=" + username + ",age=" + age);
    }
}

 

 

4、FilterConfig接口的方法

5、FilterChain接口的方法

6、编码过滤器

package com.tjetc.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    //定义编码
    private String charset = "utf-8";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //读取参数
        String encoding = filterConfig.getInitParameter("charset");
        if (charset != null && " ".equals(encoding)) {
            charset = encoding;
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //转换request和response对象
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        //设置编码参数
        //设置请求对象的参数编码
        req.setCharacterEncoding(charset);
        //设置相应的参数编码
        resp.setContentType("text/html;charset=" + charset);
        //resp.setContentType(charset);
        //过滤器链放行
        filterChain.doFilter(req, resp);
    }

    @Override
    public void destroy() {

    }
}

总结

1、过滤器的作用

把相同通用的代码用过滤器实现,会让目标资源共享

2、过滤器的开发方法

  1. 写一个类实现Filter接口
  2. 重写接口的3个方法
  3. doFilter()写处理逻辑.
    • chain.doFilter()放行
    • 不调用chain.doFilter()不放行,到不了servlet或者jsp

3、过滤器的各个方法的执行顺序

  1. 构造方法
  2. 初始化方法init(FilterConfig fConfig)
  3. doFilter()方法
  4. destroy()方法 销毁方法

4、FilterConfig接口的方法

  1. getFilterName():返回xml配置的filter的名字
  2. getInitParameter(name):返回初始化的参数的值
  3. getInitParameterNames():返回所有的初始化参数的名字
  4. getServletContext():返回上下文对象

5、FilterChain接口的方法

1、doFilter()方法:

  1. 如果有下一个过滤器就执行下一个过滤器
  2. 没有就会执行目标资源(servlet或者jsp)

6、编码过滤器

  1. 初始化参数encoding=UTF-8
  2. doFilter():设置encoding

过滤器的配置

1、过滤器配置信息

1.过滤器的名称和类

2.过滤的url

3.过滤的url的访问方式

        1.REQUEST:默认的访问方式

                1.直接url访问

                2.超级链接

                3.form的提交

                4.重定向

                5.静态包含

        2.FORWARD

                请求转发

        3.INCLUDE

                动态包含

        4.ERROR

                错误页面的跳转

4.初始化参数

5.一个过滤器可以配置给多个url

6.一个url可以配置多个过滤器,多个过滤器组成过滤器链,按照配置的顺序执行

范例:

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.tjetc.filter.MyFilter</filter-class>
    <init-param>
        <param-name>name</param-name>
        <param-value>zs</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/order/*</url-pattern>
    <url-pattern>/cart/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

一个工程有多个过滤器,形成过滤器链

多个过滤器的执行顺序是什么?

根据filter-mapping的url-pattern的顺序来执行

利用过滤器实现访问控制

1、什么是访问控制

有很多资源需要登录后才能访问,称为访问控制

访问控制使用过滤器实现效果更佳.

2、登录过滤器实现访问控制

1、创建order.jsp订单页面

要访问order.jsp必须先登录才能访问,不登录不能访问

在WEB-INF下建个目录user,user下创建order.jsp,(WEB-INF下的不会被外部访问)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <h1>order.jsp</h1>
    </body>
</html>

2、创建登录过滤器,过滤/order/*请求

判断用户是否登录,如果用户登录,用户信息会放到session

到session拿用户信息:

  1. 如果用户信息不空代表用户已经登录,则放行
  2. 如果用户信息为空,代表用户未登录,则重定向到登录页面,让用户去登录
package com.tjetc.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        //从session中获取用户名,如果存在,就请求转发到order.jsp页面,如果不存在,就响应重定向到login.jsp页面
        String username = (String) req.getSession().getAttribute("username");
        if (username == null) { //不存在
            //响应重定向到login.jsp页面
            resp.sendRedirect(req.getContextPath() + "/login.jsp");
        } else { //存在
            //说明已经登录过了,放行
            filterChain.doFilter(req, resp);
        }
    }
}
    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>com.tjetc.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <!--url中/user开头的要经过过滤器,也就是要判断登录-->
        <url-pattern>/user/*</url-pattern>
    </filter-mapping>

3、创建login.jsp

<html>
    <head>
        <title>Title</title>
        <base href="<%=request.getContextPath()%>/">
    </head>
    <body>
        <form action="login" method="post">
            用户名:<input type="text" name="username"><br>
            密码:<input type="password" name="password"><br>
            <input type="submit" value="登录">
            <%
                String msg = (String) request.getAttribute("msg");
                if (msg != null) {
            %>
            <span style="color: #ff0032"><%=msg%></span>
            <%
                }
            %>
        </form>
    </body>
</html>

4、创建LoginServlet

从请求参数取得用户名和密码

判断用户名和密码是否正确

  1. 如果正确,将user放到session,session.setAttribute(“user”,user),重定向到success.jsp
  2. 如果错误,重定向到login.jsp继续登录
package com.tjetc.servlet;

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

public class LoginServlet 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 username = req.getParameter("username");
        String password = req.getParameter("password");
        //判断用户名和密码是否正确
        if ("tom".equals(username) && "123".equals(password)) {
            //登陆验证成功,要在session中存储用户信息
            req.getSession().setAttribute("username", username);
            //正确,跳转到订单页面, 响应重定向访问order页面url(/user/order  访问订单的servlet)
            resp.sendRedirect(req.getContextPath() + "/user/order");
        } else {
            //错误,请求转发跳转到登录页面,把错误消息返回给页面
            req.setAttribute("msg", "用户名或密码错误");
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }
    }
}
  <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.tjetc.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>

5、创建OrderServlet

package com.tjetc.servlet;

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

public class OrderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //请求转发到WEB-INF/user/order.jsp页面
        req.getRequestDispatcher("/WEB-INF/user/order.jsp").forward(req, resp);
    }
}
  <servlet>
        <servlet-name>OrderServlet</servlet-name>
        <servlet-class>com.tjetc.servlet.OrderServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>OrderServlet</servlet-name>
        <url-pattern>/user/order</url-pattern>
    </servlet-mapping>

 

Servlet3.0新特性

1:注解

Servlet3.0注解有五种类型:

@WebServlet:对Servlet进行配置

@WebInitParam:配置Servlet初始化参数

@WebFilter:配置过滤器

@WebListener :配置监听器

@MultipartConfig:对文件上传的支持

1、@WebServlet:对Servlet进行配置

  1. 必选属性

                1、value:   等价于 urlPatterns 属性。

                2、urlPatterns:等价于web.xml配置文件中的 <url-pattern> 标签

        二者的值是一样的,而且代表的含义也是一样的.其他是可选的

                3、注意:

                value和urlPatterns不能同时设置,只能使用其中的一个,同时设置就会报错

                Caused by:java.lang.IllegalArgumentException: 类文件[com.tjetc.servlet.HelloServlet]的urlPatterns和值属性上同时设置了注解[WebServlet]

                4、例子

                @WebServlet(urlPatterns={"/HelloServlet","/abc"})

2、可选属性

        1、name:等价于web.xml配置文件中的 <servlet-name>。

如果没有指定name, Servlet 的<servlet-name>取值为类的全限定名,比如XXX.XXX.XXX。

如果指定name,取值为指定的名字

        2、​​​​​​​​​​​​​​loadOnStartup:

等价于web.xml配置文件中的<load-on-startup> 标签

在服务器启动的时候就加载servlet,数字,越小代表越先启动

当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。

正数的值越小,该servlet的优先级越高,应用启动时就越先加载。

​​​​​​​​​​​​​​        ​​​​​​​3、initParams :

等价于web.xml配置文件中的<init-param> 标签,他的参数是@WebInitParam注解的集合

​​​​​​​​​​​​​​        4、description:

等价于web.xml配置文件中的<description> 标签

​​​​​​​​​​​​​​        ​​​​​​​5、displayName:

等价于web.xml配置文件中的 <display-name> 标签

​​​​​​​2、@WebInitParam

配置Servlet初始化参数,常用属性有三个,这三个属性当中只有description为可选属性:

name:等价于web.xml配置文件中的 <param-name>

value :等价于web.xml配置文件中的<param-value>

description:等价于web.xml配置文件中的<description>


​​​​​​​

@WebServlet(value = "/test", initParams = {
        @WebInitParam(name = "username", value = "jack"),
        @WebInitParam(name = "age", value = "20")
})

3、@WebFilter

配置过滤器此注解为声明一个过滤器,主要属性有以下几个。

​​​​​​​​​​​​​​        ​​​​​​​1、value、urlPatterns、servletNames至少包含一个

在这些属性当中value、urlPatterns、servletNames 三个属性至少要包含其中的一个,并且 value 和 urlPatterns 属性只能有一个,如果两个同时配置,一般情况下value取值将会被忽略。

  1. value:该属性等价于 urlPatterns 属性
  2. urlPatterns:等价于web.xml配置文件中的 <url-pattern> 标签
  3. servletNames:指定该过滤器将应用的范围。如果是注解的话取值是 @WebServlet 中的 name 属性的取值,如果servlet在 web.xml 中配置的话,取值是 <servlet-name> 的取值

​​​​​​​​​​​​​​        ​​​​​​​2、其他的都是可选属性

filterName:等价于web.xml配置文件中的 <filter-name>标签,过滤器的名称

dispatcherTypes:过滤器的转发模式。取值包括:

ASYNC(异步)、ERROR(错误)、FORWARD(请求转发)、INCLUDE(包含)、REQUEST(请求)。

initParams:等价于web.xml配置文件中的<init-param> 标签

description:等价于web.xml配置文件中的<description> 标签

displayName:等价于web.xml配置文件中的<display-name> 标签

@WebFilter(filterName = "HelloFilter",value = {"/*"},initParams ={
        @WebInitParam(name = "age",value = "13"),
        @WebInitParam(name = "email",value = "33@163.com")},
        dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD}
)

 

 

​​​​​​​4、@WebListener:配置监听器,

此注解是用来声明监听器,它主要的属性只有一个:

value:这个属性表示的是监听器的描述信息,整个配置可以简写成@WebListener("XXX")

 

package com.tjetc.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener

public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed");
    }
}

 


版权声明:本文为weixin_45701868原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。