前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >day17_Listener与Filter学习笔记

day17_Listener与Filter学习笔记

作者头像
黑泽君
发布2018-10-11 11:01:44
3680
发布2018-10-11 11:01:44
举报
文章被收录于专栏:黑泽君的专栏黑泽君的专栏

一、Listener监听器(了解)

Javaweb开发中的监听器,是用于监听web常见对象的。     例如web的常见对象有:ServletContext、HttpServletRequest、HttpSession     监听它们的创建与销毁属性变化session绑定javaBean

1、监听机制

    事件:就是一个事情。     事件源:产生这个事情的源头。     监听器:用于监听指定的事件的对象。(关联事件和事件源)     注册监听:要想让监听器可以监听到事件产生,必须对其进行注册。

2、Javaweb开发中常见监听器

  2.1、监听域对象的创建与销毁

    若要监听ServletContext对象的创建与销毁       则需要写一个监听器类实现 ServletContextListener 接口     若要监听HttpSession对象的创建与销毁         则需要写一个监听器类实现 HttpSessionListener 接口     若要监听HttpServletRequest对象的创建与销毁    则需要写一个监听器类实现 ServletRequestListener 接口

  2.2、监听域对象的属性变化

    若要监听ServletContext对象的属性变化       则需要写一个监听器类实现 ServletContextAttributeListener 接口     若要监听HttpSession对象的属性变化         则需要写一个监听器类实现 HttpSessionAttributeListener 接口     若要监听HttpServletRequest对象的属性变化    则需要写一个监听器类实现 ServletRequestAttributeListener 接口

  2.3、监听session绑定javaBean

    若要监听javaBean对象是否绑定到了session域    则需要写一个javaBean实现 HttpSessionBindingListener 接口     若要监听javaBean对象的活化与钝化          则需要写一个javaBean实现 HttpSessionActivationListener 接口

3、监听器的快速入门

  关于创建一个监听器的步骤:     1. 创建一个监听器类,实现指定的监听器接口。     2. 重写接口中的方法。     3. 在web.xml文件中对监听器进行注册

  3.1、关于域对象的创建与销毁的演示

    1. ServletContext对象的创建与销毁 ServletContext对象是在服务器启动时创建的,在服务器关闭时销毁的。

package com.itheima.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext对象被创建了"); // 服务器一启动,ServletContext对象就被创建了
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext对象被销毁了"); // 服务器一关闭,ServletContext对象就被销毁了
    }
}

    2. HttpSession对象的创建与销毁       HttpSession session = request.getSession();       Session的销毁方式         1. 默认超时30分钟后销毁         2. 关闭服务器时销毁         3. 调用invalidate()方法         4. setMaxInactiveInterval(int interval) 可以设置超时时间 问题:直接访问一个jsp页面时,是否会创建Session?         答:会创建,因为我们默认情况下是在jsp页面中直接使用Session内置对象的。

package com.itheima.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MyHttpSessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("HttpSession对象被创建了");
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("HttpSession对象被销毁了");
    }
}

    index.jsp

  <body>
    <%
        session.invalidate(); // 手动使session销毁
     %>
  </body>

    3. HttpServletRequest对象的创建与销毁 Request对象是发送请求时服务器就会去创建它,当响应产生时,request对象就会被销毁。

package com.itheima.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class MyServletRequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("ServletRequest被销毁了");
    }
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("ServletRequest被创建 了");
    }
}

  3.2、演示Request域对象中的属性变化

    在java的监听机制中,它的监听器中的方法都是有参数的参数就是事件对象,而我们可以通过事件对象直接获取事件源。

package com.itheima.attributelistener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
public class MyServletRequestListener implements ServletRequestAttributeListener {
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("ServletRequest添加属性了");
    }
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        System.out.println("ServletRequest移除属性了");
    }
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) { // 参数代表事件对象
        System.out.println("ServletRequest替换属性了");
        // srae.getServletRequest(); // 通过事件对象直接获取事件源
        // System.out.println(srae.getName() + "\t" + srae.getValue()); // org.apache.catalina.ASYNC_SUPPORTED  true
    }
}

    index.jsp

  <body>
    <%
        // session.invalidate(); // 手动使session销毁
        request.setAttribute("name", "tom");
        request.setAttribute("name", "luna");
        request.removeAttribute("name");
     %>
  </body>

  3.3、演示session绑定javaBean

    1.javaBean对象自动感知被绑定到session中 HttpSessionBindingListener 这个接口是由javaBean实现的,并且不需要在web.xml文件中进行注册。

