[转]使用自定义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 ...
随机推荐
- Hadoop2.7.4 在 Windows 10(64位) 详细配置
网上查询资料,实际配置后整理记录. 一.下载安装配置 1.8.0 以上版本 java 环境 完成后,使用 java -version 命令查看是否成功. 二.下载 hadoop-2.7.4.tar.g ...
- PAT《数据结构学习与实验指导》实验项目集 2-05 2-06 2-07 2-08
题目地址:here pat 2-05 求集合数据的均方差 没什么可说的,大水题 #include<cstdio> #include<cmath> int main() { in ...
- Iperf是一个网络性能测试工具
http://blog.163.com/hlz_2599/blog/static/142378474201341341339314/ Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP ...
- SQL Server删除log文件
数据库文件太大 SQL Server用的久了,会发现备份文件越来越大,这个其实主要是log文件的增加,删掉log文件就可以了.不过操作之前最好还是有个完整备份的好. 分离数据库 分离数据库,勾选删除链 ...
- Linux 防火墙命令的操作命令CentOS
service firewalld status; #查看防火墙状态 systemctl start firewalld.service;#开启防火墙 systemctl stop firewalld ...
- coco2d-js 触摸移动的同时处理点击事件
cc.eventManager.addListener({ event: cc.EventListener.TOUCH_ALL_AT_ONCE, onTouchesMoved:function (to ...
- ODI---->Variables
一.变量简介 变量存储的是一个单一的值,既可以是数字,也可以是字符或者日期.不能为数组. ODI的变量分为两种,全局变量和项目变量. 顾名思义,项目变量定义的变量只可以在本项目中使用,其它项目无法调用 ...
- tcp 两个重要窗口:滑动窗口 和 拥塞窗口
一:滑动窗口是接受数据端使用的窗口大小,用来告知发送端接收端的缓存大小,以此可以控制发送端发送数据的大小,从而达到流量控制的目的,对应==>rwnd:接收端窗口(receiver window) ...
- django之创建第8个项目-数据库配置及同步研究
1.sqlitestudio-2.1.5数据库可视化工具--百度云盘下载 2.编写C:\djangoweb\helloworld\blog\models.py文件 # Create your mode ...
- python之模块distutils,打包工具
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之模块distutils,打包工具 import distutils #distutils包有2 ...