<mvc:annotation-driven>
<mvc:message-converters>
<bean class="com.showe.MyMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.google.common.collect.Lists;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractGenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
public class MyMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
private Charset charset = Charset.forName("UTF-8");
protected ObjectMapper objectMapper;
private PrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
public MyMessageConverter() {
this.objectMapper = Jackson2ObjectMapperBuilder.json().build();
this.setSupportedMediaTypes(Lists.newArrayList(MediaType.ALL, MediaType.APPLICATION_JSON, MediaType
.APPLICATION_JSON_UTF8, MediaType.APPLICATION_FORM_URLENCODED));
}
@Override
protected boolean supports(Class<?> clazz) {
return supportInternalAndHandle(clazz);
}
private boolean supportInternalAndHandle(Class<?> clazz) {
//这里的clazz是controller中的加有@RequestBody的入参,如果入参Dto类上有MyAnnotation注解,则支持转换
SecurityBody securityBody = AnnotationUtils.findAnnotation(clazz, MyAnnotation.class);
if (securityBody == null) {
return false;
}else{
return true;
}
}
/**
* Abstract template method that writes the actual body. Invoked from {@link #write}.
* @param t the object to write to the output message
* @param type the type of object to write (may be {@code null})
* @param outputMessage the HTTP output message to write to
* @throws IOException in case of I/O errors
* @throws HttpMessageNotWritableException in case of conversion errors
*/
@Override
protected void writeInternal(Object o, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
MediaType contentType = outputMessage.getHeaders().getContentType();
JsonEncoding jsonEncoding = getJsonEncoding(contentType);
JsonGenerator generator = objectMapper.getFactory().createGenerator(outputMessage.getBody(), jsonEncoding);
String outStr = objectMapper.writeValueAsString(o);
ObjectWriter writer = objectMapper.writer();
writer.with(prettyPrinter);
writer.writeValue(generator,outStr);
generator.flush();
}
private JsonEncoding getJsonEncoding(MediaType contentType) {
if(null != contentType && contentType.getCharset()!=null){
Charset charset = contentType.getCharset();
for (JsonEncoding jsonEncoding:JsonEncoding.values()){
if(charset.name().equals(jsonEncoding.name())){
return jsonEncoding;
}
}
}
return JsonEncoding.UTF8;
}
/**
* Abstract template method that reads the actual object. Invoked from {@link #read}.
* @param clazz the type of object to return
* @param inputMessage the HTTP input message to read from
* @return the converted object
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
*/
@Override
protected Map<String,String> readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
MediaType contentType = inputMessage.getHeaders().getContentType();
Charset charset = contentType.getCharset()!=null?contentType.getCharset():this.charset;
//String body = StreamUtils.copyToString(inputMessage.getBody(), charset);
String body = copyToString(inputMessage.getBody(),charset);
Map<String,String> inputMap = handleParameters(body);
return inputMap;
}
private Map<String,String> handleParameters(String body) throws UnsupportedEncodingException {
Map<String,String> reqMap = new HashMap<>();
String[] pairs = StringUtils.tokenizeToStringArray(body, "&");
for (String pair:pairs) {
int index = pair.indexOf("=");
if(-1 == index){
reqMap.put(URLDecoder.decode(pair, "UTF-8"), null);
}else {
String name = URLDecoder.decode(pair.substring(0,index),this.charset.name());
String value = URLDecoder.decode(pair.substring(index+1),this.charset.name());
reqMap.put(name,value);
}
}
return reqMap;
}
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return readInternal((Class) type, inputMessage);
}
private String copyToString(InputStream in,Charset charset) throws IOException {
if(null==in){
return "";
}
StringBuilder out = new StringBuilder();
char[] buffer = new char[1024];
InputStreamReader reader = new InputStreamReader(in);
int len = -1;
while ((len = reader.read(buffer)) != -1){
out.append(buffer,0,len);
}
return out.toString();
}
}