首頁 > 軟體

springboot 介面返回字串帶引號的問題解決

2022-04-15 13:01:20

框架版本

springboot 2.2.1.RELEASE
fastjson 1.2.78

maven pom.xml parent 和 dependencies

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
    </dependencies>

問題

如下程式碼,返回結果是 "hello world",新增了一個雙引號。

@RestController
@Slf4j
public class Hello1Controller {

    @GetMapping(value = "/printHello")
    @ResponseBody
    public String printHello() {
        return "hello world";
    }
}

排查

不管返回什麼的結果,肯定經過MessageConvert進行訊息的輸出,debug看使用了哪一個MessageConvert

選擇MessageConvert的方法是
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters(T, org.springframework.core.MethodParameter, org.springframework.http.server.ServletServerHttpRequest, org.springframework.http.server.ServletServerHttpResponse)

關鍵程式碼

        if (selectedMediaType != null) {
            selectedMediaType = selectedMediaType.removeQualityValue();
             // 打個斷點在此處
            for (HttpMessageConverter<?> converter : this.messageConverters) {
                GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?
                        (GenericHttpMessageConverter<?>) converter : null);
                if (genericConverter != null ?
                        ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :
                        converter.canWrite(valueType, selectedMediaType)) {
                    body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
                            (Class<? extends HttpMessageConverter<?>>) converter.getClass(),
                            inputMessage, outputMessage);
                    if (body != null) {
                        Object theBody = body;
                        LogFormatUtils.traceDebug(logger, traceOn ->
                                "Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]");
                        addContentDispositionHeader(inputMessage, outputMessage);
                        if (genericConverter != null) {
                            genericConverter.write(body, targetType, selectedMediaType, outputMessage);
                        }
                        else {
                            ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
                        }
                    }
                    else {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Nothing to write: null body");
                        }
                    }
                    return;
                }
            }
        }

debug發現我的messageConvert只有一個,是com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter。那肯定是經過FastJson將String 寫到輸出流。

debug檢視FastJsonHttpMessageConverter具體的write 程式碼 ,可以看到此時輸出字串新增了引號。

方法:com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter#writeInternal

寫個fastjson 轉化字串試試,如下結果輸出是 "hello world",新增了引號。

import com.alibaba.fastjson.JSON;

public class JsonTest {
    public static void main(String[] args) {
        System.out.println(JSON.toJSONString("hello world"));
        // 
    }
}

問題所在

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer  {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig config = new FastJsonConfig();
        config.setCharset(StandardCharsets.UTF_8);
        //設定允許返回為null的屬性
        config.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
       
        fastJsonConverter.setFastJsonConfig(config);
        List<MediaType> list = new ArrayList<>();
        list.add(MediaType.APPLICATION_JSON);
        fastJsonConverter.setSupportedMediaTypes(list);
        converters.add(fastJsonConverter);
    }

}

我設定了FastJsonHttpMessageConverter ,導致只使用FastJsonHttpMessageConverter 進行訊息轉換。

解決方法

新增StringHttpMessageConverter ,讓其轉化String。注意順序,StringHttpMessageConverter 要在FastJsonHttpMessageConverter 之前。

 @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig config = new FastJsonConfig();
        config.setCharset(StandardCharsets.UTF_8);
        //設定允許返回為null的屬性
        config.setSerializerFeatures(SerializerFeature.WriteMapNullValue);

        fastJsonConverter.setFastJsonConfig(config);
        List<MediaType> list = new ArrayList<>();
        list.add(MediaType.APPLICATION_JSON);
        fastJsonConverter.setSupportedMediaTypes(list);

        StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
        stringHttpMessageConverter.setSupportedMediaTypes(list);
        converters.add(stringHttpMessageConverter);

        converters.add(fastJsonConverter);
    }

返回資料沒有引號了。

參考資料

【Spring】HttpMessageConverter的作用及替換

到此這篇關於springboot 介面返回字串帶引號的問題解決的文章就介紹到這了,更多相關springboot 返回字串帶引號內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com