Filter全局編碼過(guò)濾器
這篇來(lái)做一個(gè)Filter在全局編碼過(guò)濾器練習(xí),這篇新建一個(gè)web項(xiàng)目來(lái)做練習(xí)腰湾。
web項(xiàng)目創(chuàng)建
先創(chuàng)建一個(gè)叫GlobalFilter的web動(dòng)態(tài)項(xiàng)目棉浸,把前面文章出現(xiàn)過(guò)的login.jsp復(fù)制過(guò)來(lái)凝危,改成如下代碼昆烁。
<%@?page?language="java"?contentType="text/html; charset=UTF-8"
? ?pageEncoding="UTF-8"%>
<!DOCTYPE?html?PUBLIC?"-//W3C//DTD HTML 4.01 Transitional//EN"?"https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta?http-equiv="Content-Type"?content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form?action="${pageContext.request.contextPath}/web/loginServlet"?method="post">
用戶名:<input?type="text"?name="username"?/><br/>
<input?type="submit"?value="登錄"?/><br/>
</form>
</body>
</html>
因?yàn)槲覀冞@里做全局編碼的練習(xí)多矮,到時(shí)候登錄頁(yè)面輸入用戶名蟹略,我們會(huì)采用中文字符輸入登失。
Servlet創(chuàng)建
因?yàn)檫@里我們是模擬全局,實(shí)際中應(yīng)該有許多servlet和許多前端頁(yè)面挖炬,例如注冊(cè)揽浙,登錄,首頁(yè)搜索等意敛。我們就來(lái)創(chuàng)建一個(gè)servlet來(lái)模擬下就好馅巷。創(chuàng)建一個(gè)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);
}
}
以前钓猬,我們是通過(guò)這個(gè)紅圈代碼來(lái)設(shè)置編碼,這樣拿到中文的username就不會(huì)是亂碼撩独。
現(xiàn)實(shí)開(kāi)發(fā)中有很多個(gè)servlet敞曹,如果都這樣寫這行代碼來(lái)設(shè)置編碼,這行代碼就冗余综膀,我們可以把這行代碼放到Filter過(guò)濾器中去澳迫。
Filter類創(chuàng)建
創(chuàng)建一個(gè)MyFilter.java?實(shí)現(xiàn)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?{
// 轉(zhuǎn)換對(duì)象
HttpServletRequest?req = (HttpServletRequest) request;
// 設(shè)置編碼
req.setCharacterEncoding("UTF-8");
// 放行
chain.doFilter(request, response);
}
public void?init(FilterConfig?fConfig) throws?ServletException?{
// TODO Auto-generated method stub
}
}
web.xml內(nèi)容如下
<?xml?version="1.0"?encoding="UTF-8"?>
<web-app?xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"?xmlns="https://java.sun.com/xml/ns/javaee"?xsi:schemaLocation="https://java.sun.com/xml/ns/javaee?https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"?id="WebApp_ID"?version="3.0">
?<display-name>GlobalFilter</display-name>
?<welcome-file-list>
? ?<welcome-file>index.html</welcome-file>
? ?<welcome-file>index.htm</welcome-file>
? ?<welcome-file>index.jsp</welcome-file>
? ?<welcome-file>default.html</welcome-file>
? ?<welcome-file>default.htm</welcome-file>
? ?<welcome-file>default.jsp</welcome-file>
?</welcome-file-list>
?<filter>
?<filter-name>MyFilter</filter-name>
?<filter-class>com.kaigejava.web.filter.MyFilter</filter-class>
?</filter>
?<filter-mapping>
?<filter-name>MyFilter</filter-name>
?<url-pattern>/*</url-pattern>
?</filter-mapping>
?<servlet>
? ?<servlet-name>LoginServlet</servlet-name>
? ?<servlet-class>com.anthony.web.servlet.LoginServlet</servlet-class>
?</servlet>
?<servlet-mapping>
? ?<servlet-name>LoginServlet</servlet-name>
? ?<url-pattern>/web/loginServlet</url-pattern>
?</servlet-mapping>
</web-app>
部署測(cè)試
現(xiàn)在部署到tomcat然后測(cè)試以下橄登,前臺(tái)頁(yè)面用戶名輸入框輸入“張三”看看。
在Eclipse控制臺(tái)可以看到“張三”打印出來(lái)不亂碼讥此,說(shuō)明我們Filter中編碼設(shè)置起效果了拢锹。
Get方式提交表單問(wèn)題
在login.jsp中我們表單提交是post方法,如果改成get呢暂论,會(huì)出問(wèn)題面褐。
重新部署,再來(lái)測(cè)試下
如果是get方式傳過(guò)來(lái)取胎,中文就很有可能顯示亂碼展哭。這個(gè)問(wèn)題怎么解決了湃窍,有兩種方式解決,第一種不要寫get匪傍,就是post表單提交∧校現(xiàn)在我們來(lái)看看第二種方式如何解決。在MyFilter類中寫一個(gè)通用的方法役衡,既能解決get也能解決post的編碼問(wèn)題茵休。
裝飾模式解決get和post編碼問(wèn)題
我們?cè)贛yFilter.java代碼中添加一個(gè)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?{
//?轉(zhuǎn)換對(duì)象
HttpServletRequest?req?= (HttpServletRequest)?request;
//?設(shè)置編碼
//req.setCharacterEncoding("UTF-8");
//?放行
req?=?new?MyRequest(req);
//?req這個(gè)對(duì)象是包裝之后的對(duì)象,把這個(gè)傳到servlet中的request
chain.doFilter(req,?response);
}
public?void?init(FilterConfig?fConfig)?throws?ServletException?{
//?TODO?Auto-generated method stub
}
}
/**
* ?繼承HttpServlet的包裝類棵介,實(shí)現(xiàn)裝飾模式钉鸯,解決get和post亂碼問(wèn)題
*
*/
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提交邮辽,測(cè)試可以解決get和post亂碼唠雕。
重寫其他方法
在request對(duì)象中,還有其他方法吨述,例如getParameters()?和getParameterMap()岩睁,這里我們把這兩個(gè)方法都重寫一下。
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?{
//?轉(zhuǎn)換對(duì)象
HttpServletRequest?req?= (HttpServletRequest)?request;
//?放行
req?=?new?MyRequest(req);
//?req變成自己包裝的對(duì)象揣云,然后傳遞給servlet中捕儒,servlet中的request就是調(diào)用包裝過(guò)的req
chain.doFilter(req,?response);
}
public?void?init(FilterConfig?fConfig)?throws?ServletException?{
}
}
/**
*?繼承HttpServlet的包裝類,實(shí)現(xiàn)裝飾模式灵再,解決get和post亂碼問(wèn)題
*
*/
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
Map?map?=?request.getParameterMap();?//?亂碼
if?(flag) {
for?(Map.Entry?m?:?map.entrySet()) {
String[]?values?=?m.getValue();
for?(int?i?= 0;?i?<?values.length;?i++) {
try?{
values[i] =?new?String(values[i].getBytes("iso-8859-1"),?"UTF-8");
}?catch?(UnsupportedEncodingException?e) {
e.printStackTrace();
}
}
}
flag?=?false;
}
return?map;
}
}
由于最后三個(gè)方法肋层,我們倒數(shù)第二個(gè)第三個(gè)都是調(diào)用倒數(shù)第一個(gè),為了解決第一個(gè)調(diào)用亂碼好了翎迁,第二個(gè)再次調(diào)用又變成亂碼栋猖,所以這里在第三個(gè)方法添加了一個(gè)flag。