Servlet全站式解决中文乱码

Servlet全站式解决中文乱码

1. java Servlet Filter(过滤器)
Filter是Servlet的过滤器,是Servlet 2.3规范中新增加的一个功能,主要用于完成一些通用的操作,如编码的过滤、判断用户的登录状态等。
Filter 被称为过滤器,其主要作用是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊功能.
在这里插入图片描述
注意:过滤器是部署在服务器上的。
当用户通过浏览器访问服务器中的目标资源时,首先会被 Filter 拦截,在 Filter 中进行预处理操作,然后再将请求转发给目标资源。当服务器接收到这个请求后会对其进行响应,在服务器处理响应的过程中,也需要将响应结果经过滤器处理后,才发送给客户端。
本质上,Filter 过滤器就是一个实现了 javax.servlet.Filter 接口的类,在 javax.servlet.Filter 接口中定义了三个方法
在这里插入图片描述
下面通过案例演示 Filter 程序如何对 Servlet 程序的调用过程进行拦截。
1.1 创建一个Servlet,充当目标资源

package qing;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("测试---TestServlet---");
        PrintWriter out=resp.getWriter();
        out.write("Hello---TestServlet---");
        out.close();
    }
}

1.2 创建过滤器
1.2.1 创建新类,实现javax.servlet.Filter接口
1.2.2 重写init、doFilter、destroy方法
1.2.3 在doFilter中编写具体过滤动作
1.2.4Web.xml配置过滤器

package qing;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init---方法执行---");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("doFilter---过滤器方法执行---");
        chain.doFilter(request,response);
    }
    
    @Override
    public void destroy() {
        System.out.println("destroy---销毁方法执行---");
    }
}

Web.xml

<filter>
    <filter-name>myfilter</filter-name>
    <filter-class>qing.MyFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>myfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>qing.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/test</url-pattern>
  </servlet-mapping>

测试:http://localhost:8080/test
在这里插入图片描述
注意:过滤器可以直接对用户的请求作出响应,而不需要Servlet/目标资源的处理。

2.Java Servlet Filter的两种映射方式
创建 Filter 后,在 web.xml 中的对应配置信息就是 Filter 映射。Filter 的映射方式可分为两种。
2.1 使用通配符拦截用户的所有请求(–所有请求)

<filter>
    <filter-name>myfilter</filter-name>
    <filter-class>qing.MyFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>myfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

2.2 拦截不同方式的访问请求
在 web.xml 文件中,每一个 元素都可以配置一个 Filter 所负责拦截的资源。在 元素中有一个特殊的子元素 ,该元素用于指定过滤器所拦截的资源被 Servlet 容器调用的方式。 元素的值共有四个。

例如:

