JavaWeb Filter

1. 过滤器概述

1.1. 什么是过滤器

Filter译为过滤器,是JavaWeb的三大组件之一,用于在Servlet以外对Request或者Response进行修改。对于Web应用程序来讲,过滤器是一个驻留在服务器端的Web组件,它能够截取客户端和服务器端之间的请求与响应信息。html

1.2. 发展历史

因为Servlet规范是开放的,借助于公众与开源社区的力量,Servlet规范愈来愈科学,功能也愈来愈强大。2000年,Sun公司在Servlet2.3规范中添加了Filter功能,并在Servlet2.4中对Filter进行了细节上的补充。目前主流版本为Servlet2.5Filterjava

1.3. 运行原理

Servlet是服务器端用于处理客户端的请求与响应的,而Filter就是介于客户端与服务器端拦截客户端的请求或服务器端的响应,并对其修改或过滤。具体实现流程以下:web

当客户端向服务器端发送一个请求时,若是有对应的过滤器进行拦截,过滤器能够改变请求的内容、或者从新设置请求协议的相关信息等,而后再将请求发送给服务器端的Servlet进行处理。当Servlet对客户端作出响应时,过滤器一样能够进行拦截,将响应内容进行修改或者从新设置后,再响应给客户端浏览器。在上述过程当中,客户端与服务器端并不须要知道过滤器的存在。api

在一个Web应用程序中,能够部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。过滤器链中的每一个过滤器负责特定的操做和任务,客户端的请求在这些过滤器之间传递,直到服务器端的Servlet。具体执行流程以下:浏览器

1.4. 第一个过滤器

Servlet API中提供了一个Filter接口,实现过滤器只须要实现该接口便可。如下是Filter接口的API缓存

Method Summary服务器

voidcookie

destroy() 
Called by the web container to indicate to a filter that it is being taken out of service.session

voidapp

doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.

void

init(FilterConfig filterConfig) 
Called by the web container to indicate to a filter that it is being placed into service.

实现过滤器的具体步骤以下:

  • 建立一个Java类,并实现Filter接口,重写该接口的方法。
public class MyFitler implements Filter {
    /**
     * init()方法用于Filter的初始化
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("执行了Filter的init()方法...");
    }
    /**
     * doFilter()方法用于Filter的拦截
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("执行了Filter的doFilter()方法...");
    }
    /**
     * destory()方法用于Filter的销毁
     */
    public void destroy() {
        System.out.println("执行了Filter的destroy()方法...");
    }
}
  • Web工程的web.xml文件中配置过滤器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <!-- 配置过滤器 -->
  <filter>
      <!-- 配置过滤器的名称 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置对应过滤器类的完整路径 -->
      <filter-class>app.java.fitler.MyFitler</filter-class>
  </filter>
  <!-- 配置过滤器的拦截路径 -->
  <filter-mapping>
      <!-- 配置过滤器的名称 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置过滤器的拦截的路径 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
  • 建立Web动态资源Servlet
public class HelloServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<h1>Hello Servlet.</h1>");
        out.flush();
        out.close();
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • Web工程的web.xml文件中配置Servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>app.java.servlet.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>
  • 建立Web工程的静态资源JSP页面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>hello.jsp</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
  </head>
  <body>
    <h1>Hello JSP.</h1>
  </body>
</html>
  • 发布Web工程并访问,不管是访问动态资源Servlet仍是静态资源JSP,过滤器都会拦截,并执行过滤器的doFilter()方法。
  • 这时访问的Servlet或者JSP并无被执行,缘由是过滤器只进行了拦截,并无将请求发送到对应的Servlet或者JSP。在过滤器的doFilter()方法中执行FilterChain对象的doFilter()方法将进行放行。
public class MyFitler implements Filter {
    /**
     * init()方法用于Filter的初始化
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("执行了Filter的init()方法...");
    }
    /**
     * doFilter()方法用于Filter的拦截
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("执行了Filter的doFilter()方法...");
        chain.doFilter(request, response);
    }
    /**
     * destory()方法用于Filter的销毁
     */
    public void destroy() {
        System.out.println("执行了Filter的destroy()方法...");
    }
}

