1 自定义消息转换器实现全局加解密
@RequiredArgsConstructor
public class MyMessageConverter extends MappingJackson2HttpMessageConverter {
Logger logger = LoggerFactory.getLogger(MyMessageConverter.class);
private static SM4Util sm4Util = new SM4Util();
private static final String SM4_KEY = "JXWECHATINTERFACE2021#@!%781";
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
logger.info("=============");
JavaType javaType = this.getJavaType(type, contextClass);
InputStream is = inputMessage.getBody();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] b = new byte[4096];
int n = 0;
while ((n = is.read(b)) > 0) {
out.write(b, 0, n);
}
//解密 解密 plainBody是未解密的参数串
String plainBody = out.toString();
JSONObject jsonObject = JSONObject.parseObject(plainBody);
String requestData = jsonObject.getString("requestData");
logger.info("需要解密的业务参数是:" + requestData);
String decode = sm4Util.decode(requestData, SM4_KEY);
JSONObject jsonObject2 = JSONObject.parseObject(decode);
jsonObject.put("requestData", jsonObject2);
plainBody = jsonObject.toJSONString();
try {
return this.objectMapper.readValue(new ByteArrayInputStream(plainBody.getBytes()), javaType);
} catch (IOException ex) {
throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
}
}
/**
* Spring在返回JSON数据时通过此方法将Object转为JSON字符串并写出到Response中,针对于@ResponseBody注解生效
*/
@Override
protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
//ObjectMapper objectMapper = new ObjectMapper();
ResponseDTO responseDTO = null;
// 用spring带的工具类,比较返给前端的数据类型是否为ResultMessage
if (TypeUtils.isAssignable(type, ResponseDTO.class)) {
responseDTO = (ResponseDTO) object;
String result = this.objectMapper.writer().writeValueAsString(responseDTO);
JSONObject jsonObject = JSONObject.parseObject(result);
Object data = jsonObject.get("data");
if (data != null) {
logger.info("需要解密的业务参数是:" + data.toString());
String encode = sm4Util.encode(data.toString(), SM4_KEY);
jsonObject.put("data", encode);
object = jsonObject;
}
}
super.writeInternal(object, type, outputMessage);
}
}
2 WebConfig添加自定义HttpMessageConverter
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public MyMessageConverter myMessageConverter() {
return new MyMessageConverter();
}
/**
* 配置消息转换器
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(myMessageConverter());
}
}
3 修复添加了HttpMessageConverter之后Feign远程调用多次进入消息转换器问题
@Configuration
public class FeignConfig {
@Bean
public Logger.Level getFeignLoggerLevel() {
return Logger.Level.FULL ;
}
@Bean
public ResponseEntityDecoder feignDecoder() {
HttpMessageConverter fastJsonConverter = createFastJsonConverter();
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(fastJsonConverter);
return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
}
@Bean
public SpringEncoder feignEncoder(){
HttpMessageConverter fastJsonConverter = createFastJsonConverter();
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(fastJsonConverter);
return new SpringEncoder(objectFactory);
}
private HttpMessageConverter createFastJsonConverter() {
//创建fastJson消息转换器
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
//升级最新版本需加=============================================================
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
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);
fastConverter.setSupportedMediaTypes(supportedMediaTypes);
//创建配置类
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//修改配置返回内容的过滤
//WriteNullListAsEmpty :List字段如果为null,输出为[],而非null
//WriteNullStringAsEmpty : 字符类型字段如果为null,输出为"",而非null
//DisableCircularReferenceDetect :消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
//WriteNullBooleanAsFalse:Boolean字段如果为null,输出为false,而非null
//WriteMapNullValue:是否输出值为null的字段,默认为false
fastJsonConfig.setSerializerFeatures(
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteMapNullValue,
SerializerFeature.PrettyFormat,
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteEnumUsingToString,
SerializerFeature.WriteNullStringAsEmpty
);
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
fastConverter.setFastJsonConfig(fastJsonConfig);
return fastConverter;
}
}