springboot 设置全局字符编码,解决乱码问题

设置springboot字符编码,只是设置http请求中 HttpServletRequest和响应HttpServletResponse的报文编码格式。
编码格式其实是对于字节而言的,字符串其实不存在字符编码问题。乱码是在字符串转字节,然后字节转字符串时出现的,前后编码格式保持一致无论使用哪种编码格式都不会乱码
请求编码格式是告诉我们用什么编码解析请求的字节数据,http请求头中的设置的编码格式(content-type=“application/json; charset=GBK”),优先级高于HttpServletRequest的编码格式,如果请求头没设置,默认使用HttpServletRequest中的。
响应编码格式只是告诉别人接收到你返回的数据时,使用什么编码格式去转换二进制流(解析数据)。与项目运行的编码格式无关,项目运行的编码格式是在IDE(idea)中设置的项目编码格式,或者启动项目是的运行参数设置。http编码格式和项目编码格式不同时,就可能返回乱码数据。假如项目运行使用的utf-8,返回的字节数据就是u8格式的,而http设置的为返回gbk格式,对方会用gbk格式解析,此时(中文)就是utf-8转成gbk格式的乱码。

以下方法都可以设置请求和响应的字符编码格式
优先级:方法一 < 方法二 < 方法三

方法一:

springboot默认的编码格式就是UTF-8(只有request是),可以在HttpEncodingAutoConfiguration和HttpEncodingProperties(HttpProperties )这两个类中查看。
如果不设置,HttpServletRequest默认是utf-8格式,HttpServletResponse默认iso-8859-1,可通过HttpServletResponse.getCharacterEncoding()方法查看。

#全局编码格式 请求和响应同时设置,也可以单独设置,可以看一下源码的属性
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
server.tomcat.uri-encoding=UTF-8

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方法二:

这个方法可以解决NO converter for [xxxx] with preset Content-Type ‘null‘的问题,也可设置字符编码。
设置字符编码时不会影响接口HttpServletRequest request,HttpServletResponse response的编码格式,但在过滤器中会改变ServletResponse的编码格式(ServletRequest编码也未改变)。
只是在返回报文的时候使用指定的编码格式化,优先级高于方法一
这个方法可能由于config.setSerializerFeatures设置的值较少,在使用时使用postman工具调用接口正常
(postman发送报文使用的编码格式应该是UTF-8,将请求头中编码格式设置成其他,项目在解析参数
时会出现乱码),但第三方请求接口是报400异常,接口获取不到请求体,可能是解析出了问题…
后来没有深究

/**
 *  json序列化配置类
 */
@Configuration
public class JsonHttpMessageConfiguration{
    /**
     *  配置全局序列化的时候为null的属性也序列化
     */
    @Bean
    @ConditionalOnMissingBean(FastJsonHttpMessageConverter.class)
    public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
        //1.需要定义一个convert转换消息的对象
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        //2.添加fastJson的配置信息;
        FastJsonConfig config = new FastJsonConfig();
        //添加配置-config.setSerializerFeatures()  方法中可以添加多个配置(以,分开)
              config.setSerializerFeatures(SerializerFeature.WriteMapNullValue,SerializerFeature.DisableCircularReferenceDetect);
        //3.在convert中添加配置信息.
        // 配置全局支持的媒体类型
       converter.setSupportedMediaTypes(getSupportedMediaTypes());
        converter.setFastJsonConfig(config);
        //设置字符编码
        converter.setDefaultCharset(Charset.forName("GBK"));
        return converter;
    }
    /**
     *  配置全局支持的媒体类型
     */
    private List<MediaType> getSupportedMediaTypes() {
        List<MediaType> supportedMediaTypes = new ArrayList<>();
         //supportedMediaTypes.add(MediaType.ALL);
        supportedMediaTypes.add(MediaType.APPLICATION_JSON);
        supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        supportedMediaTypes.add(MediaType.APPLICATION_PDF);
        supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
        supportedMediaTypes.add(MediaType.APPLICATION_XML);
        supportedMediaTypes.add(MediaType.IMAGE_GIF);
        supportedMediaTypes.add(MediaType.IMAGE_JPEG);
        supportedMediaTypes.add(MediaType.IMAGE_PNG);
        supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
        supportedMediaTypes.add(MediaType.TEXT_HTML);
        supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
        supportedMediaTypes.add(MediaType.TEXT_PLAIN);
        supportedMediaTypes.add(MediaType.TEXT_XML);
        return supportedMediaTypes;
    }
}

方法三:

