使用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);方法中”放行“即可。