spring mvc字符编码过滤器 CharacterEncodingFilter ,添加例外url
前言spring 4.3.4.RELEASECharacterEncodingFilter : Spring MVC 提供的字符集过滤器,用于处理项目中的乱码问题项目比较老,大部分url使用的是GBK编码,少量url使用UTF-8编码。需要对 CharacterEncodingFilter 设置例外。即,少量url不要进行 CharacterEncodingFilter 过滤。Cha...
前言
- spring 4.3.4.RELEASE
- CharacterEncodingFilter : Spring MVC 提供的字符集过滤器,用于处理项目中的乱码问题
- 项目比较老,大部分url使用的是GBK编码,少量url使用UTF-8编码。
- 需要对 CharacterEncodingFilter 设置例外。即,少量url不要进行 CharacterEncodingFilter 过滤。
CharacterEncodingFilter设置
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
url-pattern很霸气,过滤所有。
forceEncoding更霸气,强制编码格式为GBK。
为什么这么设置不说了(很显然这样让charset为UTF-8的JS很受伤),就说怎么办吧。
受伤的JS
<script type="text/javascript" language="javascript" src="../codebase/laydate/laydate.js" charset="UTF-8"></script>
CharacterEncodingFilter添加例外
方法1(推荐):filter-mapping添加例外
嗯~,filter-mapping添加例外是个好办法。
<!-- 解决编码问题过滤器 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- CharacterEncodingFilter过滤器添加例外 -->
<filter>
<filter-name>characterEncodingFilter_utf8</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter_utf8</filter-name>
<url-pattern>/codebase/laydate/laydate.js</url-pattern>
</filter-mapping>
方法2:告知CharacterEncodingFilter不用再处理了
根据CharacterEncodingFilter代码显示,在request的Attribute中,增加名为filter-name.FILTERED
,值为TRUE
的Attribute时,会跳过过滤器。
本文中需要增加名为characterEncodingFilter.FILTERED
的Attribute。
增加名为characterEncodingFilter.FILTERED
的Attribute的方法则是:在characterEncodingFilter执行前,再增加一个Filter。该Filter向request增加名为characterEncodingFilter.FILTERED
的Attribute。(该Filter需要自己写,此处暂不提供)
CharacterEncodingFilter的相关代码如下:
CharacterEncodingFilter的相关代码:
public class CharacterEncodingFilter extends OncePerRequestFilter {
...
}
OncePerRequestFilter的相关代码:
public abstract class OncePerRequestFilter extends GenericFilterBean {
/**
* Suffix that gets appended to the filter name for the
* "already filtered" request attribute.
* @see #getAlreadyFilteredAttributeName
*/
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
/**
* This {@code doFilter} implementation stores a request attribute for
* "already filtered", proceeding without filtering again if the
* attribute is already there.
* @see #getAlreadyFilteredAttributeName
* @see #shouldNotFilter
* @see #doFilterInternal
*/
@Override
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
throw new ServletException("OncePerRequestFilter just supports HTTP requests");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();
boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;
if (hasAlreadyFilteredAttribute || skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) {
// Proceed without invoking this filter...
filterChain.doFilter(request, response);
}
else {
// Do invoke this filter...
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
try {
doFilterInternal(httpRequest, httpResponse, filterChain);
}
finally {
// Remove the "already filtered" request attribute for this request.
request.removeAttribute(alreadyFilteredAttributeName);
}
}
}
/**
* Return the name of the request attribute that identifies that a request
* is already filtered.
* <p>The default implementation takes the configured name of the concrete filter
* instance and appends ".FILTERED". If the filter is not fully initialized,
* it falls back to its class name.
* @see #getFilterName
* @see #ALREADY_FILTERED_SUFFIX
*/
protected String getAlreadyFilteredAttributeName() {
String name = getFilterName();
if (name == null) {
name = getClass().getName();
}
return name + ALREADY_FILTERED_SUFFIX;
}
...
}
GenericFilterBean的相关代码:
public abstract class GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,
EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean {
/**
* Make the name of this filter available to subclasses.
* Analogous to GenericServlet's {@code getServletName()}.
* <p>Takes the FilterConfig's filter name by default.
* If initialized as bean in a Spring application context,
* it falls back to the bean name as defined in the bean factory.
* @return the filter name, or {@code null} if none available
* @see javax.servlet.GenericServlet#getServletName()
* @see javax.servlet.FilterConfig#getFilterName()
* @see #setBeanName
*/
@Nullable
protected String getFilterName() {
return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);
}
...
}

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)