首页 > 其他分享 >SpringMVC中的字符编码问题

SpringMVC中的字符编码问题

时间:2023-04-15 17:44:20浏览次数:46  
标签:编码 HTTP encoding SpringMVC 配置 字符 properties

字符编码问题

目录

一、背景

最近项目中在使用feign接口调用中产生了乱码问题,所以总结下这里产生乱码的原因。

如下所示:

Feign远程调用过程中出现中文乱码问题

正确的文件名称应该是:

二、排查思路

2.1、查看idea默认编码方式

发现都是UTF-8编码方式,继续向下来进行排查。

2.2、查看接口代码

2.3、查看linux编码

发现也是中文,所以可能存在问题的地方是第二个。

三、解决思路

因为从idea中编码中没有找到问题,所以只有在接口中存在问题,尝试来进行修复。

3.1、修改远程调用编码

指定响应的编码方式

如下所示:

四、SpringMVC对字符编码的配置

4.1、字符编码自动配置类HttpEncodingAutoConfiguration

直接来看自动配置类对字符编码的配置。org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration

源码如下所示:

@Configuration(proxyBeanMethods = false)
// 配置server中的配置
@EnableConfigurationProperties(ServerProperties.class)
// servlet环境
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
// 字符编码类
@ConditionalOnClass(CharacterEncodingFilter.class)
// 字符编码的配置是在这里来进行配置的。默认也是开启的
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

	private final Encoding properties;

	public HttpEncodingAutoConfiguration(ServerProperties properties) {
		this.properties = properties.getServlet().getEncoding();
	}
    
    // 配置过滤器
	@Bean
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
         // 设置字符编码
		filter.setEncoding(this.properties.getCharset().name());
         // 强制request编码
		filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
         // 强制response编码
		filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
		return filter;
	}

	@Bean
	public LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
		return new LocaleCharsetMappingsCustomizer(this.properties);
	}

	static class LocaleCharsetMappingsCustomizer
			implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {

		private final Encoding properties;

		LocaleCharsetMappingsCustomizer(Encoding properties) {
			this.properties = properties;
		}
		// 配置映射路径
		@Override
		public void customize(ConfigurableServletWebServerFactory factory) {
			if (this.properties.getMapping() != null) {
				factory.setLocaleCharsetMappings(this.properties.getMapping());
			}
		}

		@Override
		public int getOrder() {
			return 0;
		}

	}

}

通过上面的代码,可以看出springmvc所有request的配置是通过

spring.http.encoding

来进行配置的。所以就有必要来对这个配置类的属性来做了解。

4.2、配置类中属性说明

直接参考:org.springframework.boot.web.servlet.server.Encoding

public class Encoding {

	/**
	 * Default HTTP encoding for Servlet applications.
	 */
     // 采用的模仿编码方式
	public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

	/**
	 * Charset of HTTP requests and responses. Added to the "Content-Type" header if not
	 * set explicitly.
	 */
    // 针对request和response默认设置的字符编码
	private Charset charset = DEFAULT_CHARSET;

	/**
	 * Whether to force the encoding to the configured charset on HTTP requests and
	 * responses.
	 */
    // 是否强制对HTTP请求和响应上配置的字符集进行编码
	private Boolean force;

	/**
	 * Whether to force the encoding to the configured charset on HTTP requests. Defaults
	 * to true when "force" has not been specified.
	 */
    // 是否强制对HTTP请求上配置的字符集进行编码。未指定“force”时默认为true
	private Boolean forceRequest;

	/**
	 * Whether to force the encoding to the configured charset on HTTP responses.
	 */
    // 是否强制对HTTP响应上配置的字符集进行编码
	private Boolean forceResponse;

	/**
	 * Locale in which to encode mapping.
	 */
    // 要在其中编码映射的区域设置
	private Map<Locale, Charset> mapping;
   
    // ......
}

即配置文件如下所示:

spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true 

参考官方文档中的配置

https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

4.3、过滤器中设置源码

然后进入到org.springframework.web.filter.CharacterEncodingFilter#doFilterInternal方法来

