22.【任务案例:使用Filter实现全站统一编码】

任务案例

使用Filter实现全站统一编码

任务目标

在Web开发中,经常会遇到中文乱码问题,按照前面所学知识,解决乱码的通常做法都是在Servlet程序中设置编码方式,但是,如果多个Servlet程序都需要设置编码方式,势必会书写大量重复的代码。为了解决上面的问题,可以在Filter中对获取到的请求和响应消息进行编码,从而统一全站的编码方式。

实现步骤

编写form.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body style="text-align: center;">
<center>
    <h3>用户登录</h3>
</center>
<a href="<%=request.getContextPath()%>/CharacterServlet?name=聊城职业技术学院&password=123456">单击超链接登录</a>
<form action="<%=request.getContextPath()%>/CharacterServlet" method="post">
<table border="1" width="600px" cellpadding="0" cellspacing="0" align="center">
<tr>
    <td height="30">用户名:</td>
    <td>&nbsp;<input type="text" name="name" />
    </td>
</tr>
<tr>
    <td height="30">密 &nbsp; 码:</td>
    <td>&nbsp;<input type="password" name="password" />
    </td>
</tr>
<tr>
    <td height="30" colspan="2">
    <input type="submit" value="登录" />
    &nbsp;&nbsp;&nbsp;&nbsp;
    <input type="reset" value="重置" />
    </td>
</tr>
</table>
</form>
</body>
</html>

创建CharacterServlet

创建CharacterServlet,该类用于获取用户输入的请求参数,并将参数输出到控制台

CharacterServlet.java


@WebServlet("/CharacterServlet")
public class CharacterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out=response.getWriter();
        out.println(request.getParameter("name"));
        out.println(request.getParameter("password"));
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out=response.getWriter();
        String name=request.getParameter("name");
        name=new String(name.getBytes("iso8859-1"),"utf-8");
        out.println(name);
        out.println(request.getParameter("password"));
    }
}

Post请求可以通过

request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");

来解决。
Get请求通过:

String name=request.getParameter("name");
 name=new String(name.getBytes("iso8859-1"),"utf-8");

来解决。
但是如果每次都写这样的代码有点重复,我们可以对所有的请求进行过滤。

创建过滤器CharacterFilter

编写一个CharacterFilter类,该类用于拦截用户的请求访问,实现统一全站编码的功能。只是针对请求的方式不同,解决乱码的方式也不同。其中,POST方式的请求参数存放在消息体中,可以通过setCharacterEncoding()方法进行设置;而Get方式的请求参数存放在消息头中,必须通过获取URI参数才能进行设置。如果每次单独对GET请求方式进行处理,势必会很麻烦。为此,可以通过HttpServletRequestWrapper类对HttpServletRequest类进行包装,通过重写getParameter()的方式来设置GET方式提交参数的编码。(HttpServletRequestWrapper类是HttpServletRequest的实现类,我们平时定义的HttpServletRequest request的实现类是HttpServletRequestWrapper,在这里我们定义一个类CharacterRequest继承HttpServletRequestWrapper这个实现类,在这个类中重写getParameter方法,然后用CharacterRequest这个类来创建request对象)

CharacterFilter.java
@WebFilter("/*")
public class CharacterFilter implements Filter {
    public void destroy() {
    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //拦截所有的请求 解决全站中文乱码
        //指定 request 和 response 的编码
        request.setCharacterEncoding("utf-8");// 只对消息体有效
        response.setContentType("text/html;charset=utf-8");
        //对request进行包装
        CharacterRequest characterRequest = new CharacterRequest(request);
        chain.doFilter(characterRequest,response);

    }
    public void init(FilterConfig config) throws ServletException {

    }
    // 继承 默认包装类HttpServletRequestWrapper

    class CharacterRequest extends HttpServletRequestWrapper {
        private HttpServletRequest request;

        public CharacterRequest(HttpServletRequest request) {
            super(request);
            this.request = request;
        }
        //子类继承父类一定会覆写一些方法,此处用于重写getParamter()方法
        public String getParameter(String name) {
            //调用被包装对象的getParameter()方法,获得请求参数
            String value = super.getParameter(name);
            //调用父类的getParameter方法,得到value值。这里必须调用父类的getParameter,因为本类要重写父类的方法,本类的这个方法还没有父类的那个功能。
            if (value == null)
                return null;
            //判断请求方式
            String method = super.getMethod();
            if ("get".equalsIgnoreCase(method)) {
                try {
                    value = new String(value.getBytes("iso-8859-1"), "utf-8");

                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            }            //解决乱码后返回结果
            return value;
        }
    }
    }

在测试前把 CharacterServlet.java doGet方法中 name=new String(name.getBytes(“iso8859-1”),“utf-8”); 这行代码去掉。运行
http://localhost:8080/form.jsp 单击“单击超链接登录”后,发现也能正常显示中文。

猜你喜欢

转载自blog.csdn.net/lcachang/article/details/82928404