package com.itheima.domain;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class User implements HttpSessionBindingListener {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("向session中绑定了一个user对象");
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("从session中将user对象移除");
    }
}

    index.jsp

  <body>
    <%
        // session.invalidate(); // 手动使session销毁

        // request.setAttribute("name", "tom");
        // request.setAttribute("name", "luna");
        // request.removeAttribute("name");

        User user = new User();
        user.setName("luna");
        user.setAge(25);
        // 绑定到session
        session.setAttribute("u", user); 
        // 解除绑定
        session.removeAttribute("u"); 
     %>
  </body>

    2.javabean对象可以活化或钝化到session中       HttpSessionActivationListener,如果javaBean实现了这个接口,那么当我们正常关闭服务器时,session中的javaBean对象就会被钝化到我们指定的文件中。       当下一次再启动服务器,因为我们已经将对象写入到文件中,这时就会自动将javaBean对象活化到session中。

package com.itheima.domain;
import java.io.Serializable;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
public class User implements Serializable, HttpSessionBindingListener, HttpSessionActivationListener {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("向session中绑定了一个user对象");
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("从session中将user对象移除");
    }
    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println("钝化");
    }
    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println("活化");
    }
}

    我们还需要个context.xml文件来配置钝化时存储的文件,在META-INF目录下创建一个context.xml文件,输入以下代码:

<Context>
    <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
        <Store className="org.apache.catalina.session.FileStore" directory="it315"/>
    </Manager>
</Context>

4、监听器的案例

  4.1、案例_定时销毁session

  1. 怎样可以将每一个创建的session全都保存起来呢? 答:我们可以做一个HttpSessionListener,当session对象创建时,就将这个session对象装入到一个集合中,然后将集合List<HttpSession>保存到ServletContext域中。
  2. 怎样判断session是否过期了呢? 答:在HttpSession中有一个方法public long getLastAccessedTime(),它可以得到session对象最后使用的时间。然后可以使用invalidate方法销毁

    我们上面的操作需要使用任务调度功能

  在java中有一个Timer定时器类,定时器测试代码:     TestTimer.java

package com.itheima.timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TestTimer {
    public static void main(String[] args) {
        // 创建一个计时器对象
        Timer t = new Timer();
        // 调度任务功能
        t.schedule(new TimerTask() { // 要执行的任务
            @Override
            public void run() {
                System.out.println(new Date().toLocaleString());
            }
        }, 5000, 1000); // 5秒后开始,每隔1秒执行一次
    }
}

    监听ServletContext代码:

package com.itheima.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;
public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 通过事件对象得到事件源(ServletContext)
        ServletContext application = sce.getServletContext();
        // 创建一个集合用于存储所有的session对象(需要考虑并发问题,因为我们在web中,它一定是一个多线程的)
        final List<HttpSession> list = Collections.synchronizedList(new ArrayList<HttpSession>());
        // 把集合放到application域中
        application.setAttribute("sessions", list);
        // 创建一个计时器对象
        Timer t = new Timer();
        // 调度任务
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("开始扫描了...");
                for (Iterator iterator = list.iterator(); iterator.hasNext();) {
                    HttpSession session = (HttpSession) iterator.next();
                    long l = System.currentTimeMillis() - session.getLastAccessedTime();
                    if (l > 5000) { // 如果时间大于5秒,就把session销毁
                        System.out.println("session移除了" + session.getId());
                        session.invalidate(); // 把session销毁
                        iterator.remove();
                    }
                }
                /*
                for (HttpSession session : list) { 
                    long l = System.currentTimeMillis() - session.getLastAccessedTime();
                    if (l > 5000) { // 如果时间大于5秒,就把session销毁
                        session.invalidate(); // 把session销毁
                        list.remove(session); // 从集合中移除 
                    } 
                }
                */
            }
        }, 2000, 5000); // 延迟2秒后执行,每间隔5秒执行一次
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

    监听Session代码:

package com.itheima.test;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class MySessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // 通过事件源得到HttpSession对象
        HttpSession session = se.getSession();
        // 得到application对象(ServletContext对象)
        ServletContext application = session.getServletContext();
        // 得到session对象,并放入到list集合中
        List<HttpSession> list = (List<HttpSession>) application.getAttribute("sessions");
        list.add(session);
        System.out.println("添加了" + session.getId());
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
    }
}

    配置注册监听代码:

    <listener>
        <listener-class>com.itheima.test.MyServletContextListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.itheima.test.MySessionListener</listener-class>
    </listener>

二、Filter过滤器(重要)

Javaweb中的过滤器可以拦截所有访问web资源的请求响应操作。

1、Filter快速入门

    步骤:       1. 创建一个类实现Filter接口。       2. 重写接口中方法,其中doFilter方法是真正过滤用的。       3. 在web.xml文件中进行配置。 注意:在实现Filter接口的类中重写的doFilter方法内如果没有执行这句代码chain.doFilter(request, response);那么浏览器访问服务器的资源是不会被访问到的。     示例代码如下:

