Spring boot 如何避免\“;在json中';谁的绳子?
Spring启动应用程序 在build.gradle中:Spring boot 如何避免\“;在json中';谁的绳子?,spring-boot,gson,activemq,Spring Boot,Gson,Activemq,Spring启动应用程序 在build.gradle中: implementation 'com.google.code.gson:gson:2.7' 这里是JMS配置: import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer; import org.springframework.context.annotation.Bean; import org.spri
implementation 'com.google.code.gson:gson:2.7'
这里是JMS配置:
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
@Configuration
@ComponentScan(basePackages = "ru.otus.software_architect.eshop")
public class JMSConfiguration {
@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all boot's default to this factory, including the message converter
configurer.configure(factory, connectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
}
在日志中:
成功\u向\u MB发送消息\u
:
{"email":"someemail@email.com","action":"order_update","orderId":14}
很好
但在我的队列中的ActiveMQ上,消息如下所示:
"{\"email\":\"a_subscriber@mail.ru\",\"action\":\"order_update\",\"orderId\":4,\"createdAt\":\"2020-09-13T11:32:09.976+0300\"}"
"%7B%22email%22%3A%22myemail%40mail.com%22%2C%22action%22%3A%22order_delete%22%2C%22orderId%22%3A6%2C%22createdAt%22%3A%222020-09-19T12%3A20%3A57.844%2B0300%22%7D"
这里是截图:
然后启动另一个应用程序(消费者)。当尝试从json获取日期时,它被破坏:
JsonElement messageJson = GsonUtil.parser.parse(message);
String action = messageJson.getAsJsonObject().get("action").getAsString(); // here broken
我收到错误消息:
Caused by: java.lang.IllegalStateException: Not a JSON Object: "{\"email\":\"a_subscriber@mail.ru\",\"action\":\"order_update\",\"orderId\":4,\"createdAt\":\"2020-09-13T11:32:09.976+0300\"}"
如何避免字符串中的\
我需要排队成为下一个字符串:
{"email":"someemail@email.com","action":"order_update","orderId":14}
尝试使用默认的
MessageConverter
(即),并以字节[]
的形式发送消息,例如:
private void sendMessageToMessageBroker(NotifyActionEnum操作,int orderId){
JsonObject json=新的JsonObject();
json.addProperty(“email”,UserService.getCurrentUserName());
addProperty(“action”,action.name().toLowerCase());
addProperty(“orderId”,orderId);
JmsTemplate JmsTemplate=context.getBean(JmsTemplate.class);
String message=json.toString();
convertAndSend(ESHOP_队列,message.getBytes());
info(“sendMessageToMessageBroker:success\u sent\u message\u to\u MB:+message”);
}
当您以字节[]
的形式发送消息时,SimpleMessageConverter
将其转换为javax.jms.ByteMessage
。当您的消费者收到消息时,它可以将字节[]
转换为字符串,如下所示:
String消息字符串;
if(字节消息的消息实例){
BytesMessage BytesMessage=(BytesMessage)消息;
byte[]buffer=新字节[(int)bytesMessage.getBodyLength()];
bytesMessage.readBytes(缓冲区);
messageAsString=新字符串(缓冲区);
}
JsonElement messageJson=GsonUtil.parser.parse(messageAsString);
String action=messageJson.getAsJsonObject().get(“action”).getAsString();
我相信以字节[]
的形式发送消息将避免任何不必要的转义。我使用urlEncode/decode
将消息发送到ActiveMQ
在我的控制器中:
private String publishToMessageBroker(NotifyActionEnum action, int orderId) {
logger.info("publishToMessageBroker:");
JsonObject json = new JsonObject();
json.addProperty("email", UserService.getCurrentUserName());
json.addProperty("action", action.name().toLowerCase());
json.addProperty("orderId", orderId);
json.addProperty("createdAt", DateUtil.date2String(new Date(), DateUtil.JSON_DATE_FORMAT));
String message = json.toString();
String urlEncodeMessage = StringUtll.urlEncode(message);
jmsTemplate.convertAndSend(ESHOP_QUEUE, urlEncodeMessage);
logger.info("publishToMessageBroker: success_sent_message_to_MB: " + message);
return "Message was success published on Message Broker!"; // can use as response
}
现在在ActiveMQ中,消息如下所示:
"{\"email\":\"a_subscriber@mail.ru\",\"action\":\"order_update\",\"orderId\":4,\"createdAt\":\"2020-09-13T11:32:09.976+0300\"}"
"%7B%22email%22%3A%22myemail%40mail.com%22%2C%22action%22%3A%22order_delete%22%2C%22orderId%22%3A6%2C%22createdAt%22%3A%222020-09-19T12%3A20%3A57.844%2B0300%22%7D"
现在在信息接收器中,我解码信息
@JmsListener(destination = ESHOP_QUEUE)
public void receiveMessage(String urlEncodeMessage) {
try {
String urlDecodeMessage = StringUtil.urlDecode(urlEncodeMessage);
String pureDecodeMessage = StringUtil.removeFirstAndLastQuotes(urlDecodeMessage);
JsonElement messageJson = GsonUtil.parser.parse(pureDecodeMessage);
现在工作正常。没有像“这样的越狱符号
url解码后,我得到纯json:
"{"email":"myemail@mail.com","action":"order_delete","orderId":6,"createdAt":"2020-09-19T12:20:57.844+0300"}"
有东西将字符串放在双引号中,需要转义字符串中的双引号才能起作用。@Steve为什么在队列中用\“?我猜是因为字符串开头和结尾的引号。不管是什么机制添加这些引号,也可以通过在每个字符串前面加“\”来避开字符串中间的引号。我不知道为什么会发生这种情况。您为JmsTemplate
配置了什么MessageConverter
?您是否使用默认的SimpleMessageConverter
将字符串
转换为javax.jms.TextMessage
?@JustinBertram我更新了我的帖子是否可以理解制作人通过web控制台发送的内容?我不确定您的意思。我想查看一些信息,如{“email”:someemail@email.com“,”动作“:“订单更新”、“订单ID”:14}
通过ui工具我不确定ActiveMQ web控制台是否会将字节[]
解码为字符串以显示。请记住,消息(甚至文本消息)可以以多种不同的方式进行编码,代理不一定拥有将消息解码为人类可读格式(假设存在这种格式)所需的信息。我相信web控制台无法将字节[]解码为字符串,因为字节[]可以是任何内容。但order_id可能是一条非常有用的信息,应该能够被视为人类的语言