2. 深刻过滤器

2.1. 生命周期

Servlet API提供的Filter接口中含有三个方法,分别为init()doFilter()destroy()方法。该三个方式就是Filter的生命周期方法。

  • Filter的构造函数
  • Tomcat服务器启动时执行。
  • Filter的生命周期中只执行一次。
  • init(FilterConfig)方法
    • Tomcat服务器启动时执行。
    • Filter的生命周期中只执行一次。
    • 用于Filter的初始化工做。
  • doFilter(ServletRequest, ServletResponse, FilterChain)方法
    • 在每次拦截时执行。
    • Filter的生命周期中只执行屡次。
    • 用于Filter的拦截处理工做。
  • destroy()方法
    • Tomcat服务器关闭时执行。
    • Filter的生命周期中只执行一次。
    • 用于Filter的销毁工做。

2.2. 过滤器链

在一个Web应用程序中,能够部署多个过滤器进行拦截,这些过滤器组成了一个过滤器链。完成过滤器链的功能,具体步骤以下:

  • 建立一个Java类,并实现Filter接口,重写该接口的方法。
public class MyFitler1 implements Filter {
    /**
     * init()方法用于Filter的初始化
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("执行了Filter1的init()方法...");
    }
    /**
     * doFilter()方法用于Filter的拦截
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("执行了Filter1的doFilter()方法...");
    }
    /**
     * destory()方法用于Filter的销毁
     */
    public void destroy() {
        System.out.println("执行了Filter1的destroy()方法...");
    }
}
  • 再建立一个Java类,并实现Filter接口,重写该接口的方法。
public class MyFilter2 implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("执行了Filter2的init()方法...");
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("执行了Filter2的doFilter()方法...");
    }
    public void destroy() {
        System.out.println("执行了Filter2的destroy()方法...");
    }
}
  • Web工程的web.xml文件中配置过滤器。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <!-- 配置过滤器 -->
  <filter>
      <!-- 配置过滤器的名称 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置对应过滤器类的完整路径 -->
      <filter-class>app.java.fitler.MyFitler</filter-class>
  </filter>
  <!-- 配置过滤器的拦截路径 -->
  <filter-mapping>
      <!-- 配置过滤器的名称 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置过滤器的拦截的路径 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter>
      <filter-name>MyFitler2</filter-name>
      <filter-class>app.java.fitler.MyFilter2</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>MyFitler2</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

须要注意的是,FilterChaindoFilter()方法执行时,若是只有一个过滤器的话,执行该方法会将请求发送给服务器端的动态或静态资源。若是是过滤器链的话,只有在执行过滤器链的最后一个过滤器的FilterChaindoFilter()方法时,才会将请求发送给服务器端的动态或静态资源。若是不是在过滤器链的最后一个过滤器的FilterChaindoFilter()方法时,将请求发送给下一个过滤器进行拦截。

在过滤器链中的过滤器执行的前后顺序是按照Web工程的web.xml文件配置过滤器的前后顺序被执行。

2.3. FilterConfig

在过滤器接口的init()方法中提供了FilterConfig参数,经过该参数能够获取web.xml配置过滤器的参数内容,或者获取ServletContext对象等。FilterConfig API内容以下:

Method Summary

String

getFilterName() 
Returns the filter-name of this filter as defined in the deployment descriptor.

String

getInitParameter(String name) 
Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.

Enumeration

getInitParameterNames() 
Returns the names of the filter's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the filter has no initialization parameters.

ServletContext

getServletContext() 
Returns a reference to the ServletContext in which the caller is executing.

具体使用方式以下:

  • 建立一个Java类,并实现Filter接口,重写该接口的方法。