protected void doFilterInternal(
  HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
  throws ServletException, IOException {
  
  // 获取得到默认编码方式。默认为UTF-8
  String encoding = getEncoding();
  if (encoding != null) {
    // 两个设置条件:1、forceRequestEncoding是否为true;2、利用request获取得到默认编码
    if (isForceRequestEncoding() || request.getCharacterEncoding() == null) {
      request.setCharacterEncoding(encoding);
    }
    // 是否设置强制响应编码。默认值是false
    // 默认为false
    if (isForceResponseEncoding()) {
      response.setCharacterEncoding(encoding);
    }
  }
  filterChain.doFilter(request, response);
}

终于在这里找到了原因。原因就是这里的响应没有设置为中文编码。

五、Tomcat编码设置

另外web窗口 tomcat可以配置

# Character encoding to use to decode the URI.
server.tomcat.uri-encoding=UTF-8 

六、总结

1、排查问题的时候,就考虑到多种情况的发生,并逐一进行验证。

2、最终的字符编码配置如下所示:

spring:
  http:
    encoding:
      charset: UTF-8
      force: true

标签:编码,HTTP,encoding,SpringMVC,配置,字符,properties
From: https://www.cnblogs.com/likeguang/p/17321527.html

相关文章

  • shell命令--字符串截取
    shell截取字符串通常有两种方式:截取指定长度的字符串和截取指定模式的字符串。1.截取指定长度的字符串这种方式除了需要指定起始位置还需要指定截取长度。按起始位置可以分为从左边开始或者从右边开始。a.从左边开始截取${string:start:length}其中,string是要截取的字符......
  • Java 把列表元素拼接字符串
    摘要:使用JavaCollectors.joining方法把列表中的所有元素通过指定的分隔符连接字符串。目录综述使用For循环StringUtils.join函数Collectors.joining(Function)函数GuavaJoinerjoin函数String.join函数结束语综述  在项目开发中,经常遇到的一个问题就是要把得到的一个......
  • 删除无效的括号(广度优先搜索、字符串)、计算右侧小于当前元素的个数(树状数组、线段
    删除无效的括号(广度优先搜索、字符串)给你一个由若干括号和字母组成的字符串s,删除最小数量的无效括号,使得输入的字符串有效。返回所有可能的结果。答案可以按任意顺序返回。示例1:输入:s="()())()"输出:["(())()","()()()"]示例2:输入:s="(a)())()"输出:["(a())()","(......
  • 25-组合逻辑集成电路-编码器
    编码器组合逻辑集成电路(MSI)组合电路使用小规模电路设计,描述清楚,用小规模的集成电路实现;小规模集成电路比较灵活常用的部件(译码器\编码器\比较器\选择器)都是事先做好,直接进行使用1.编码器概念及分类1.1编码器的概念编码器:使用一组二进制数表示一个数值或者是符号。例......
  • Python字符串处理
    Python之正则表达式正则表达式重在处理字符串规则普通字符importre#普通字符result=re.findall("p","python")print(result,type(result))result=re.findall("o","Ilovepython")print(result,type(result))预定义字符模式描述\d匹配所有数字0......
  • m基于matlab的图像方块编码仿真,输出编码后PSNR图像质量指标
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要BTC编码又称方块编码,是一种有效,快速,简单的有损灰度图像数字压缩技术,具有性能高,信道容错力高等特点,在实时图像传输方面具有很高的应用价值,由美国普渡大学的Mitchell和Delphi教授提出.使用Mat-lab实现BTC编码......
  • 字符串哈希
    算法简介字符串哈希是将字符串映射为数字的算法,它通常用来解决快速判断两个字符串是否相等的问题。时间复杂度\(O(n+m)\)实现原理1.构造原理字符串哈希运用了进制的思想,将字符串变为p进制的数字。如:""可以映射为:\((X_1*P^{n-1}+X_2*P^{n-2}+\cdots+X^{n-1......
  • m基于matlab的图像方块编码仿真,输出编码后PSNR图像质量指标
    1.算法仿真效果matlab2022a仿真结果如下:   2.算法涉及理论知识概要       BTC编码又称方块编码,是一种有效,快速,简单的有损灰度图像数字压缩技术,具有性能高,信道容错力高等特点,在实时图像传输方面具有很高的应用价值,由美国普渡大学的Mitchell和Delphi教授提......
  • 97. 交错字符串
    classSolution{public:boolf[110][110];boolisInterleave(strings1,strings2,strings3){intn=s1.size(),m=s2.size();if(n+m!=s3.size())returnfalse;s1=''+s1;s2=''+s2;s3=�......
  • python 正则处理字符串,使用函数
    """在正则截取的字符子串基础上,处理字符串Python的re模块提供了re.sub用于替换字符串中的匹配项。语法:re.sub(pattern,repl,string,count=0,flags=0)参数:pattern:正则中的模式字符串。repl:替换的字符串,也可为一个函数。string:要被查找替换的原始字符串。cou......