Servlet API 提供了四个包装类:ServletRequestWrapper、ServletResponseWrapper、HttpServletRequestWrapper、HttpServletReponseWrapper。这些包装类使用的频率很小,但却很有用。当 servlet 接收到请求,service 方法被调用时,我们可以使用这些包装类来包装 servlet 容器传递过来的 request 和 response 对象以改变 request 和 response 的行为。例如,当 HTTP 请求的参数包含中文字符时,不想在每个 servlet 里面都对其转换编码,可以使用过滤器去拦截请求,然后使用 HttpServletRequestWrapper 去装饰该请求,覆盖 getParameter、getParameterValues 等方法,使这些方法返回的参数是转换过编码的。
应用示例
自定义的 HttpServletRequestWrapper:
package com.huey.hello.wrapper; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class CharsetServletRequestWrapper extends HttpServletRequestWrapper { private HttpServletRequest request; private String oldCharset; private String newCharset; public CharsetServletRequestWrapper(HttpServletRequest request, String oldCharset, String newCharset) { super(request); this.request = request; this.oldCharset = oldCharset; this.newCharset = newCharset; } @Override public String getParameter(String name) { return convertCharset(request.getParameter(name)); } @Override public String[] getParameterValues(String name) { return convertCharset(request.getParameterValues(name)); } @Override public Map<String, String[]> getParameterMap() { final Map<String, String[]> parameterMap = request.getParameterMap(); Map<String, String[]> newMap = new Map<String, String[]>() { @Override public int size() { return parameterMap.size(); } @Override public boolean isEmpty() { return parameterMap.isEmpty(); } @Override public boolean containsKey(Object key) { return parameterMap.containsKey(key); } @Override public boolean containsValue(Object value) { return parameterMap.containsValue(value); } @Override public String[] get(Object key) { return convertCharset(parameterMap.get(key)); } @Override public String[] put(String key, String[] value) { return parameterMap.put(key, value); } @Override public String[] remove(Object key) { return parameterMap.remove(key); } @Override public void putAll(Map<? extends String, ? extends String[]> m) { parameterMap.putAll(m); } @Override public void clear() { parameterMap.clear(); } @Override public Set<String> keySet() { return parameterMap.keySet(); } @Override public Collection<String[]> values() { return convertCharset(parameterMap.values()); } @Override public Set<Map.Entry<String, String[]>> entrySet() { return convertCharset(parameterMap.entrySet()); } }; return newMap; } private String convertCharset(String str) { String newStr; try { newStr = new String(str.getBytes(oldCharset), newCharset); } catch (UnsupportedEncodingException e) { newStr = str; } return newStr; } private String[] convertCharset(String[] strs) { String[] newStrs = null; if (strs != null) { newStrs = new String[strs.length]; for (int i = 0; i < newStrs.length; i++) { newStrs[i] = convertCharset(strs[i]); } } return newStrs; } private Collection<String[]> convertCharset(Collection<String[]> valueCollection) { Collection<String[]> newCollection = new ArrayList<String[]>(); for (String[] values : valueCollection) { newCollection.add(convertCharset(values)); } return newCollection; } private Set<Entry<String, String[]>> convertCharset(Set<Map.Entry<String, String[]>> entrySet) { Set<Map.Entry<String, String[]>> newSet = new HashSet<Map.Entry<String, String[]>>(); for (final Map.Entry<String, String[]> entry : entrySet) { Map.Entry<String, String[]> newEntry = new Map.Entry<String, String[]> () { @Override public String getKey() { return entry.getKey(); } @Override public String[] getValue() { return convertCharset(entry.getValue()); } @Override public String[] setValue(String[] value) { return entry.setValue(value); } }; newSet.add(newEntry); } return newSet; } }
过滤器:
package com.huey.hello.filters; 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.annotation.WebInitParam; import javax.servlet.http.HttpServletRequest; import com.huey.hello.wrapper.CharsetServletRequestWrapper; @WebFilter(filterName="charsetFilter", urlPatterns = {"/*"}, initParams = { @WebInitParam(name = "oldCharset", value = "ISO-8859-1"), @WebInitParam(name = "newCharset", value = "UTF-8"), }) public class CharsetFilter implements Filter { private String oldCharset; private String newCharset; @Override public void init(FilterConfig filterConfig) throws ServletException { oldCharset = filterConfig.getInitParameter("oldCharset"); newCharset = filterConfig.getInitParameter("newCharset"); } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(newCharset); response.setContentType("text/plain;charset=" + newCharset); HttpServletRequest httpRequest = (HttpServletRequest) request; CharsetServletRequestWrapper requestWrapper = new CharsetServletRequestWrapper(httpRequest, oldCharset, newCharset); chain.doFilter(requestWrapper, response); } }