Filter全局编码过滤器
这篇来做一个Filter在全局编码过滤器练习,这篇新建一个web项目来做练习。
web项目创建
先创建一个叫GlobalFilter的web动态项目,把前面文章出现过的login.jsp复制过来,改成如下代码。
pageEncoding="UTF-8"%>
Insert title here
用户名:
因为我们这里做全局编码的练习,到时候登录页面输入用户名,我们会采用中文字符输入。
Servlet创建
因为这里我们是模拟全局,实际中应该有许多servlet和许多前端页面,例如注册,登录,首页搜索等。我们就来创建一个servlet来模拟下就好。创建一个LoginServlet.java。 url-pattern是/web/loginServlet。
package com.kaigejava.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//request.setCharacterEncoding("UTF-8");
String name = request.getParameter("username");
System.out.println(name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
以前,我们是通过这个红圈代码来设置编码,这样拿到中文的username就不会是乱码。
现实开发中有很多个servlet,如果都这样写这行代码来设置编码,这行代码就冗余,我们可以把这行代码放到Filter过滤器中去。
Filter类创建
创建一个MyFilter.java 实现Filter接口,代码如下。
package com.kaigejava.web.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;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
public class MyFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 转换对象
HttpServletRequest req = (HttpServletRequest) request;
// 设置编码
req.setCharacterEncoding("UTF-8");
// 放行
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
web.xml内容如下
GlobalFilter
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
MyFilter
com.kaigejava.web.filter.MyFilter
MyFilter
/*
LoginServlet
com.anthony.web.servlet.LoginServlet
LoginServlet
/web/loginServlet
部署测试
现在部署到tomcat然后测试以下,前台页面用户名输入框输入“张三”看看。
在Eclipse控制台可以看到“张三”打印出来不乱码,说明我们Filter中编码设置起效果了。
Get方式提交表单问题
在login.jsp中我们表单提交是post方法,如果改成get呢,会出问题。
重新部署,再来测试下
如果是get方式传过来,中文就很有可能显示乱码。这个问题怎么解决了,有两种方式解决,第一种不要写get,就是post表单提交。现在我们来看看第二种方式如何解决。在MyFilter类中写一个通用的方法,既能解决get也能解决post的编码问题。
装饰模式解决get和post编码问题
我们在MyFilter.java代码中添加一个MyRequest class,里面写我们的装饰器代码,只重写了getParameter(String text)方法。
package com.kaigejava.web.filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
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;
public class MyFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 转换对象
HttpServletRequest req = (HttpServletRequest) request;
// 设置编码
//req.setCharacterEncoding("UTF-8");
// 放行
req = new MyRequest(req);
// req这个对象是包装之后的对象,把这个传到servlet中的request
chain.doFilter(req, response);
}
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
/**
* 继承HttpServlet的包装类,实现装饰模式,解决get和post乱码问题
*
*/
class MyRequest extends HttpServletRequestWrapper{
HttpServletRequest request;
public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
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;
}
}
部署到tomcat,login.jsp表单还是get提交,测试可以解决get和post乱码。
重写其他方法
在request对象中,还有其他方法,例如getParameters() 和getParameterMap(),这里我们把这两个方法都重写一下。
package com.kaigejava.web.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;
public class MyFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 转换对象
HttpServletRequest req = (HttpServletRequest) request;
// 放行
req = new MyRequest(req);
// req变成自己包装的对象,然后传递给servlet中,servlet中的request就是调用包装过的req
chain.doFilter(req, response);
}
public void init(FilterConfig fConfig) throws ServletException {
}
}
/**
* 继承HttpServlet的包装类,实现装饰模式,解决get和post乱码问题
*
*/
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 map = getParameterMap();
return map.get(name)[0];
}
@Override
public String[] getParameterValues(String name) {
Map map = getParameterMap();
return map.get(name);
}
public boolean flag = true;
@Override
public Map getParameterMap() {
Map map = request.getParameterMap(); // 乱码
if (flag) {
for (Map.Entry m : map.entrySet()) {
String[] values = m.getValue();
for (int i = 0; i try {
values[i] = new String(values[i].getBytes("iso-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
flag = false;
}
return map;
}
}
由于最后三个方法,我们倒数第二个第三个都是调用倒数第一个,为了解决第一个调用乱码好了,第二个再次调用又变成乱码,所以这里在第三个方法添加了一个flag。