package com.itheima.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilter1 implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("MyFilter1拦截开始了"); // 对浏览器发送的请求进行过滤
        // 放行
        chain.doFilter(request, response);
        System.out.println("MyFilter1拦截结束了"); // 对服务器返回的响应进行过滤
    }
    @Override
    public void destroy() {
    }
}

    在web.xml文件中进行配置。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>day17_01_filter</display-name>
  <filter>
      <filter-name>MyFilter1</filter-name>
      <filter-class>com.itheima.filter.MyFilter1</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>MyFilter1</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>ServletDemo1</servlet-name>
    <servlet-class>com.itheima.servlet.ServletDemo1</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ServletDemo1</servlet-name>
    <url-pattern>/servlet/demo1</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

  测试代码     测试代码一:http://localhost:8080/day17_01_filter/index.jsp     测试代码二:http://localhost:8080/day17_01_filter/servlet/demo1

package com.itheima.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo1 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ServletDemo1");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

2、FilterChain过滤器链

    FilterChain 是 servlet 容器(即服务器)为开发人员提供的对象,它提供了对某一资源的已过滤请求调用链的视图。     过滤器使用 FilterChain 调用链中的下一个过滤器(由我们配置的web.xml的先后顺序决定),如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。 问题:怎样可以形成一个Filter链?       答:只要多个Filter对同一个资源进行拦截就可以形成Filter链。 问题:怎样确定Filter的执行顺序?       答:由web.xml中的<filter-mapping>的先后顺序来确定。     示例代码如下图所示:

3、Filter的生命周期

Servlet的生命周期:       实例化 --> 初始化 --> 服务 --> 销毁         当第一次访问服务器资源的时候,Servlet就进行实例化和初始化,只调用一次。(二者不同的地方)         只要应用在(即应用没有卸载),service服务就一直在。         只要应用卸载了或者服务器停止了,Servlet就销毁了。

Filter的生命周期:         当服务器启动时,会创建Filter对象(即调用构造方法进行实例化),并调用init方法,只调用一次。(二者不同的地方)         当浏览器访问服务器资源时,路径与Filter的拦截路径匹配后,会执行Filter中的doFilter方法,这个方法是真正拦截操作的方法。         当服务器关闭或应用卸载时,会调用Filter中的destroy方法来进行销毁操作。

4、FilterConfig过滤器参数

    在Filter的init方法上有一个参数,类型就是FilterConfig。     FilterConfig它是Filter的配置对象,它可以完成下列功能:         1. 获取Filter名称。         2. 获取Filter初始化参数。         3. 获取ServletContext对象。     如下图所示:

问题:怎样在Filter中获取一个FIlterConfig对象呢?       答:如下图所示:

5、Filter的配置文件书写格式

基本配置

    <filter>
        <filter-name>Filter名称</filter-name>
        <filter-class>Filter类的包名.类名</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter名称</filter-name>
        <url-pattern>路径</url-pattern>
    </filter-mapping>

关于其它配置

1.  <url-pattern>
        完全匹配        以"/demo1"开始,不包含通配符*。
        目录匹配        以”/”开始 ,以*结束。
        扩展名匹配      *.xxx  不能写成 /*.xxx。
    </url-pattern>
2.  <servlet-name>
        它是对指定的servlet名称的servlet进行拦截的。
    </servlet-name>
3.  <dispatcher>
        可以取的值有  REQUEST  FORWARD  ERROR  INCLUDE    
        它的作用是:当以什么方式去访问web资源时,进行拦截操作。

        1.REQUEST 当从浏览器直接访问资源,或是重定向到某个资源时进行拦截方式配置,它也是默认值。
        2.FORWARD 它描述的是请求转发的拦截方式配置。
        3.ERROR 如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。(了解即可)
        4.INCLUDE 如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。跟FORWORD差不多。(了解即可)
    </dispatcher>

三、自动登陆

1、创建数据库与数据表

CREATE DATABASE day17;
USE day17;

CREATE TABLE USER(
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(100),
    PASSWORD VARCHAR(100)
)

INSERT INTO USER VALUES(NULL, "tom", "123");

2、自动登陆功能实现步骤

  1. 当用户登陆成功后,判断是否勾选了自动登陆,如果勾选了,就将用户名与密码持久化存储到cookie中。
  2. 做一个Filter,对需要自动登陆的资源进行拦截。

    自动登录思路图:

四、MD5加密

在mysql中可以对数据进行md5加密,是不可逆(单向)加密。   Md5(字段)   UPDATE USER SET PASSWORD=MD5(PASSWORD) WHERE id=1;

    在java中也提供了md5加密。md5工具类(MD5Utils类)示例代码如下:

package com.itheima.util;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Utils {
    /**
     * 使用md5的算法给某数据进行加密
     */
    public static String md5(String plainText) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                    plainText.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有md5这个算法!");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }
}

五、全局的编码过滤器