public class MyFitler implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("执行了Filter的init()方法...");
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("执行了Filter的doFilter()方法...");
    }
    public void destroy() {
        System.out.println("执行了Filter的destroy()方法...");
    }
}
  • Web工程的web.xml文件中配置过滤器,而且设置初始化参数内容。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>MyFitler</filter-name>
      <filter-class>app.java.fitler.MyFitler</filter-class>
      <init-param>
          <param-name>longestory</param-name>
          <param-value>http://www.baidu.com.com</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>MyFitler</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
  • 在过滤器的init()方法中获取配置文件的初始化参数。
public class MyFitler implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("执行了Filter的init()方法...");
System.out.println(filterConfig.getInitParameter("longestory"));
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("执行了Filter的doFilter()方法...");
    }
    public void destroy() {
        System.out.println("执行了Filter的destroy()方法...");
    }
}

须要注意的是,经过getInitParameter()方法获取的初始化参数是私有参数。只有当前过滤器才能获取到,而其余过滤器并不能访问。若是配置全局初始化参数,可使用<context-param>来配置,并使用ServletContext对象获取。

2.4. Filter映射配置

过滤器须要配置在web.xml中才能生效。一个过滤器须要配置<filter><filter-mapping>标签,例如以下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <!-- 配置过滤器 -->
  <filter>
      <!-- 配置过滤器的名称 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置对应过滤器类的完整路径 -->
      <filter-class>app.java.fitler.MyFitler</filter-class>
  </filter>
  <!-- 配置过滤器的拦截路径 -->
  <filter-mapping>
      <!-- 配置过滤器的名称 -->
      <filter-name>MyFitler</filter-name>
      <!-- 配置过滤器的拦截的路径 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

<filter>配置过滤器的名称,实现类以及初始化参数。<filter-mapping>配置当前过滤器拦截的路径。<filter-mapping>中的<url-pattern>标签用于配置当前过滤器拦截的路径,配置方式与Servlet<url-pattern>配置方式相似,共有三种方式:

  • 彻底匹配
  • 目录匹配
  • 扩展名匹配

若是须要拦截的是Servlet的话,有两种方式配置拦截路径:

  • 使用<url-pattern>标签:<url-pattern>/hello</url-pattern>
  • 使用<servlet-name>标签:<servlet-name>HelloServlet</servlet-name>

<dispatcher>标签配置到达Servlet的方法,有四种取值:REQUESTFORWARDINCLUDEERROR。能够同时配置多个<dispatcher>标签,若是没有配置<dispatcher>标签,默认为REQUEST。这四种取值的区别以下:

  • REQUEST:表示仅当直接请求Servlet时才生效。
  • FORWARD:表示仅当某Servlet经过FORWARD到该Servlet时才生效。
  • INCLUDEJSP中能够经过<jsp:include>标签请求某Servlet或调用RequestDispatcherinclude()方法请求某Servlet,仅这种状况下有效。
  • ERRORJSP中能够经过<%@ page errorPage=”error.jsp”>标签指定错误处理页面,仅这种状况下有效。

<url-pattern>标签与<dispatcher>标签的关系是“且”的关系。只有知足<url-pattern>标签的条件,且知足<dispatcher>标签的条件时,当前过滤器才能生效。

3. 过滤器案例

3.1. 全站乱码案例

中文乱码问题一直都是Web应用开发的问题,想要解决整个Web应用程序的中文乱码问题,能够以下操做:

  • 建立一个Java类继承于HttpServletRequestWrapper类,用于重写HttpServletRequest,解决GET方式的中文乱码问题。
