JSP ---[过滤器]

Posted 小智RE0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSP ---[过滤器]相关的知识,希望对你有一定的参考价值。



过滤器


过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。

  • 过滤器位于客户端和web应用程序之间,用于检查和修改两者之间流过的请求.
  • 在客户端的请求访问后端资源之前,拦截某些请求。(在请求到达Servlet/JSP之前)
  • 在服务器的响应发送回客户端之前,处理这些响应。
  • 过滤器用来实现通用的功能,减少代码冗余,提高可维护性
  • 一个过滤器可以配置给多个资源使用
  • 一个资源可以配置多个过滤器,按照配置顺序调用
  • 可以将一个或多个过滤器附加到一个 Servlet 或一组 Servlet。过滤器也可以附加到 JavaServer Pages (JSP) 文件和 html 页面。
  • 过滤器是可用于 Servlet 编程的 Java 类

相关API接口


Filter ; FilterChain ; FilterConfig

Filter 接口

过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了三个方法:

public void init(FilterConfig filterConfig)
该方法对filter对象进行初始化仅在容器初始化filter对象结束后被调用一次。参数FilterConfig可以获得filter的初始化参数。
web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

public void doFilter (ServletRequest, ServletResponse, FilterChain)
该方法是filter进行过滤操作的方法当客户端的请求与过滤器设置的 URL 匹配时,Servlet 先调用过滤器的 doFilter 方法。方法体中可以对request和response进行预处理。其中FilterChain可以将处理后的request和response对象传递到过滤链上的下一个资源。

public void destroy( )
该方法在容器销毁过滤器对象前被调用;在该方法中释放Servlet过滤器占用的资源。

FilterChain接口

FilterChain接口类型作为Filter接口中doFilter方法的参数使用

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse)
将当前的请求和响应传递到当前过滤链上的下一个资源,可能是下一个过滤器,可能是目标资源。

FilterConfig接口

FilterConfig接口类型作为Filter接口中的init方法的参数使用

public String getInitParameter(String s),
获得过滤器的初始化参数值 ;在web.xml中,可以为每一个filter配置需要的初始化参数,与Servlet的类似。过滤器的初始化参数即可通过FilterConfig中的getInitParameter方法获取。如果指定名称的初始化参数不存在,则返回 null

public String getFilterName( )
用于返回在 web.xml 文件中为 Filter 所设置的名称,即返回 <filter-name> 元素的设置值

public ServletContext getServletContext( )
返回 FilterConfig 对象中所包装的 ServletContext 对象的引用

public Enumeration <String> getInitParameterNames( )
返回一个 Enumeration 集合对象,该集合对象包含在 web.xml 文件中为当前 Filter 设置的所有初始化参数的名称


案例


(1)在过滤器中为所有servlet配置公用的编码规则处理


注意导包时用的是import javax.servlet.*;

注意在原有项目包的基础上建立一个存放过滤类的工具包;例如名为filter的包

编写EncodingFilter过滤类,实现 Filter接口

public class EncodingFilter implements Filter {
    //初始化方法;不写时默认调用接口方法;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化方法");
    }
    //当客户端的请求与过滤器设置的 URL 匹配时,Servlet 先调用过滤器的 doFilter 方法。
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤处理方法");
        //设置字符编码过滤;
        servletRequest.setCharacterEncoding("utf-8");
        //使得请求继续向下执行;到达过滤链的下一个资源;
        filterChain.doFilter(servletRequest,servletResponse);
    }
    //销毁过滤器对象方法;不写时默认调用接口方法;
    @Override
    public void destroy() {
        System.out.println("释放资源方法");
    }
}

