Java EE 之 过滤器入门学习与总结(1)

简介: 使用Filter技术来配合开发会使得开发变得简单起来。简单的一个例子就表现在“乱码问题”上。不使用Filter的话,我们有可能需要为每一个网页设置字符编码集,如request.setCharacterEncoding("charsetname");response.setCharacterEncoding("charset")以及response.setContentType("text/html;charset="+targetCharset);这确实是一件繁琐而且费时费力的工作。

使用Filter技术来配合开发会使得开发变得简单起来。简单的一个例子就表现在“乱码问题”上。不使用Filter的话,我们有可能需要为每一个网页设置字符编码集,如request.setCharacterEncoding("charsetname");response.setCharacterEncoding("charset")以及response.setContentType("text/html;charset="+targetCharset);这确实是一件繁琐而且费时费力的工作。而且更重要的是这种方式违背了java的编码原则,即消除重复代码。所以要进行改进和优化的话。Filter就登上了舞台。使用Filter我们可以轻松的对乱码问题进行解决。下面就一起来看一个小小的实例吧。


什么是Filter


官方文档上对Filter是这样解释的:
这里写图片描述
大致的意思就是说,我们要自定义一个实现了javax.servlet.Filter接口的类的实例,然后重写相关的业务逻辑方法就可以完成相关的操作了。其中最主要的方法就是doFilter方法了,也是最为关键的一个方法。前两个参数也是比较容易理解,而第三个FilterChain是什么呢?
这里写图片描述。从官方的解释上我们可以发现,它是一个“链”。顾名思义就是在一个连续的操作上执行有效的对象的实例。它会按照在web.xml生命的filter-mapping的顺序来进行顺序的移动,直到最后一个filter完毕。


怎么创建一个自定义的Filter呢?


步骤如下:

  • 创建一个实现了javax.servlet.Filter接口的类,并重写内部方法。
  • 在web.xml进行声明,web.xml意义就好比android中清单文件的作用,保存着项目的全局信息。
  • 然后发布工程就可以实现调用咯

请看CharacterEncoding.java:

package web.filter.example;

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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 此类用于解决全站乱码问题
 * @author Summer
 *
 */
public class CharacterEncoding implements Filter {

    //用于获取网站初始化参数的配置信息载体
    private FilterConfig filterConfig;
    //为了防止未设置初始化参数引起的空指针错误,我们采用一个默认的字符编码集
    String defaultCharset = "UTF-8";

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest req , ServletResponse resp ,
            FilterChain chain) throws IOException, ServletException {
        //获得所需要的字符编码集
        String charset = this.filterConfig.getInitParameter("charset");
        if(charset==null){
            charset = defaultCharset;
        }

        //将request和response强制转换为http类型的
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //开始设置码表
        request.setCharacterEncoding(charset);
        response.setCharacterEncoding(charset);
        response.setContentType("text/html;charset="+charset);

        chain.doFilter(request, response);

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
            this.filterConfig = filterConfig;
    }

}

然后是在web.xml中进行相关项的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name>FilterStudy</display-name>
    <servlet>
        <description>JAX-RS Tools Generated - Do not modify</description>
        <servlet-name>JAX-RS Servlet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>ServletTest</servlet-name>
    <servlet-class>web.servlet.ServletTest</servlet-class>
  </servlet>

    <servlet-mapping>
        <servlet-name>JAX-RS Servlet</servlet-name>
        <url-pattern>/jaxrs/*</url-pattern>
    </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ServletTest</servlet-name>
    <url-pattern>/servlet/ServletTest</url-pattern>
  </servlet-mapping>

<!--没错,下面的就是配合的信息。是不是很熟悉呢?就和servlet的配置声明的原理是一样滴-->
    <filter>
        <filter-name>CharacterEncoding</filter-name>
        <filter-class>web.filter.example.CharacterEncoding</filter-class>
        <init-param>
            <param-name>charset</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncoding</filter-name>
        <!--使用*号的作用是对所有的文件适用,也可以自定义为对某一个文件有效-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

测试代码


ServletTest.java:

package web.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 ServletTest extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.getWriter().write("Summer:夏天");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}

实现的效果


这里写图片描述


总结


对于Filter技术,应用的场景很是广泛。现讨论一下本文的优缺点吧。
优点:

  • 可以方便的处理页面的乱码问题。不用一个一个的进行设置
  • 可以方便的对各种复杂的重复性强的工作进行简化
    缺点:
  • 不够灵活。

真正的解决全站乱码问题


上面的代码是关于post请求方式的乱码问题的解决的,然而这并不能够真正的解决实际开发状态下的乱码问题。比如使用get请求提交数据的时候就不能够采用那种方式进行解决。下面就来看一下使用解决get方式引起的乱码问题。
关键在于将get方式获取的parameter进行转换即可。这里我们可以采用包装模式增强request的功能。

//主要的思路是将使用get方式的编码进行转换。
class MyRequest extends HttpServletRequestWrapper{
private HttpServletRequest request = null;

public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}

@Override
public String getParameter(String name) {
String value_name = this.request.getParameter(name);
if(!request.getMethod().equalsIgnoreCase("get")){
return value_name;//即采用的是post的方式
}

if(value_name==null){
return null;
}

try{
value_name = new String(value_name.getBytes("iso859-1"),"UTF-8");
}catch(Exception e ){
throw new RuntimeException(e);
}
return super.getParameter(name);

}

然后,将这个自定义的增强过得request对象传至chain.doFilter(myRequest,response);方法中”放行“即可。

目录
相关文章
|
26天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第17天】本文详细介绍了Java编程中Map的使用,涵盖Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的并发处理和性能优化技巧,适合初学者和进阶者学习。
40 3
|
26天前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
86 43
Java学习十六—掌握注解:让编程更简单
|
5天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
11天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
12天前
|
监控 Java 数据管理
java会话跟踪和拦截器过滤器
本文介绍了Web开发中的会话跟踪技术——Cookie与Session,以及过滤器(Filter)和监听器(Listener)的概念和应用。Cookie通过在客户端记录信息来识别用户,而Session则在服务器端保存用户状态。过滤器用于拦截和处理请求及响应,监听器则监控域对象的状态变化。文章详细解释了这些技术的实现方式、应用场景和主要方法,帮助开发者更好地理解和使用这些工具。
29 1
|
1月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
31 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
17天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
55 5
|
15天前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
29 1
|
19天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
21天前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
43 3