使用RequestMapping注解属性设置,设置字符编码时也不会影响接口参数中HttpServletRequest request,HttpServletResponse response的编码格式,但在过滤器中会改变ServletResponse的编码格式(ServletRequest编码也未改变)。此方法会出现NO converter for [xxxx] with preset Content-Type ‘null‘的问题(可能版本原因)需要配合方法二使用。
也可以在接口中直接赋值,这种方法在过滤器中会改变ServletResponse、ServletRequest的编码格式,不用和方法二配合使用。

@RequestMapping(value = "/notify",headers ={"Content-Type=application/x-www-form-urlencoded;charset=GBK"} , method = RequestMethod.POST, 
consumer= "application/json; charset=GBK",produces = "application/json; charset=GBK")
// produces  GBK 只是告诉别人接收返回的数据时,使用GBK编码格式化字节数据,
//如果项目使用的utf-8格式,则返回的字节数据是utf-8格式的,这里指定GBK,别人在解析接收数据时就会乱码,所以这里指定的编码格式要与项目使用的编码一值
public ResponseEntity<String> notify(@RequestParam(name = "p") String plain, @RequestParam("s") String signature), HttpServletRequest request,HttpServletResponse response){
request.setCharacterEncoding("GBK");
response.setCharacterEncoding("GBK");//与produces 设置相同,优先级低于produces 
response.setContentType("application/json;charset=GBK");//3设置

方法四:

自定义过滤器等等,原理类似

@Configuration
public class CharacterConfig {
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
 
        //创建SpringWeb提供的字符编码过滤器,主要实现字符编码过滤
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setForceEncoding(true);//强制对请求的编码,
        filter.setEncoding("GBK");//使用GBK编码
        
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }
//@Bean
//CharacterEncodingFilter characterEncodingFilter() {
    //CharacterEncodingFilter filter = new CharacterEncodingFilter();
    //filter.setEncoding("UTF-8");
    //filter.setForceEncoding(true);
    //return filter;
//}
}

自定义filter,RequestWrapper,ResponseWrapper 处理请求和响应数据,此方法可参考下一篇

package com.hoau.monitor.filter;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.hoau.common.exception.PSBCommonException;
import com.hoau.monitor.entity.MonitorData;
import com.hoau.monitor.facade.IhoauMonitorDataFacade;
import com.hoau.monitor.servlet.RequestWrapper;
import com.hoau.monitor.servlet.ResponseWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@WebFilter(urlPatterns = {"/*"}, filterName = "monitorDataFilter")
public class MonitorDataFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
        ResponseWrapper responseWrapper = new ResponseWrapper(httpServletResponse);
        filterChain.doFilter(requestWrapper, responseWrapper);
        byte[] bytes = responseWrapper.getBytes();
        val = new String(bytes, "UTF-8");
        //将数据 再写到 response 中
        byte[] gbks = val.getBytes("gbk");//这里编码转换操作
        servletResponse.setContentLength(gbks.length);
        servletResponse.getOutputStream().write(gbks);
        servletResponse.getOutputStream().flush();
        servletResponse.getOutputStream().close();

    }

    @Override
    public void destroy() {

    }
}

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
后端分离开发是现代Web应用开发的一种趋势,多数情况下前端和后端是独立开发的,也是独立部署和运行。由于浏览器的同源策略限制,前端应用不允许跨域访问不同源的资源,也就是说前端应用和后端应用必须部署在同一个域名下。但是,在实际应用开发中,例如前端和后端部署在不同的服务器上,我们就需要解决跨域的问题SpringBoot是一个快速开发框架,它大大简化了Spring应用的开发过程,作为SpringBoot的一部分,它提供了解决全局跨域问题的方法。SpringBoot 改进了 SpringMVC 的 WebMvcConfigurerAdapter 这个类的功能,提供了 addCorsMappings 方法。使用 CorsFilter 自定义过滤器则是在 Spring Boot 2.x 之前的做法。 我们可以通过在SpringBoot的实例中添加如下全局跨域配置方法来解决全局跨域问题: ``` @Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST","PUT", "DELETE") .allowCredentials(true) .maxAge(3600); } }; } } ``` 以上代码的作用是为SpringBoot实例添加一个名为CorsConfig的类,并在其中定义一个名为corsConfigurer的方法,该方法返回一个继承自WebMvcConfigurerAdapter的匿名类实例,并重载 addCorsMappings 方法。在该方法中,我们使用 registry.addMapping("/**") 为所有的路径添加跨域配置;allowedOrigins("*") 允许所有的来源;allowedMethods("GET", "POST","PUT", "DELETE") 允许所有的HTTP方法;allowCredentials(true) 允许发送cookie;maxAge(3600) 缓存响应时间为1小时。 在使用SpringBoot解决跨域问题后,前端应用就可以访问不同的后端服务器资源了。这大大提高了应用的灵活性和可维护性,使得我们可以在实际应用中更好地实现前后端分离的开发和部署。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值