public class MyRequest extends HttpServletRequestWrapper {
    public MyRequest(HttpServletRequest request) {
        super(request);
    }
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (getMethod().equalsIgnoreCase("GET")) {
            try {
                value = new String(value.getBytes("ISO-8859-1"),"utf-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return value;
    }
}
  • 建立一个过滤器用于解决整个Web应用程序的中文乱码问题。
public class EncodingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        MyRequest req = new MyRequest((HttpServletRequest)request);
        chain.doFilter(req, response);
    }
    public void destroy() {}
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>EncodingFilter</filter-name>
      <filter-class>app.java.demo4.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>EncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
  • 建立一个JSP页面用于中文乱码问题的测试。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'login.jsp' starting page</title>
  </head>
  <body>
    <form id="userinfo" action="encoding" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="登陆">
    </form>
    <a href="/encoding?username=张无忌">GET方式的中文乱码问题</a>
  </body>
</html>
  • 建立一个Servlet用于测试中文乱码问题。
public class EncodingServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        response.getWriter().println("<h1>username : "+username+"</h1>");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>EncodingServlet</servlet-name>
    <servlet-class>app.java.servlet.EncodingServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>EncodingServlet</servlet-name>
    <url-pattern>/encoding</url-pattern>
  </servlet-mapping>
</web-app>

3.2. 自动登陆案例

所谓自动登陆就是当用户第一次登陆后,而且选择“自动登陆”选项,用户从第二次访问开始,用户都无需再登陆,完成直接登陆的功能。具体实现步骤以下:

  • 建立一个JSP页面用于用户登陆功能。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'login.jsp' starting page</title>
  </head>
  <body>
    <h3 style="color:red;">${msg }</h3>
    <form id="userinfo" action="login" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="checkbox" name="autologin" value="true">自动登陆<br>
        <input type="submit" value="登陆">
    </form>
  </body>
</html>
  • 建立一个JavaBean用于封装用户信息。
public class User {
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
  • 建立一个Servlet用于处理用户登陆逻辑。
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if("admin".equals(username)&&"admin".equals(password)){
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            
            HttpSession session = request.getSession();
            session.setAttribute("user", user);
            
            if("true".equals(request.getParameter("autologin"))){
                Cookie cookie = new Cookie("autologin", username+"#"+password);
                cookie.setPath("/");
                cookie.setMaxAge(60 * 60 * 24 * 90);
                response.addCookie(cookie);
            }
            response.sendRedirect("index.jsp");
            return;
        }else{
            request.setAttribute("msg", "用户名或密码错误,请从新输入.");
            request.getRequestDispatcher("login.jsp").forward(request, response);
            return;
        }
    }
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>app.java.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>
</web-app>
  • 建立一个JSP页面用于显示主页面,显示用户登陆信息。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  <body>
    <c:if test="${empty user }">
        <h1>您还未登陆,请去<a href="login.jsp">登陆</a></h1>
    </c:if>
    <c:if test="${not empty user }">
        <h1>欢迎您,${user.username }</h1>
    </c:if>
  </body>
</html>
  • 建立一个过滤器用于完成自动登陆功能。
public class AutoLoginFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        // 判断用户是否选择手动登陆
        if(req.getSession().getAttribute("user") != null){
            // 已经登陆
            chain.doFilter(request, response);
            return;
        }else{
            // 没有登陆,查找是否含有自动登陆Cookie
            Cookie autoLoginCookie = findCookie(req.getCookies(), "autologin");
            if (autoLoginCookie == null){
                // 没有自动登陆信息
                chain.doFilter(request, response);
                return;
            }else{
                // 存在自动登陆信息
                String username = autoLoginCookie.getValue().split("#")[0];
                String password = autoLoginCookie.getValue().split("#")[1];
                if (!"admin".equals(username)||!"admin".equals(password)) {
                    // 自动登陆信息有问题
                    chain.doFilter(request, response);
                }else{
                    // 完成自动登陆功能
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    req.getSession().setAttribute("user", user);
                    chain.doFilter(request, response);
                    return;
                }
            }
        }
    }
    public Cookie findCookie(Cookie[] cookies, String name) {
        if (cookies == null) {
            return null;
        } else {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    return cookie;
                }
            }
            return null;
        }
    }
    public void destroy() {}
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>AutoLoginFilter</filter-name>
      <filter-class>app.java.demo2.AutoLoginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>AutoLoginFilter</filter-name>
      <url-pattern>/index.jsp</url-pattern>
  </filter-mapping>
</web-app>

3.3. 权限控制案例

通常状况下,Web应用程序不能容许全部用户能够访问全部功能。换句话讲,不一样的用户具备访问不一样功能的权限。因此,须要完成权限控制功能,具体操做以下:

  • 建立JavaBean用于封装用户信息(包含权限信息)。