分析:         我们之前做的过滤操作,只能对post请求是ok的,get请求就不行了。

    怎样可以做成一个通用的,可以处理post、get所有的请求的?

    在java中怎样可以对一个方法进行功能增强法1. 继承该方法所在的类         该方法不好,因为不想要的东西我也得继承。 法2. 装饰设计模式         1). 创建一个装饰类让它与被装饰类实现同一个接口或继承同一个父类         2). 在装饰类中有一个被装饰类的引用(即:定义一个与被包装类相同对象的引用(字段))         3). 定义一个构造方法,把被包装的对象传过来         3). 重写要增强的方法(即:对于不需要改写方法,直接调用;对于需要改写方法,写自己的方法体)

问题我们获取请求参数有以下方法:         1. getParameter         2. getPrameterValues         3. getParameterMap       这三个方法都可以获取请求参数。     分析后,我们知道 getParametergetParameterValues 方法可以依赖于 getParamterMap 方法来实现。     login.jsp

    <form action="${pageContext.request.contextPath }/servlet/loginServlet" method="post">
        username:<input type="text" name="username"><br/>
        username1:<input type="text" name="username1"><br/>
        <input type="submit" value="登录">
    </form>

    LoginServlet.java

package com.itheima.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // request.setCharacterEncoding("UTF-8"); // 每一个servlet都写这句代码,不好
        String name = request.getParameterValues("username")[0];
        String name1 = request.getParameter("username1");
        System.out.println(name);   
        System.out.println(name1);
    }
    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

    web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>day17_03_Globalfilter</display-name>
  <filter>
      <filter-name>MyFilter</filter-name>
      <filter-class>com.itheima.filter.MyFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>  
  </filter-mapping>
  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>com.itheima.servlet.LoginServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/servlet/loginServlet</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

    MyFilter.java

package com.itheima.filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
// import javax.servlet.http.HttpServletResponse;
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        // HttpServletResponse resp = (HttpServletResponse) response;
        // req.setCharacterEncoding("UTF-8"); // 只能解决post的提交方式
        // resp.setContentType("text/html; charset=utf-8");
        req = new MyRequest(req); // 装饰一把(把处理乱码的动作放在装饰类代码里)
        chain.doFilter(req, response);
    }
    @Override
    public void destroy() {
    }
}
// 装饰设计模式 + 适配器
// 实现与被包装对象相同的接口
// 定义一个与被包装类相同对象的引用(字段)
// 定义一个构造方法,把被包装的对象传过来
// 对于不需要改写方法,直接调用
// 对于需要改写方法,写自己的方法体
class MyRequest extends HttpServletRequestWrapper {
    HttpServletRequest request;
    public MyRequest(HttpServletRequest request) {
        super(request); // 是因为父类没有无参数构造
        this.request = request;
    }
    // 一个一个的乱码处理,不好
//    @Override public String getParameter(String name) { 
//        name = request.getParameter(name); // 可能会出现乱码 
//        try { 
//            return new String(name.getBytes("iso-8859-1"), "UTF-8"); // 处理乱码
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace(); 
//        } 
//        return null; 
//        
//    }
    @Override
    public String getParameter(String name) {
        Map<String, String[]> map = getParameterMap();
        return map.get(name)[0];
    }
    @Override
    public String[] getParameterValues(String name) {
        Map<String, String[]> map = getParameterMap();
        return map.get(name);
    }
    private boolean flag = true;
    @Override
    public Map<String, String[]> getParameterMap() {
        // 得到原始的map集合
        Map<String, String[]> map = request.getParameterMap(); // 可能会出现乱码
        if (flag) { // 处理乱码
            // 将map集合中的String[]得到,解决每一个元素的乱码问题
            for (Map.Entry<String, String[]> m : map.entrySet()) {
                String[] values = m.getValue();
                for (int i = 0; i < values.length; i++) {
                    try {
                        values[i] = new String(values[i].getBytes("iso-8859-1"), "UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
            }
            flag = false;
        }
        return map;
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-05-31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Listener监听器(了解)
    • 1、监听机制
      • 2、Javaweb开发中常见监听器
        •   2.1、监听域对象的创建与销毁
        •   2.2、监听域对象的属性变化
        •   2.3、监听session绑定javaBean
      • 3、监听器的快速入门
        •   3.1、关于域对象的创建与销毁的演示
        •   3.2、演示Request域对象中的属性变化
        •   3.3、演示session绑定javaBean
      • 4、监听器的案例
        •   4.1、案例_定时销毁session
    • 二、Filter过滤器(重要)
      • 1、Filter快速入门
        • 2、FilterChain过滤器链
          • 3、Filter的生命周期
            • 4、FilterConfig过滤器参数
              • 5、Filter的配置文件书写格式
              • 三、自动登陆
              • 四、MD5加密
              • 五、全局的编码过滤器
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档