springboot中的攔截器interceptor和過濾器filter,多次獲取request引數
阿新 • • 發佈:2019-01-29
大家好,我是烤鴨:
這是一篇關於springboot的攔截器(interceptor)和過濾器(Filter)。
1.servlet請求,順序:Filter ——> interceptor。
2.Filter的作用是對所有進行過濾,包括介面或者靜態資源,interceptor 僅攔截 請求。
3.Filter對請求或者資源進行過濾,篩選合適的請求或者資源。interceptor,僅對不符合的請求攔截。
4.Filter基於回撥函式,我們需要實現的filter介面中doFilter方法就是回撥函式,而interceptor則基於
java本身的反射機制,這是兩者最本質的區別。
5.Filter是依賴於servlet容器的,即只能在servlet容器中執行,很顯然沒有servlet容器就無法來回調
doFilter方法。而interceptor與servlet容器無關。
後面程式碼較多,不太適合看。
簡單說一下,我這個過濾器的作用。目的就是可以以流的方式多次獲取請求引數。
正常requst.getInputStream只能獲取一次。但是我在過濾器中將他的引數放到threadlocal中,
這樣當前請求中就可以獲取到請求引數了。
另外說一下:
有兩種方式實現多次獲取request引數。
1.建立threadlocal類,將request或者request的引數放進去。
2.建立wrapper類,類似裝飾者模式,對request物件進行處理。getInputStream之後將流重新set進去。
回撥介面都需要驗證簽名,而且簽名規則一樣,所以想拿到攔截器處理。
如果簽名或者ip地址不符合條件,直接就返回了。而具體的介面只要專注業務處理,不需要驗證簽名了。
這是一篇關於springboot的攔截器(interceptor)和過濾器(Filter)。
先說一下過濾器和攔截器。
區別:1.servlet請求,順序:Filter ——> interceptor。
2.Filter的作用是對所有進行過濾,包括介面或者靜態資源,interceptor 僅攔截 請求。
3.Filter對請求或者資源進行過濾,篩選合適的請求或者資源。interceptor,僅對不符合的請求攔截。
4.Filter基於回撥函式,我們需要實現的filter介面中doFilter方法就是回撥函式,而interceptor則基於
java本身的反射機制,這是兩者最本質的區別。
5.Filter是依賴於servlet容器的,即只能在servlet容器中執行,很顯然沒有servlet容器就無法來回調
doFilter方法。而interceptor與servlet容器無關。
後面程式碼較多,不太適合看。
提前總結一下,我這裡的過濾器和攔截器的使用:
filter:目的就是可以以流的方式多次獲取請求引數。
Interceptor: 對回撥介面進行統一的驗證簽名。
回撥介面都需要驗證簽名,而且簽名規則一樣,所以想拿到攔截器處理。
如果簽名或者ip地址不符合條件,直接就返回了。而具體的介面只要專注業務處理,不需要驗證簽名了。
下面貼一下在springboot中的使用:
1. filter:
InterfaceFilter.java
package com.test.test.filter; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter(urlPatterns = "/*", filterName = "InterfaceFilter") public class InterfaceFilter implements Filter{ private static Logger log = LoggerFactory.getLogger(InterfaceFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; try { if ("POST".equals(req.getMethod().toUpperCase())) { // 獲取請求引數 byte[] bytes = IOUtils.toByteArray(request.getInputStream()); String params = new String(bytes, req.getCharacterEncoding()); ThreadCache.setPostRequestParams(params); log.info("filer-post請求引數:[params={}]", params); } else { log.info("非post請求"); } chain.doFilter(request, response); } catch (Exception e) { log.error(e.getMessage(), e); } } @Override public void destroy() { } }
ThreadCache.java:
package com.test.test.filter; public class ThreadCache { // ThreadLocal裡只儲存了簡單的String物件,也可以自己定義物件,儲存更加複雜的引數 private static ThreadLocal<String> threadLocal = new ThreadLocal<String>(); public static String getPostRequestParams(){ return threadLocal.get(); } public static void setPostRequestParams(String postRequestParams){ threadLocal.set(postRequestParams); } public static void removePostRequestParams(){ threadLocal.remove(); } }
說一下WebFilter註解。
urlPatterns指的是過濾哪個路徑。跟在xml中配置是一樣的作用。簡單說一下,我這個過濾器的作用。目的就是可以以流的方式多次獲取請求引數。
正常requst.getInputStream只能獲取一次。但是我在過濾器中將他的引數放到threadlocal中,
這樣當前請求中就可以獲取到請求引數了。
另外說一下:
有兩種方式實現多次獲取request引數。
1.建立threadlocal類,將request或者request的引數放進去。
2.建立wrapper類,類似裝飾者模式,對request物件進行處理。getInputStream之後將流重新set進去。
推薦一篇多次獲取request引數的部落格:
2.Interceptor:
PlatformInterceptor.java:
package com.test.test.interceptor;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSONObject;
import com.test.test.config.ConfigProperties;
import com.test.test.constants.IMsgEnum;
import com.test.test.filter.ThreadCache;
import com.test.test.resp.BaseResp;
import com.test.test.security.SignCheck;
import com.test.test.utils.DESTools;
import com.test.test.utils.JsonUtil;
import com.test.test.utils.LogUtils;
import com.test.test.utils.NetworkUtil;
import com.test.test.utils.ReflectUtil;
/**
* ClassName: PlatformInterceptor date: 2015年12月30日 下午2:13:24 Description: 攔截器
*
* @author xiaozhan
* @version
* @since JDK 1.8
*/
@Component
public class PlatformInterceptor implements HandlerInterceptor {
private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);
@Autowired
private SignCheck signCheck;
@Autowired
private ConfigProperties configProperties;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
logger.info(LogUtils.getRequestLog(request));
// 獲取自定義註解
String allowOrigin = null;
String servletPath = request.getServletPath();
boolean isDeprecated = false;
BaseResp baseResp = new BaseResp();
ServletOutputStream out = response.getOutputStream();
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Deprecated deprecated = handlerMethod.getMethodAnnotation(Deprecated.class);
if (deprecated != null) {
isDeprecated = true;
}
}
String method = request.getMethod();
if (!method.equals(RequestMethod.POST.name())) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText());
logger.info("----- " + IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
String clientIp = NetworkUtil.getIpAddress(request);
logger.info("------ client Ip is ---》" + clientIp);
// 判斷是否是ip白名單
if (!signCheck.checkIpAddress(clientIp)) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText());
logger.info("----- " + IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
// 驗證簽名
String params = ThreadCache.getPostRequestParams();
logger.info("interceptor-post請求引數:[params={}]" + params);
Map<String, Object> map = ReflectUtil.getDecodeParamMap(params);
String sign = (String) map.get("sign");
if (map.containsKey("sign")) {
map.remove("sign");
}
// 簽名校驗
if (!SignCheck.checkSign(map, sign, configProperties.getPrivateKey())) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAM_SIGN_FALSE.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAM_SIGN_FALSE.getMsgText());
logger.info("----- " + IMsgEnum.PARAM_SIGN_FALSE.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
try {
if (isDeprecated) {
logger.error(LogUtils.getCommLog(String.format("該介面已停止使用,%s", servletPath)));
}
} catch (Exception e) {
baseResp.getMsg().setRstcode(IMsgEnum.PARAMETER_INVALID.getMsgCode());
baseResp.getMsg().setRsttext(IMsgEnum.PARAMETER_INVALID.getMsgText());
logger.info("----- " + IMsgEnum.PARAMETER_INVALID.getMsgText() + " -----");
out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
可以針對某些具體的請求進行攔截。我這裡沒做限制,所有的請求都走。如果想攔截 特定的請求,判斷一下request.getContextPath()是否包含某個路徑。(後續更新)
我這裡用到攔截器的作用是對回撥介面進行統一的驗證簽名。回撥介面都需要驗證簽名,而且簽名規則一樣,所以想拿到攔截器處理。
如果簽名或者ip地址不符合條件,直接就返回了。而具體的介面只要專注業務處理,不需要驗證簽名了。
分享一下用的工具類:ip和簽名校驗:
signCheck.java:
package com.test.test.security;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.test.test.config.ConfigProperties;
import com.test.test.interceptor.PlatformInterceptor;
import com.test.test.utils.Signature;
import org.springframework.stereotype.Service;
/**
* @author gmwang E-mail:
* @version 建立時間:2018年3月1日 上午10:35:47
* 類說明 :校驗簽名和ip
*/
@Service(value="signCheck")
public class SignCheck{
private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);
@Autowired
private ConfigProperties configProperties;
@Bean
public SignCheck getSignCheck(){
return new SignCheck();
}
/**
* 校驗簽名
* @Description:
* @author:
* @throws IllegalAccessException
* @time:2018年3月1日 上午10:38:09
*/
public static Boolean checkSign(Map params, String sign,String privateKey) throws IllegalAccessException {
if(StringUtils.isBlank(sign)) {
logger.info("*********************sign is null*********************");
return false;
}else {
String signAfter = Signature.getSign(params,privateKey);
System.out.println("sign:"+sign);
System.out.println("signAfter:"+signAfter);
if(!sign.equals(signAfter)) {
logger.info("*********************sign is not equal signAfter*********************");
return false;
}
}
return true;
}
/**
* 校驗ip
* @Description:
* @author:
* @throws IllegalAccessException
* @time:2018年3月1日 上午10:38:09
*/
public Boolean checkIpAddress(String ip) throws IllegalAccessException {
String ipWhite = configProperties.getRequestUrl();
System.out.println(ipWhite);
String[] ipWhiteArray = ipWhite.split(",");
List<String> ipWhiteList = Arrays.asList(ipWhiteArray);
if(!ipWhiteList.contains(ip)) {
logger.info("*********************ip is not in ipWhiteList*********************");
return false;
}
return true;
}
}
獲取ip地址工具類:NetworkUtil.java:
package com.test.test.utils;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.Logger;
/**
* 常用獲取客戶端資訊的工具
*
*/
public final class NetworkUtil {
/**
* Logger for this class
*/
private static Logger logger = Logger.getLogger(NetworkUtil.class);
/**
* 獲取請求主機IP地址,如果通過代理進來,則透過防火牆獲取真實IP地址;
*
* @param request
* @return
* @throws IOException
*/
public final static String getIpAddress(HttpServletRequest request) throws IOException {
// 獲取請求主機IP地址,如果通過代理進來,則透過防火牆獲取真實IP地址
String ip = request.getHeader("X-Forwarded-For");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip=" + ip);
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip=" + ip);
}
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if (logger.isInfoEnabled()) {
logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip=" + ip);
}
}
} else if (ip.length() > 15) {
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = (String) ips[index];
if (!("unknown".equalsIgnoreCase(strIp))) {
ip = strIp;
break;
}
}
}
return ip;
}
}
加密解密工具類:Signature.java:
package com.test.test.utils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
/**
* User:
* Date: 2015/8/26
* Time: 15:23
*/
public class Signature {
/**
* 簽名演算法
* @param o 要參與簽名的資料物件
* @return 簽名
* @throws IllegalAccessException
*規則:簽名,將篩選的引數按照第一個字元的鍵值ASCII碼遞增排序(字母升序排序),如果遇到相同字元則按照第二個字元的鍵值ASCII碼遞增排序,以此類推,形成key=value& * skey的字串MD5加密; (必填)
*/
public static String getSign(Object o) throws IllegalAccessException {
ArrayList<String> list = new ArrayList<String>();
Class cls = o.getClass();
Field[] fields = cls.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
if (f.get(o) != null && f.get(o) != "") {
list.add(f.getName() + "=" + f.get(o) + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
System.out.println(result);
result = MD5Util.MD5Encode(result).toUpperCase();
System.out.println(result);
return result;
}
public static String getSign(Map<String,Object> map,String privateKey){
ArrayList<String> list = new ArrayList<String>();
for(Map.Entry<String,Object> entry:map.entrySet()){
if(entry.getValue()!=""){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
sb.append(privateKey);
String result = sb.toString();
System.out.println(result);
result = MD5Util.MD5Encode(result).toUpperCase();
return result;
}
public static void main(String[] args) {
/*
* */
Map<String,Object> map=new HashMap();
map.put("uuid","PC0000000056");
String result= getSign(map,"aaaaa!aaa");
System.out.println(result);
map.put("sign", result);//sign
DESTools desTools = new DESTools();
String s = JSONObject.toJSONString(map);
System.out.println(s);
String param= desTools.getEncString(s);
String str= HttpUtil.doPost("http://localhost:8111/test/test", param);
System.out.println(str);
}
}
DESTools.java:
package com.test.test.utils;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;
public class DESTools {
public static DESTools instance;
public static DESTools getInstace()
{
if(instance == null)
{
instance = new DESTools();
}
return instance;
}
Key key;
/**
* 金鑰
*/
private static byte[] BOSS_SECRET_KEY = { 0x0b, 0x13, (byte) 0xe7,
(byte) 0xb2, 0x51, 0x0d, 0x75, (byte) 0xc2, 0x4e, (byte) 0xdd,
(byte) 0x4b, (byte) 0x51, 0x24, 0x36, (byte) 0xa8, (byte) 0x28,
0x0b, 0x13, (byte) 0xe2, (byte) 0xb2, 0x31, 0x0d, 0x75, (byte) 0xc1 };
public DESTools() {
setKey(BOSS_SECRET_KEY);
}
/**
* 根據引數生成KEY
*/
public void setKey(byte[] strKey) {
try {
DESKeySpec dks = new DESKeySpec(BOSS_SECRET_KEY);
SecretKeyFactory keyFactory;
keyFactory = SecretKeyFactory.getInstance("DES");
this.key = keyFactory.generateSecret(dks);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
}
}
/**
* 加密String明文輸入,String密文輸出
*/
public String getEncString(String strMing) {
byte[] byteMi = null;
byte[] byteMing = null;
String strMi = "";
Base64 base64en = new Base64();
try {
byteMing = strMing.getBytes("UTF8");
byteMi = this.getEncCode(byteMing);
strMi = base64en.encodeAsString(byteMi);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
} finally {
base64en = null;
byteMing = null;
byteMi = null;
}
return strMi;
}
/**
* 解密 以String密文輸入,String明文輸出
* @param strMi
* @return
*/
public String getDesString(String strMi) {
Base64 base64De = new Base64();
byte[] byteMing = null;
byte[] byteMi = null;
String strMing = "";
try {
byteMi = base64De.decode(strMi);
byteMing = this.getDesCode(byteMi);
strMing = new String(byteMing, "UTF8");
} catch (Exception e) {
throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);
} finally {
base64De = null;
byteMing = null;
byteMi = null;
}
return strMing;
}
/**
* 加密以byte[]明文輸入,byte[]密文輸出
* @param byteS
* @return
*/
private byte[] getEncCode(byte[] byteS) {
byte[] byteFina = null;
Cipher cipher;
try {
cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byteFina = cipher.doFinal(byteS);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
} finally {
cipher = null;
}
return byteFina;
}
/**
* 解密以byte[]密文輸入,以byte[]明文輸出
* @param byteD
* @return
*/
private byte[] getDesCode(byte[] byteD) {
Cipher cipher;
byte[] byteFina = null;
try {
cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byteFina = cipher.doFinal(byteD);
} catch (Exception e) {
throw new RuntimeException(
"Error initializing DESTOOLS class. Cause: " + e);
} finally {
cipher = null;
}
return byteFina;
}
}
獲取yml檔案的值:
ConfigProperties.java:
package com.test.test.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
@Component
public class ConfigProperties {
@Value("${test.test.privateKey}")
private String privateKey;
@Value("${test.test.requestUrl}")
private String requestUrl;
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getRequestUrl() {
return requestUrl;
}
public void setRequestUrl(String requestUrl) {
this.requestUrl = requestUrl;
}
}
yml檔案如圖:
2018-07-08 更新:
springboot 2.x 過濾器和攔截器 放行某個路徑(靜態資源):
package xxx.xxxx.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import xxx.xxxx.interceptor.PlatformInterceptor;
@EnableWebMvc
@Configuration
@Component
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
PlatformInterceptor passportInterceptor;
/**
* 處理攔截器 攔截路徑(暫時無效)
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多個攔截器組成一個攔截器鏈
registry.addInterceptor(passportInterceptor).addPathPatterns("/**")
.excludePathPatterns("notify","/static/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
/**
* 處理過濾器 靜態資源放行
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
/**
* 利用fastjson替換掉jackson,且解決中文亂碼問題
* @param converters
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
//處理中文亂碼問題
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
fastConverter.setFastJsonConfig(fastJsonConfig);
converters.add(fastConverter);
WebMvcConfigurer.super.configureMessageConverters(converters);
}
}