<filter>
  	<filter-name>myfilter</filter-name>
  	<filter-class>qing2.MyFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>myfilter</filter-name>
  	<url-pattern>/*</url-pattern>
  	<dispatcher>FORWARD</dispatcher>
  </filter-mapping> 

例如:
当FORWARD表示通过RequestDispatcher 的 forward() 方法访问资源的时候才会使用当前配置的过滤器。当我们发送一个请求的时候,没有使用RequestDispatcher 的 forward() 方法时,是不会使用当前配置的过滤器。

2.3 拦截不同访问路径的访问请求
通过设置 元素中的指定不同的访问路径,来确定哪些资源可以访问当前过滤器,哪些资源不可以访问当前过滤器。

<filter>
  	<filter-name>test</filter-name>
  	<filter-class>qing3.TestFilter</filter-class>
  </filter>
   <filter-mapping>
  	<filter-name>test</filter-name>
  	<url-pattern>/test</url-pattern>
  </filter-mapping> 
  
  <filter>
  	<filter-name>other</filter-name>
  	<filter-class>qing3.OtherFilter</filter-class>
  </filter>
   <filter-mapping>
  	<filter-name>other</filter-name>
  	<url-pattern>/other</url-pattern>
  </filter-mapping> 
  
  <servlet>
  	<servlet-name>test</servlet-name>
  	<servlet-class>qing3.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>test</servlet-name>
  	<url-pattern>/test</url-pattern>
  </servlet-mapping>
  
  <servlet>
  	<servlet-name>other</servlet-name>
  	<servlet-class>qing3.OtherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>other</servlet-name>
  	<url-pattern>/other</url-pattern>
  </servlet-mapping>

http://localhost:8080/test
在这里插入图片描述

http://localhost:8080/other
在这里插入图片描述

3.FilterChain(过滤器链)详解
在一个 Web 应用程序中可以注册多个 Filter 程序,每个 Filter 程序都可以针对某一个 URL 进行拦截。如果多个 Filter 程序都对同一个 URL 进行拦截,那么这些 Filter 就会组成一个Filter 链(也称过滤器链)。
Filter 链用 FilterChain 对象表示,FilterChain 对象中有一个 doFilter() 方法,该方法的作用是让 Filter 链上的当前过滤器放行,使请求进入下一个 Filter。
在这里插入图片描述
在上图中,当浏览器访问 Web 服务器中的资源时,需要经过两个过滤器 Filter1 和 Filter2。首先 Filter1 会对这个请求进行拦截,在 Filter1 中处理完请求后,通过Filter 链 FilterChain 对象调用 doFilter() 方法将请求传递给 Filter2,Filter2 处理用户请求后同样FilterChain 对象调用 doFilter() 方法,最终将请求发送给目标资源。当 Web 服务器对这个请求做出响应时,也会被过滤器拦截,但这个拦截顺序与之前相反,最终将响应结果发送给客户端浏览器。

例如:

<filter>
    <filter-name>basefilter</filter-name>
    <filter-class>qing3.BaseFilter</filter-class>
  </filter>
  <filter>
    <filter-name>testfilter</filter-name>
    <filter-class>qing3.TestFilter</filter-class>
  </filter>
  <filter>
    <filter-name>otherfilter</filter-name>
    <filter-class>qing3.OtherFilter</filter-class>
  </filter>


  <filter-mapping>
    <filter-name>basefilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>testfilter</filter-name>
    <url-pattern>/test</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>otherfilter</filter-name>
    <url-pattern>/other</url-pattern>
  </filter-mapping>

  <servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>qing3.TestServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>other</servlet-name>
    <servlet-class>qing3.OtherServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/test</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>other</servlet-name>
    <url-pattern>/other</url-pattern>
  </servlet-mapping>

http://localhost:8080/test
在这里插入图片描述
过滤器链中的每一个过滤器在执行的时候,与在web.xml文件中配置的顺序一致。
4.FilterConfig接口及其使用方法详解
FilterConfig接口与我们前面学习的ServletConfig接口相似。
FilterConfig 是 Servlet API 提供的一个用于获取 Filter 程序在 web.xml 文件中的配置信息的接口,该接口封装了 Filter 程序在 web.xml 中的所有注册信息,并且提供了一系列获取这些配置信息的方法。
在这里插入图片描述
测试FilterConfig的接口方法

package qing4;
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class TestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("TestFilter---init方法执行!!!");
        //测试FilterConfig接口对象常用方法
        String name=filterConfig.getFilterName();//getFilterName--web.xml文件中Filter所设置的名称
        System.out.println("name==="+name);
        String myname=filterConfig.getInitParameter("name");//得到web.xml文件中配置的指定的初始化参数值
        System.out.println("name==="+myname);
        Enumeration<String> initname=filterConfig.getInitParameterNames();//得到web.xml文件中配置的初始化参数的名称
        //遍历所有初始化参数名,得到对应值并打印
        while (initname.hasMoreElements()){
            String paramname=initname.nextElement();
            String value=filterConfig.getInitParameter(paramname);
            System.out.println("初始化信息=="+paramname+"=="+value);
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("TestFilter---doFilter方法执行!!!");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        System.out.println("TestFilter---destroy方法执行!!!");
    }
}
package qing4;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       System.out.println("TestServlet---");
       PrintWriter out=resp.getWriter();
       out.write("<h1>Hello TestServlet</h1>");
       out.close();
    }
}

web.xml 配置:

<filter>
    <filter-name>testfilter</filter-name>
    <filter-class>qing4.TestFilter</filter-class>
    <init-param>
      <param-name>myname</param-name>
      <param-value>张三</param-value>
    </init-param>
    <init-param>
      <param-name>myage</param-name>
      <param-value>23</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>testfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>qing4.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/test</url-pattern>
  </servlet-mapping>

启动服务器就能看到执行结果
http://localhost:8080/test
在这里插入图片描述

5.Servlet Filter实现全站统一编码,解决中文乱码问题
注意:tomcat8以后默认编码格式是utf-8;7之前的都是iso8859-1

package qing5;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * 字符编码过滤器 [ 全站统一编码,解决中文乱码问题 ]
 */
public class EncodingFilter implements Filter {
    private String encoding = "utf-8";

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //转换ServletRequest为HttpServletRequest
        HttpServletRequest req = (HttpServletRequest) request;
        //转换ServletResponse为HttpServletResponse
        HttpServletResponse resp = (HttpServletResponse) response;
        //设置请求和响应的字符编码
        req.setCharacterEncoding(this.encoding);
        resp.setCharacterEncoding(this.encoding);
        resp.setContentType("text/html;charset=" + this.encoding);
        //解决get请求中文乱码
        //重写getParameter方法,对request进行包装
        CharacterRequest characterRequest = new CharacterRequest(req, this.encoding);
        chain.doFilter(characterRequest, resp);
    }

    @Override
    public void destroy() {
    }
}
package qing5;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.UnsupportedEncodingException;
/**
 * 对 request 进行包装
 */
public class CharacterRequest extends HttpServletRequestWrapper {
    private HttpServletRequest request;
    private String encoding="utf-8";
    public CharacterRequest(HttpServletRequest request,String encoding) {
        super(request);
        this.request=request;
        this.encoding=encoding;
    }

    @Override
    public String getParameter(String name) {
        String value = request.getParameter(name);
        if (value == null) {
            return null;
        }
        //得到请求的提交方式
        String method = request.getMethod();
        if ("get".equalsIgnoreCase(method)) {
            try {
                //tomcat8以后默认编码格式是utf-8 7之前的都是iso8859-1
                value = new String(value.getBytes(this.encoding), this.encoding);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
        return value;
    }
}
package qing5;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("TestServlet---执行!!!");
        String name = req.getParameter("name");
        System.out.println("name==" + name);
        PrintWriter out = resp.getWriter();
        out.write("Hello TestServlet==name==" + name);
        out.close();
    }
}

Web.xml

<filter>
  <filter-name>encodingfilter</filter-name>
  <filter-class>qing5.EncodingFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>utf-8</param-value>
  </init-param>
</filter>
  <filter-mapping>
    <filter-name>encodingfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <servlet>
    <servlet-name>test</servlet-name>
    <servlet-class>qing5.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>test</servlet-name>
    <url-pattern>/test</url-pattern>
  </servlet-mapping>

测试
http://localhost:8080/test?name=%E5%B0%8F%E6%9D%8E%E5%90%8C%E5%AD%A6
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值