[转]使用自定义HttpMessageConverter对返回内容进行加密
今天上午技术群里的一个人问” 如何在 Spring MVC 中统一对返回的 Json 进行加密?”。
大部分人的第一反应是通过 Spring 拦截器(Interceptor)中的postHandler
方法处理。实际这是行不通的,因为当程序运行到该方法,是在返回数据之后,渲染页面之前,所以这时候 Response 中的输出流已经关闭了,自然无法在对返回数据进行处理。
其实这个问题用几行代码就可以搞定,因为 Spring 提供了非常丰富的扩展支持,无论是之前提到的Interceptor
和MethodArgumentResolver
,还是接下来要提到的HttpMessageConverter
。
在 Spring MVC 的 Controller 层经常会用到@RequestBody
和@ResponseBody
,通过这两个注解,可以在 Controller 中直接使用 Java 对象作为请求参数和返回内容,而完成这之间转换作用的便是HttpMessageConverter
。
HttpMessageConverter
接口提供了 5 个方法:
canRead
:判断该转换器是否能将请求内容转换成 Java 对象canWrite
:判断该转换器是否可以将 Java 对象转换成返回内容getSupportedMediaTypes
:获得该转换器支持的 MediaType 类型read
:读取请求内容并转换成 Java 对象write
:将 Java 对象转换后写入返回内容其中
read
和write
方法的参数分别有有HttpInputMessage
和HttpOutputMessage
对象,这两个对象分别代表着一次 Http 通讯中的请求和响应部分,可以通过getBody
方法获得对应的输入流和输出流。这里通过实现该接口自定义一个 Json 转换器作为示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
class CustomJsonHttpMessageConverter implements HttpMessageConverter {
//Jackson 的 Json 映射类
private ObjectMapper mapper = new ObjectMapper ();
// 该转换器的支持类型:application/json
private List supportedMediaTypes = Arrays.asList (MediaType.APPLICATION_JSON);
/**
* 判断转换器是否可以将输入内容转换成 Java 类型
* @param clazz 需要转换的 Java 类型
* @param mediaType 该请求的 MediaType
* @return
*/
@Override
public boolean canRead (Class clazz, MediaType mediaType) {
if (mediaType == null) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes ()) {
if (supportedMediaType.includes (mediaType)) {
return true;
}
}
return false;
}
/**
* 判断转换器是否可以将 Java 类型转换成指定输出内容
* @param clazz 需要转换的 Java 类型
* @param mediaType 该请求的 MediaType
* @return
*/
@Override
public boolean canWrite (Class clazz, MediaType mediaType) {
if (mediaType == null || MediaType.ALL.equals (mediaType)) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes ()) {
if (supportedMediaType.includes (mediaType)) {
return true;
}
}
return false;
}
/**
* 获得该转换器支持的 MediaType
* @return
*/
@Override
public List getSupportedMediaTypes () {
return supportedMediaTypes;
}
/**
* 读取请求内容,将其中的 Json 转换成 Java 对象
* @param clazz 需要转换的 Java 类型
* @param inputMessage 请求对象
* @return
* @throws IOException
* @throws HttpMessageNotReadableException
*/
@Override
public Object read (Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return mapper.readValue (inputMessage.getBody (), clazz);
}
/**
* 将 Java 对象转换成 Json 返回内容
* @param o 需要转换的对象
* @param contentType 返回类型
* @param outputMessage 回执对象
* @throws IOException
* @throws HttpMessageNotWritableException
*/
@Override
public void write (Object o, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
mapper.writeValue (outputMessage.getBody (), o);
}
}
|
当前 Spring 中已经默认提供了相当多的转换器,分别有:
名称 | 作用 | 读支持 MediaType | 写支持 MediaType |
---|---|---|---|
ByteArrayHttpMessageConverter | 数据与字节数组的相互转换 | \/\ | application/octet-stream |
StringHttpMessageConverter | 数据与 String 类型的相互转换 | text/\* | text/plain |
FormHttpMessageConverter | 表单与 MultiValueMap的相互转换 | application/x-www-form-urlencoded | application/x-www-form-urlencoded |
SourceHttpMessageConverter | 数据与 javax.xml.transform.Source 的相互转换 | text/xml 和 application/xml | text/xml 和 application/xml |
MarshallingHttpMessageConverter | 使用 Spring 的 Marshaller/Unmarshaller 转换 XML 数据 | text/xml 和 application/xml | text/xml 和 application/xml |
MappingJackson2HttpMessageConverter | 使用 Jackson 的 ObjectMapper 转换 Json 数据 | application/json | application/json |
MappingJackson2XmlHttpMessageConverter | 使用 Jackson 的 XmlMapper 转换 XML 数据 | application/xml | application/xml |
BufferedImageHttpMessageConverter | 数据与 java.awt.image.BufferedImage 的相互转换 | Java I/O API 支持的所有类型 | Java I/O API 支持的所有类型 |
回到最开始所提的需求,既然要对返回的 Json 内容进行加密,肯定是对MappingJackson2HttpMessageConverter
进行改造,并且只需要重写write
方法。
从MappingJackson2HttpMessageConverter
的父类AbstractHttpMessageConverter
中的write
方法可以看出,该方法通过writeInternal
方法向返回结果的输出流中写入数据,所以只需要重写该方法即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter () {
return new MappingJackson2HttpMessageConverter () {
// 重写 writeInternal 方法,在返回内容前首先进行加密
@Override
protected void writeInternal (Object object,
HttpOutputMessage outputMessage) throws IOException,
HttpMessageNotWritableException {
// 使用 Jackson 的 ObjectMapper 将 Java 对象转换成 Json String
ObjectMapper mapper = new ObjectMapper ();
String json = mapper.writeValueAsString (object);
LOGGER.error (json);
// 加密
String result = json + "加密了!";
LOGGER.error (result);
// 输出
outputMessage.getBody ().write (result.getBytes ());
}
};
}
|
在这之后还需要将这个自定义的转换器配置到 Spring 中,这里通过重写WebMvcConfigurer
中的configureMessageConverters
方法添加自定义转换器:
1
2
3
4
5
6
|
// 添加自定义转换器
@Override
public void configureMessageConverters (List> converters) {
converters.add (mappingJackson2HttpMessageConverter ());
super.configureMessageConverters (converters);
}
|
测试一下:
如此便简单的完成了对返回内容进行加密的功能。
(原文地址:http://www.scienjus.com/custom-http-message-converter/)
[转]使用自定义HttpMessageConverter对返回内容进行加密的更多相关文章
- 自定义HttpMessageConverter实现RestTemplate的exchange方法返回自定义格式数据
一 概述 实现如下效果代码,且可正常获取到返回数据: ResponseEntity<JsonObject> resEntity = restTemplate .exchange(url, ...
- .net中自定义过滤器对Response内容进行处理
原文:http://www.cnblogs.com/zgqys1980/archive/2008/09/02/1281895.html 代码DEMO:http://files.cnblogs.com/ ...
- Fiddler 修改返回内容 OnBeforeResponse 无效 没用
Fiddler自定义脚本可以实现很强大的内容替换,包括很有意义的——修改返回内容. 具体的方法可以参考官网:http://docs.telerik.com/fiddler/KnowledgeBase/ ...
- SpringBoot自定义HttpMessageConverter
Spring就是一个大大的插线板,上面插着各种各样的Bean. SpringBoot大大简化了Spring的配置,将原来放在XML中的配置大量的在代码中使用注解实现.这么做有利有弊,总体上利大于弊. ...
- Django(四) 后台管理:创建管理员、注册模型类、自定义管理页面显示内容
后台管理 第1步.本地化:设置语言.时区 修改project1/settings.py #LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'zh-hans' #设置语言 ...
- WPF界面设计技巧(5)—自定义列表项呈现内容
原文:WPF界面设计技巧(5)-自定义列表项呈现内容 接续上次的程序,稍微改动一下原有样式,并添加一个数据模板,我们就可以达成下面这样的显示功能: 鼠标悬停于文件列表项上,会在工具提示中显示图像缩略图 ...
- 自定义View 可清除内容、设置图标、下划线的输入框 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Spring mvc 注解@ResponseBody 返回内容编码问题
@ResponseBody 在@Controller 类方法中能够让字符串直接返回内容. 其返回处理的类是org.springframework.http.converter.StringHttpMe ...
- echarts自定义tooltip提示框内容
1.echarts自定义tooltip提示框内容 https://blog.csdn.net/dreamsup/article/details/56667330 2.关于Echarts的formatt ...
随机推荐
- 1066: 单词游戏(game)
var i,j,k,n,ans,p,len,chk,zh:longint; ch:char; s:string; a:array[..] of longint; begin readln(ch); c ...
- Atlas系列一:【已解决】error while loading shared libraries: libcrypto.so.6: cannot open shared object file: No such file or directory
1:Atlas的安装 https://github.com/Qihoo360/Atlas/wiki/Atlas的安装 2: [root@localhost bin]# ./mysql-proxyd t ...
- JavaScript中如何检测一个变量是一个String类型?请写出函数实现
方法1. function isString(obj){ return typeof(obj) === "string"? true: false; // returntypeof ...
- 关于0xFFFFFFFF和alpha,温故而知新
做图像处理都好多年了,今天随手做个小画板的时候,发现一个挺有趣的小坑.而其实这个小坑,以前也坑过自己,不过太久没处理了,又踩到坑里了. 先来看看:0xFFFFFFFF>>24 这个结果是什 ...
- Linux进程共享通信 -- mmap实现
https://blog.csdn.net/y396397735/article/details/50651633 使用mmap内存映射实现一端写,另一端读的进程间通信 写端代码write.c /*w ...
- 〖Linux〗Kubuntu KDE开机后总是提示“system program problem detected”的解决方法
自从从Ubuntu切换到了Kubuntu之后,就经常在开机的时候提示“system program problem detected”: 查看 /var/crash/ 发现都是一些无关痛痒的程序在关机 ...
- 〖Android〗依据资源信息,Mock Android资源
#!/bin/bash - #=============================================================================== # # F ...
- django之创建第6-1个项目-自定义过滤器
1.在站点blog目录下创建templatetags文件夹 2.templatetags目录下需要作为一个包来处理和调用其中的内容,需要有一个__init__.py文件 3.在templatetags ...
- python之模块ftplib(FTP协议的客户端)
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之模块ftplib(FTP协议的客户端) #需求:快速进行ftp上传 ,下载,查询文件 from ...
- Linux下RocksDB、LevelDB、ForestDB性能测试对比
简要说明 本次环境与http://www.cnblogs.com/oloroso/p/6306352.html中的一致. 依然是增删查改各测试10000次,每个测试重复5次取平均值. 1.不使用jem ...