配置web.xml文件;在过滤器映射中可以直接用<url-pattern>/*</url-pattern>,将过滤器作用于当前的项目所有url地址.

<?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">



    <!--配置字符编码过滤器-->
    <filter>
        <!--filter-name:过滤器名称-->
        <filter-name>aboutEncodingFilter</filter-name>
        <!--filter-class:过滤器在当前项目的路径-->
        <filter-class>com.xiaozhi.filter.EncodingFilter</filter-class>
    </filter>
    <!--过滤器的映射-->
    <filter-mapping>
        <!--需要映射的过滤器名称-->
        <filter-name>aboutEncodingFilter</filter-name>
        <!--<url-pattern>:设置过滤器的作用地址;匹配对应url地址,有多个地址时可以写多个 -->
       <!-- <url-pattern>/login.jsp</url-pattern>-->
        <!--或者直接写 /* 匹配当前项目所有的地址-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <!--配置默认首选加载页-->
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

LoginServlet文件

//使用注解方式配置servlet
@WebServlet(name = "login",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到session对象; 直接调用强制销毁会话的方法;
        req.getSession().invalidate();
        //重定向到登录页面;
        resp.sendRedirect("login.jsp");
  }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取页面中对应name的值;
            String account = req.getParameter("account");
            String password = req.getParameter("password");
            //是否记住密码的标记;
             String rememberPW = req.getParameter("RememberPW");

             //创建session对象;
             HttpSession session;

            //这里仅仅是用equals方法进行了判断;
            if (account.equals("xiaozhi") && password.equals("123456")) {
                //当拿到的标记不为空时;创建cookie对象封装数据;
                if(rememberPW!=null){
                    Cookie name=new Cookie("name",account);
                    Cookie pw=new Cookie("password",password);
                    //设置Cookie的有效期(以秒为单位)
                    name.setMaxAge(365*24*3600);
                    pw.setMaxAge(365*24*3600);
                    //在响应时将cookie对象传到客户端;
                    resp.addCookie(name);
                    resp.addCookie(pw);

                }
                //从请求对象中获取对应的session对象;
                session = req.getSession();
                //将上面获取到的account的值设置给名为 name的属性;(以键值对的形式);
                session.setAttribute("name",account);
                //若符合条件,则重定向到页面LoginSuccess.jsp;
                resp.sendRedirect("loginSuccess.jsp");
            } else {
                //从请求对象中获取对应的session对象;
                session=req.getSession();
                //设置属性名为 errorMsg 的值为 "账号或密码错误!"
                session.setAttribute("errorMsg", "账号或密码错误!");
               //将页面重定向到login.jsp;
                resp.sendRedirect("login.jsp");
            }
       }
}

登录login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录</title>
</head>
<body>
<%--在服务器端获取到cookie--%>
<%
    //定义用户名和密码两个变量;
    String name = "";
    String password = "";
    //获取请求中的所有cookie;
    Cookie[] cookies = request.getCookies();
    //对获取的cookie判空;避免出现空指针异常;
    if (cookies != null) {
        //遍历获取到的cookie数组;
        for(Cookie ck:cookies){
            //得到对应name的cookie后;取到对应的值;
            if(ck.getName().equals("name")){
                name=ck.getValue();
            }
            if(ck.getName().equals("password")){
                password=ck.getValue();
            }
        }
    }
%>
<div>
    <%--获取到session对象中属性名为 errorMsg 的值 ;若不存在,则返回 null--%>
    <%--此时获取到的session对象和客户端访问服务器的是同一个;(都在同一个浏览器)--%>
<%
    String errorMsg =(String) session.getAttribute("errorMsg");
    out.print(errorMsg+"<br/>");
%>
    <%--这里直接在用户名和密码标签的value输入值;--%>
</div>
<form action="login" method="post">
    账号:<input type="text" name="account" value="<%out.print(name);%>"/><br/>
    密码:<input type="password" name="password" value="<%out.print(password);%>"/><br/>
    <input type="submit" value="登录"/><br/>
    记住密码:<input type="checkbox" name="RememberPW" value="RememberPW"/>
</form>
</body>
</html>

登陆成功loginSuccess.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录成功</title>
    <script type="text/javascript">
        function logout() {
            var result = confirm("确定退出?");
            //取到的result是布尔值;
            if(result){
                //使用replace方法获取一个url;	可用一个新页面取代当前页面。这里默认请求方式为 get;
                location.replace("login");
            }
        }
    </script>
</head>
<body>
<%--通过getAttribute方法获取到指定的参数名(name)对应的值;若不存在,则返回 null--%>
<%--此时获取到的session对象和客户端访问服务器的是同一个;(都在同一个浏览器)--%>
<%
    String account = (String) session.getAttribute("name");
%>
<%
    out.print("用户==> "+account+"你来了!"+"<br/>");
%>
<input type="button" value="安全退出的按钮" onclick="logout()"/><br/>
</body>
</html>

启动服务器;初始化方法执行;

关闭服务器后,销毁过滤器对象;销毁方法执行.


(2)得到登录成功的地址时,进行非法访问登陆成功页面,过滤器首先会判断是否已经登录账号;若未登录则拦截当前请求,拒绝访问资源;

创建AccessViolationFilter判断登录类

public class AccessViolationFilter implements Filter {
    //过滤处理方法;
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //判断用户是否已登录;
        //ServletRequest作为 HttpServletRequest 的父类;需要向下转型;
        HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
        //获取到session对象;
        HttpSession session = httpServletRequest.getSession();
        //获取到设置的用户名的值;
        String name = (String) session.getAttribute("name");
        if(name==null){
            //若为空值,则重定向到登录页面;
            HttpServletResponse httpServletResponse= (HttpServletResponse) servletResponse;
            httpServletResponse.sendRedirect("login.jsp");
        }else{
            //使请求继续向下执行;到达过滤链的下一个资源;
            filterChain.doFilter(servletRequest,servletResponse);
        }

    }
}

配置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">


    <!--配置字符编码过滤器-->
    <filter>
        <!--filter-name:过滤器名称-->
        <filter-name>aboutEncodingFilter</filter-name>
        <!--filter-class:过滤器在当前项目的路径-->
        <filter-class>com.xiaozhi.filter.EncodingFilter</filter-class>
    </filter>
    <!--过滤器的映射-->
    <filter-mapping>
        <!--需要映射的过滤器名称-->
        <filter-name>aboutEncodingFilter</filter-name>
        <!--<url-pattern>:设置过滤器的作用地址;匹配对应url地址,有多个地址时可以写多个 -->
       <!-- <url-pattern>/login.jsp</url-pattern>-->
        <!--或者直接写 /* 匹配当前项目所有的地址-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <!--配置判断登录过滤器-->
    <filter>
        <!--filter-name:过滤器名称-->
        <filter-name>AccessViolationFilter</filter-name>
        <!--filter-class:过滤器在当前项目的路径-->
        <filter-class>com.xiaozhi.filter.AccessViolationFilter</filter-class>
    </filter>
    <!--过滤器的映射-->
    <filter-mapping>
        <!--需要映射的过滤器名称-->
        <filter-name>AccessViolationFilter</filter-name>
        <!--<url-pattern>:设置过滤器的作用地址;匹配对应url地址-->
        <url-pattern>/loginSuccess.jsp</url-pattern>
    </filter-mapping>


    <!--配置默认首选加载页-->
    <!--设置默认加载页面-->
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>

</web-app>

当未登录时,访问登录成功页面;会被重定向到登录页面


以上是关于JSP ---[过滤器]的主要内容,如果未能解决你的问题,请参考以下文章

jsp frame

19 jsp——jsp的转发标签

JSP_动作和隐式对象

在jsp页面中如何获取另一个jsp页面提交的信息

jsp中将一个jsp引入另一个jsp指定位置

JSP学习日记