0%

Filter

Filter

Filter,过滤器,顾名思义,即是对数据等的过滤,预处理过程。为什么要引入过滤器呢?在平常访问网站的时候,有时候发一些敏感的信息,发出后显示时 就会将敏感信息用*等字符替代,这就是用过滤器对信息进行了处理。(摘自这篇博客

Filter:过滤器,用来过滤网站的数据。

  • 处理中文乱码
  • 登陆状态验证
  • 实现URL级别的权限访问控制
  • 过滤敏感词汇
  • 压缩响应信息
  • 等等

开发步骤

  1. 导包(Maven依赖,jar包)

  2. 编写过滤器

    • 导包不要错。实现接口Filter,注意是这个包:import javax.servlet.Filter

    • 实现方法init、doFilter、destroy

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      import javax.servlet.*;
      import java.io.IOException;
      public class CharacterEncodingFilter implements Filter {//注意是实现接口
      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
      //初始化:web服务器启动该方法就会被初始化,随时等待过滤对象出现
      }
      @Override
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
      //业务代码


      //让我们的请求继续走,如果不写,程序到这里就被拦截停止
      filterChain.doFilter(servletRequest,servletResponse);
      }
      @Override
      public void destroy() {
      //销毁:web服务器关闭时,过滤才会被销毁
      }
      }
  3. 注册Filter

    • 在web.xml中配置Filter(与注册Servlet相似)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <!--注册过滤器-->
      <filter>
      <filter-name>characterEncodingFilter</filter-name>
      <filter-class>com.qsdbl.filter.CharacterEncodingFilter</filter-class>
      </filter>
      <filter-mapping>
      <filter-name>characterEncodingFilter</filter-name>
      <url-pattern>/servlet/*</url-pattern><!--只要是/servlet下的任何请求,都会经过这个过滤器 -->
      </filter-mapping>

代码演示

(下边代码演示部分所使用的开发环境搭建,可以查看这里

解决乱码

过滤器解决中文乱码问题。

servlet

编写测试Servlet类demo02(继承HttpServlet类),当请求该Servlet时,就返回一段中文回去。没有做编码处理,会出现乱码。

在web.xml中配置请求路径/servlet/demo02/demo02

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--注册servlet-->
<servlet>
<servlet-name>showdemo02</servlet-name>
<servlet-class>com.qsdbl.jspdemo.demo02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>showdemo02</servlet-name>
<url-pattern>/servlet/demo02</url-pattern><!--注册 两个请求路径-->
</servlet-mapping>
<servlet-mapping>
<servlet-name>showdemo02</servlet-name>
<url-pattern>/demo02</url-pattern><!--注册 两个请求路径-->
</servlet-mapping>

Filter

编写过滤器CharacterEncodingFilter(实现Filter接口),对rescuest请求和response响应设置编码类型为ut f-8,解决中文乱码问题。

web.xml

要让过滤器起作用,还需要配置web.xml文件。(可以理解为把过滤器放到什么位置)。我们将该过滤器放置在/servlet下,即访问该目录下的资源都会经过该过滤器。而前边的demo02其中一个请求路径就设置在该目录下(/servlet/demo02/demo02

1
2
3
4
5
6
7
8
9
<!--注册过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>com.qsdbl.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern><!--只要是/servlet下的任何请求,都会经过这个过滤器 -->
</filter-mapping>

运行结果

Servlet类demo02配置了两个请求路径:/servlet/demo02/demo02

权限拦截

  • 管理员登陆页面,jsp页面,文件名:Login.jsp,放在web应用程序根目录
  • 验证功能,servlet程序,类名:LoginServlet,web.xml中注册的请求路径:/servlet/login
  • 提示权限不够的页面,jsp页面,文件名:error_login.jsp,放在web应用程序根目录
  • 后台主页,jsp页面,文件名:home.jsp,放在web应用程序根目录下的sys文件夹内即/sys/home.jsp
  • 过滤器,(实现接口Filter),类名:SysFilter,web.xml中配置过滤/sys下的所有资源
  • 退出登陆功能,servlet程序,类名:LogoutServlet,web.xml中注册的请求路径:/servlet/logout
  • 再编写一个类Constant,用于保存一些经常要使用的常量。一是避免用的地方多了容易写错,二是可以方便修改

原理:

  1. 当用户登陆成功后,将sessionID保存到当前的session对象中,字段名为USER_SESSION(LoginServlet程序实现)。然后跳转到后台主页。(session对象是保存在服务器端的)
  2. 后台主页,放在sys文件夹内
  3. 所有访问sys文件夹内的资源都会经过我们的过滤器,过滤器的作用是查看当前session对象中字段名为USER_SESSION的属性值是否存在(对应的value不为空)
  4. 若该字段的属性值为空,则重定向回登陆页面,不能访问sys文件夹内的资源。起权限拦截的作用

保存常量

类Constant,用于保存一些经常要使用的常量。一是避免用的地方多了容易写错,二是可以方便修改

1
2
3
4
5
package com.qsdbl.util;
public class Constant {
public final static String USER_SESSION = "USER_SESSION";
//将sessionID保存到session对象中时使用该字符串作为key(字段名)
}

登陆页面

文件名:Login.jsp,放在web应用程序根目录。${pageContext.request.contextPath},获取当前JSP页面所在的路径,其实就是web应用程序名(关于路径问题,可以访问这里复习一下)。点击提交按钮后,将数据发送给类LoginServlet处理(验证功能)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆</title>
</head>
<body>
<h1>登陆</h1>
<form action="${pageContext.request.contextPath}/servlet/login" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>

验证功能

这里主要是想记录一下过滤器实现权限拦截功能,所以不是真正的实现验证功能。为了方便测试,只是判断用户名是不是admin,以此确定登陆状态。使用数据库中的数据实现登陆验证功能,可以看看这篇笔记。(注意,字段名USER_SESSION是类Constant中的静态常量,static、final,通过Constant.USER_SESSION取得。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.qsdbl.jspdemo;
import com.qsdbl.util.Constant;
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 {
//获取前端请求的参数
String username = req.getParameter("username");
if (username.equals("admin")){//登陆成功
req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());//每个客户端连接都有一个session对象
resp.sendRedirect(req.getContextPath()+"/sys/home.jsp");//重定向到 主页
}else {//登陆失败
resp.sendRedirect(req.getContextPath()+"/error_login.jsp");//错误页面
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}

web.xml中注册的请求路径:/servlet/login

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.qsdbl.jspdemo.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/servlet/login</url-pattern>
</servlet-mapping>

登陆失败

提示权限不够的页面,jsp页面,文件名:error_login.jsp,放在web应用程序根目录。有一个链接用于返回登陆页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>错误</h1>
<h3>没有权限,用户名错误</h3>
<br>
<br>
<br>
<p><a href="${pageContext.request.contextPath}/Login.jsp">返回登陆页面</a></p>
</body>
</html>

登陆成功

后台主页,jsp页面,文件名:home.jsp,放在web应用程序根目录下的sys文件夹内即/sys/home.jsp。有一个链接用于退出登陆状态。类LogoutServlet处理。

退出登陆

退出登陆功能,servlet程序,类名:LogoutServlet。删掉字段名为USER_SESSION的属性值。(注意,字段名USER_SESSION是类Constant中的静态常量,static、final,通过Constant.USER_SESSION取得。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.qsdbl.jspdemo;
import com.qsdbl.util.Constant;
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 LogoutServlet extends HttpServlet {//用户退出登陆
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
if (user_session!=null){
req.getSession().removeAttribute(Constant.USER_SESSION);//删掉该属性值,而不是删掉session
}
resp.sendRedirect(req.getContextPath()+"/Login.jsp");//跳转到登陆页面(重定向)
}

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

web.xml中注册的请求路径:/servlet/logout

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>logout</servlet-name>
<servlet-class>com.qsdbl.jspdemo.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>logout</servlet-name>
<url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>

过滤器

过滤器,(实现接口Filter),类名:SysFilter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.qsdbl.filter;

import com.qsdbl.util.Constant;

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

public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
if (request.getSession().getAttribute(Constant.USER_SESSION) == null){//该字段值为空
response.sendRedirect(request.getContextPath()+"/Login.jsp");//跳转回登陆页面
}

filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
}

web.xml中配置过滤/sys下的所有资源

1
2
3
4
5
6
7
8
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.qsdbl.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/sys/*</url-pattern><!--只要是/sys下的任何请求,都会经过这个过滤器 -->
</filter-mapping>

运行结果

直接访问后台主页

先把过滤器在web.xml中的配置去掉。后台主页是我们不希望未登陆的用户访问的,如果不使用过滤器拦截那么知道了该页面的URL任何人都可以访问。

现在使用过滤器。(恢复在web.xml中的配置)。未登陆状态下,直接访问后台主页会被过滤器拦截,重定向回登陆页面。

模拟退出登陆

过滤器通过判断session对象中字段名为USER_SESSION的属性值是否为空,来判断是否要拦截客户端(浏览器)的请求。session对象是保存在服务器端的。

若图片不能正常显示,请在浏览器中打开

欢迎关注我的其它发布渠道