public class User {
    private String username;
    private String password;
    private String role;
    public String getRole() {
        return role;
    }
    public void setRole(String role) {
        this.role = role;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
  • 建立Web应用程序的主页面,用于用户功能的显示。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  <body>
    <c:if test="${empty user }">
        <h1>您还未登陆,请去<a href="login.jsp">登陆</a></h1>
    </c:if>
    <c:if test="${not empty user }">
        <h1>欢迎您,${user.username }</h1>
        <h1><a href="user/userlist.jsp">用户操做功能列表</a></h1>
        <h1><a href="admin/adminlist.jsp">管理员操做功能列表</a></h1>
    </c:if>
  </body>
</html>
  • 建立用户能够访问的功能列表页面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'userlist.jsp' starting page</title>
  </head>
  <body>
    <h1>这里是用户操做的功能列表!</h1>
  </body>
</html>
  • 建立管理员能够访问的功能列表页面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'adminlist.jsp' starting page</title>
  </head>
  <body>
    <h1>这里是管理员操做的功能列表!</h1>
  </body>
</html>
  • 建立一个过滤器用于完成权限控制功能。
public class AuthoFilter implements Filter {
    private FilterConfig config;
    private Map<String, String> map = new HashMap<String, String>();
    public void init(FilterConfig filterConfig) throws ServletException {
        this.config = filterConfig;
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        Enumeration names = config.getInitParameterNames();
        while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            String value = config.getInitParameter(name);
            map.put(value, name);
        }
        HttpServletRequest req = (HttpServletRequest) request;
        String path = req.getRequestURI().substring(req.getContextPath().length());
        for (String needPath : map.keySet()) {
            if (path.startsWith(needPath)) {
                String needRole = map.get(needPath);
                User user = (User) req.getSession().getAttribute("user");
                if (user == null) {
                    req.getRequestDispatcher("login.jsp").forward(request, response);
                    return;
                }else {
                    String role = user.getRole();
                    if (needRole.equals(role)) {
                        chain.doFilter(request, response);
                        return;
                    }else {
                        throw new RuntimeException("权限不足,没法访问!");
                    }
                }
            }
        }
        chain.doFilter(request, response);
    }
    public void destroy() {}
}
  • 配置Web工程的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>AuthoFilter</filter-name>
      <filter-class>app.java.demo3.AuthoFilter</filter-class>
      <init-param>
          <param-name>user</param-name>
          <param-value>/user</param-value>
      </init-param>
      <init-param>
          <param-name>admin</param-name>
          <param-value>/admin</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>AuthoFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

3.4. 禁用缓存案例

以前完成过禁止浏览器缓存功能,使用的是响应协议头中的三个内容,以下:

Expires: -1

禁用浏览器缓存(考虑不一样浏览器兼容性,存在三个字段)

Cache-Control: no-cache

Pragma: no-cache

在服务器端Servlet代码以下:

//设置响应头信息,禁止浏览器缓存.
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);

但这种方式只能适用于一个JSP页面,而一个Web应用程序中可能包含多个JSP页面。若是想要整个Web应用程序的全部JSP页面都禁止缓存,须要使用过滤器功能来完成,具体操做以下:

  • 建立一个过滤器类,实现Filter接口,并重写全部方法。
public class NoCacheFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {}
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        //1 将ServletResponse强转为HttpServletResponse
        HttpServletResponse res = (HttpServletResponse)response;
        //2 禁止浏览器缓存功能
        res.setHeader("Cache-Control", "no-cache");
        res.setHeader("Pragma", "no-cache");
        res.setDateHeader("Expires", -1);
        //3 过滤器放行
        chain.doFilter(request, response);
    }
    public void destroy() {}
}
  • 配置Web工程中的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <filter>
      <filter-name>NoCacheFilter</filter-name>
      <filter-class>app.java.demo1.NoCacheFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>NoCacheFilter</filter-name>
      <url-pattern>*.jsp</url-pattern>
  </filter-mapping>
</web-app>
相关文章
相关标签/搜索